Skip to content

Commit

Permalink
Fix: Maple (#13607)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpeluche authored Mar 3, 2025
1 parent 0944885 commit 8e4bda0
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 163 deletions.
63 changes: 52 additions & 11 deletions projects/maple-rwa/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
const axios = require('axios');

const rwaPools = [
'0xfe119e9C24ab79F1bDd5dd884B86Ceea2eE75D92', // Cash Management
'0xe9d33286f0E37f517B1204aA6dA085564414996d', // AQRU
]
const query_url = "https://api.maple.finance/v2/graphql";

async function tvl(api) {
const tokens = await api.multiCall({ abi: 'address:asset', calls: rwaPools })
const bals = await api.multiCall({ abi: 'uint256:totalAssets', calls: rwaPools })
api.addTokens(tokens, bals)
const coingeckoMapping = {
'BTC': { name: 'bitcoin', decimals: 8 },
'ETH': { name: 'ethereum', decimals: 18 },
'SOL': { name: 'solana', decimals: 18 },
'INJ': { name: 'injective-protocol', decimals: 18 }
}

const query = `
query {
nativeLoans {
liquidityAsset {
symbol
decimals
}
createdAt
principalOwed
collateralAsset
collateralAssetAmount
}
}
`;

const getLoans = async (api) => {
const payload = {
query,
headers: { "Content-Type": "application/json" }
};

const { data } = await axios.post(query_url, payload);
return data.data.nativeLoans.filter(({ createdAt }) => createdAt < api.timestamp * 1000);
};

const processLoans = async (api, key) => {
const loans = await getLoans(api)
const isCollateral = key === "collateralValue";

loans.forEach(({ liquidityAsset: { symbol, decimals }, principalOwed, collateralAssetAmount, collateralAsset }) => {
const assetKey = isCollateral ? collateralAsset : symbol;
const balance = Number(isCollateral ? collateralAssetAmount : principalOwed);
const token = coingeckoMapping[assetKey]?.name;
const parseDecimals = coingeckoMapping[assetKey]?.decimals ?? decimals;
if (!token) return;
api.addCGToken(token, balance / 10 ** parseDecimals);
})
}


module.exports = {
doublecounted: true,
ethereum: { tvl, }
}
ethereum: {
tvl: async (api) => processLoans(api, "collateralValue"),
borrowed: async (api) => processLoans(api),
}
};
15 changes: 0 additions & 15 deletions projects/maple-syrup/index.js

This file was deleted.

8 changes: 0 additions & 8 deletions projects/maple/abi.json

This file was deleted.

191 changes: 62 additions & 129 deletions projects/maple/index.js
Original file line number Diff line number Diff line change
@@ -1,139 +1,72 @@
const ADDRESSES = require('../helper/coreAssets.json')
const sdk = require("@defillama/sdk");
const { sumTokens2 } = require("../helper/unwrapLPs");
const { sumTokens2: sumSolana } = require("../helper/solana");
const { staking, } = require("../helper/staking")
const { getConnection, } = require('../helper/solana')
const { PublicKey } = require('@solana/web3.js')
const { getLogs } = require('../helper/cache/getLogs')

const USDC = ADDRESSES.ethereum.USDC;

/*** Solana TVL Portions ***/
const POOL_DISCRIMINATOR = "35K4P9PCU";
const TVL_OFFSET = 257;
const TVL_DATA_SIZE = 8;
const PROGRAM_ID = "5D9yi4BKrxF8h65NkVE1raCCWFKUs5ngub2ECxhvfaZe";

let _tvl

function getTvl(borrowed = false) {
return async () => {
if (!_tvl) _tvl = getSolanaTVL()
const res = await _tvl
return borrowed ? res.borrowed : res.tvl
}
}

async function getSolanaTVL() {
const programId = new PublicKey(PROGRAM_ID);
const connection = getConnection();
const accounts = await connection.getProgramAccounts(programId, {
filters: [{
memcmp: {
offset: 0,
bytes: POOL_DISCRIMINATOR
const ADDRESSES = require('../helper/coreAssets.json');
const axios = require('axios');

const query_url = "https://api.maple.finance/v2/graphql";
const stSYRUP = "0xc7E8b36E0766D9B04c93De68A9D47dD11f260B45"

const query = `
query example($block: Block_height) {
poolV2S(block: $block) {
id
name
collateralValue
principalOut
tvl
assets
asset {
symbol
}
}]
});

let borrowed = 0;
let tvlValue = 0;
for (const account of accounts) {
const data = account.account.data.slice(TVL_OFFSET, TVL_OFFSET + TVL_DATA_SIZE)
const poolTvl = Number(data.readBigUint64LE())
borrowed += poolTvl
poolMeta {
state
asset
poolCollaterals {
addresses
assetAmount
}
}
}
}
const usdc = ADDRESSES.solana.USDC
const tempBalances = await sumSolana({ owners: accounts.map(a => a.pubkey.toString()), tokens: [ADDRESSES.solana.USDC] })
const usdValue = +(tempBalances['solana:'+usdc] ?? 0)
tvlValue += usdValue
borrowed -= usdValue
if (borrowed < 0) borrowed = 0
`;

return {
tvl: {
[USDC]: tvlValue.toFixed(0),
},
borrowed: {
[USDC]: borrowed.toFixed(0)
}
const getPools = async (block) => {
const payload = {
query,
variables: { block: { number: block - 10 } },
headers: { "Content-Type": "application/json" }
};
}

const pInfos = {}

async function getPoolInfo(block, api) {
if (!pInfos[block]) pInfos[block] = _getPoolInfo()
return pInfos[block]

async function _getPoolInfo() {
const loanFactory = '0x1551717ae4fdcb65ed028f7fb7aba39908f6a7a6'
const openTermLoanManagerFactory = '0x90b14505221a24039A2D11Ad5862339db97Cc160'

const logs = await getLogs({
api,
target: loanFactory,
topic: "InstanceDeployed(uint256,address,bytes)",
fromBlock: 16126995,
});
const logs2 = await getLogs({ // open term
api,
target: openTermLoanManagerFactory,
topic: "InstanceDeployed(uint256,address,bytes)",
fromBlock: 17372608,
});

let proxies = logs.map(s => "0x" + s.topics[2].slice(26, 66))
const proxiesOpenTerm = logs2.map(s => "0x" + s.topics[2].slice(26, 66))
proxies.push(...proxiesOpenTerm)
proxies = [...new Set(proxies.map(i => i.toLowerCase()))]
const managers = await api.multiCall({ abi: 'address:poolManager', calls: proxies })
const assets = await api.multiCall({ block, abi: abis.fundsAsset, calls: proxies, })
return { proxies, assets, managers }
}
}

async function ethTvl2(api) {
const block = api.block
const { managers, assets, } = await getPoolInfo(block, api)
const pools = await api.multiCall({
abi: abis.pool,
calls: managers,
const { data } = await axios.post(query_url, payload);
return data.data.poolV2S;
};

const processPools = async (api, key) => {
const block = await api.getBlock();
// This is the deployment block of the first poolV2
if (block < 16186377) return console.error('Error: Impossible to backfill - The queried block is earlier than the deployment block of poolsV2');
const pools = await getPools(block);

pools.forEach((pool) => {
const { id, name, asset: { symbol }, assets, collateralValue, principalOut, poolMeta } = pool
const token = ADDRESSES.ethereum[symbol] ?? null
if (!token) return;
const balance = key === "collateralValue" ? Number(collateralValue) + Number(assets) : Number(principalOut)
api.add(token, balance)
})
};

return sumTokens2({ block, tokensAndOwners: pools.map((o, i) => ([assets[i], o])) })
}

async function borrowed2(api) {
const balances = {}
const { proxies, assets, } = await getPoolInfo(api.block, api)
const principalOut = await api.multiCall({
abi: abis.principalOut,
calls: proxies,
})
principalOut.forEach((val, i) => sdk.util.sumSingleBalance(balances, assets[i], val))
return balances
const staking = async (api) => {
const START_BLOCK = 20735662
const block = await api.getBlock()
if (block < START_BLOCK) return;
return api.erc4626Sum({ calls: [stSYRUP], tokenAbi: 'address:asset', balanceAbi: 'uint256:totalAssets' })
}

module.exports = {
misrepresentedTokens: true,
timetravel: false,
ethereum: {
tvl: sdk.util.sumChainTvls([ethTvl2]),
staking: staking('0x4937a209d4cdbd3ecd48857277cfd4da4d82914c', '0x33349b282065b0284d756f0577fb39c158f935e6'),
borrowed: sdk.util.sumChainTvls([borrowed2]),
},
solana: {
tvl: getTvl(),
borrowed: getTvl(true),
},
methodology:
"We count liquidity by USDC deposited on the pools through PoolFactory contract",
}

const abis = {
fundsAsset: "address:fundsAsset",
principalOut: "uint128:principalOut",
pool: "address:pool",
}
hallmarks: [[1670976000, 'V2 Deployment']],
solana: { tvl: () => ({})},
ethereum: {
tvl: async (api) => processPools(api, "collateralValue"),
borrowed: async (api) => processPools(api),
staking
}
};

0 comments on commit 8e4bda0

Please sign in to comment.