Skip to content

Commit 8d22448

Browse files
0xpeluche0xpelucheg1nt0ki
authored
Dex_Finance_Vault (DefiLlama#11037)
* wip dex_finance_vaults * WIP dex-finance * restore * batch fetch farm data * bugfix * feat:DexFinance-vault Adapter * revert using last logic sequential call * exclude gDEX * use addERC721Data instead of custom function * rm call tokenId from getVaultDatas since its call in addERC721Data --------- Co-authored-by: 0xpeluche <[email protected]> Co-authored-by: g1nt0ki <[email protected]>
1 parent eebc267 commit 8d22448

File tree

6 files changed

+207
-33
lines changed

6 files changed

+207
-33
lines changed

projects/agentfi/index.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ async function tvl(api) {
1919
const blasterswapv2 = dexBalancerAgents.map(i => [uniV2Lp.blasterswap, i.agentAddress])
2020
const ringv2 = dexBalancerAgents.map(i => [uniV2Lp.ring, i.agentAddress])
2121

22-
const blasterswapV3 = concentratedLiquidityAgents.map(i => [uniV3NftManager.blasterswap, i.agentAddress])
23-
const blasterswap2V3 = concentratedLiquidityAgents.map(i => [uniV3NftManager.blasterswap2, i.agentAddress])
24-
const thrusterV3 = concentratedLiquidityAgents.map(i => [uniV3NftManager.thruster, i.agentAddress])
25-
22+
const agents = concentratedLiquidityAgents.map(i => i.agentAddress)
23+
await sumTokens2({ api, owners: agents, uniV3ExtraConfig: { nftAddress: [uniV3NftManager.blasterswap, uniV3NftManager.blasterswap2, uniV3NftManager.thruster]}})
2624

2725
await getTvlForDexBalancer(dexBalancerAgents.map(i => i.agentAddress), api)
2826
await getTvlForLooperWithOrbit(looperAgentsAddresses, api)
@@ -33,11 +31,6 @@ async function tvl(api) {
3331
...blasterswapv2,
3432
...ringv2,
3533
],
36-
uniV3nftsAndOwners: [
37-
...blasterswapV3,
38-
...blasterswap2V3,
39-
...thrusterV3
40-
],
4134
resolveLP: true,
4235
api,
4336
})

projects/dexfinance-vault/abi.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
exports.abi = {
2+
factory: {
3+
vaultsLength: "function vaultsCount() view returns (uint256)",
4+
vaults: "function vaults(uint256 index) view returns (address)",
5+
farmCalculationConnector:
6+
"function farmCalculationConnector(address) view returns (address)",
7+
},
8+
vault: {
9+
liquidity: "function liquidity(address) view returns (uint256 liquidity_)",
10+
farmsLength: "uint256:farmsCount",
11+
farmConnector: "function farmConnector(address) view returns (address)",
12+
farms:
13+
"function farms(uint256 index) view returns (tuple(address beacon, uint256 percent, bytes data))",
14+
},
15+
farm: {
16+
stakingToken: "function stakingToken() view returns (address)",
17+
farm: "address:farm",
18+
type: "string:stakingTokenType",
19+
tokenId: "uint256:tokenId",
20+
stakingTokenLiquidity:
21+
"function stakingTokenLiquidity(uint256 tokenId_) view returns (uint256 liquidity_)",
22+
stakingTokenData:
23+
"function stakingTokenData() view returns ((string stakingTokenType, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, (uint256 sqrtPriceX96LowInit, uint256 sqrtPriceX96UpInit, uint256 sqrtPriceX96LowLimit, uint256 sqrtPriceX96UpLimit, uint256 sqrtPriceX96ApproxPricePercent, uint256 sqrtPriceX96ShiftPercentLow, uint256 sqrtPriceX96ShiftPercentUp, uint256 sqrtPriceX96DefaultShiftPercentLow, uint256 sqrtPriceX96DefaultShiftPercentUp) pricesData, (address tokenIn, address tokenOut)[] swapsToken0ToNative, (address tokenIn, address tokenOut)[] swapsToken1ToNative, (address tokenIn, address tokenOut)[] swapsNativeToToken0, (address tokenIn, address tokenOut)[] swapsNativeToToken1))",
24+
}
25+
};

projects/dexfinance-vault/index.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const { sumTokens2, addUniV3LikePosition } = require("../helper/unwrapLPs");
2+
const { abi } = require("./abi");
3+
4+
const CONFIG = {
5+
optimism: {
6+
factory: "0xd4f1a99212e5be72426bde45abadef66d7d6edf3",
7+
},
8+
fantom: {
9+
factory: "0x9b7e30644a9b37eebaa7158129b03f5a3088659d",
10+
},
11+
pulse: {
12+
factory: "0xac297968C97EF5686c79640960D106f65C307a37",
13+
USDEX_PLUS: "0xaA2C47a35C1298795B5271490971Ec4874C8e53d",
14+
},
15+
base: {
16+
factory: "0x714c94b9820d7d73e61510e4c18b91f995a895c1",
17+
},
18+
arbitrum: {
19+
factory: "0xe31fceaf93667365ce1e9edad3bed4a7dd0fc01a",
20+
USDEX_PLUS: "0x4117EC0A779448872d3820f37bA2060Ae0B7C34B",
21+
gDEX: "0x92a212d9f5eef0b262ac7d84aea64a0d0758b94f"
22+
},
23+
avax: {
24+
factory: "0x6b714e6296b8b977e1d5ecb595197649e10a3db1",
25+
},
26+
bsc: {
27+
factory: "0x3ace08b10b5c08a17d1c46277d65c81249e65f44",
28+
},
29+
// manta: {
30+
// factory: "0x714C94B9820D7D73e61510e4C18B91F995A895C1",
31+
// },
32+
};
33+
34+
const getVaults = async (api, factory) => {
35+
const vaults = await api.fetchList({ lengthAbi: abi.factory.vaultsLength, itemAbi: abi.factory.vaults, target: factory, });
36+
const farmsAll = await api.fetchList({ lengthAbi: abi.vault.farmsLength, itemAbi: abi.vault.farms, targets: vaults, groupedByInput: true })
37+
const items = []
38+
vaults.map((vault, i) => items.push(farmsAll[i].map((farm) => ({ vault, farm }))))
39+
return items.flat()
40+
};
41+
42+
const getVaultsConnectors = async (api, factory, vaultFarms) => {
43+
const connectorsCalls = vaultFarms.map(({ farm, vault }) => ({ params: farm.beacon, target: vault, }));
44+
const calculationConnectorCalls = vaultFarms.map(({ farm }) => farm.beacon);
45+
const connectors = await api.multiCall({ abi: abi.vault.farmConnector, calls: connectorsCalls })
46+
const calculationConnectors = await api.multiCall({ abi: abi.factory.farmCalculationConnector, calls: calculationConnectorCalls, target: factory })
47+
48+
vaultFarms.forEach((item, i) => {
49+
delete item.farm.data
50+
item.connector = connectors[i]
51+
item.calculationConnector = calculationConnectors[i]
52+
})
53+
}
54+
55+
const getVaultsDatas = async (api, vaultFarms) => {
56+
const calls = vaultFarms.map(({ connector }) => connector)
57+
const liquidityCalls = vaultFarms.map(({ calculationConnector, connector }) => ({ target: calculationConnector, params: [connector] }))
58+
59+
const [types, stakingTokens, liquidities] =
60+
await Promise.all([
61+
api.multiCall({ calls, abi: abi.farm.type }),
62+
api.multiCall({ calls, abi: abi.farm.stakingToken }),
63+
api.multiCall({ calls: liquidityCalls, abi: abi.vault.liquidity }),
64+
]);
65+
66+
vaultFarms.forEach((item, i) => {
67+
item.type = types[i]
68+
item.stakingToken = stakingTokens[i]
69+
item.liquidity = liquidities[i]
70+
})
71+
};
72+
73+
const groupBy = (array, keyFn) => {
74+
return array.reduce((acc, item) => {
75+
const key = keyFn(item);
76+
if (!acc[key]) {
77+
acc[key] = [];
78+
}
79+
acc[key].push(item);
80+
return acc;
81+
}, {});
82+
};
83+
84+
const lpv2Balances = async (api, farms) => {
85+
farms.forEach(({ stakingToken, liquidity }) => {
86+
api.add(stakingToken, liquidity);
87+
});
88+
};
89+
90+
async function addERC721Data(api, vaultFarms) {
91+
const positionIds = await api.multiCall({ abi: abi.farm.tokenId, calls: vaultFarms.map(i => i.connector) })
92+
const nftPositionMapping = {}
93+
vaultFarms.forEach((item, i) => {
94+
if (!+positionIds[i])
95+
return;
96+
97+
const nft = item.stakingToken.toLowerCase()
98+
if (!nftPositionMapping[nft]) nftPositionMapping[nft] = []
99+
nftPositionMapping[nft].push(positionIds[i])
100+
})
101+
for (const [nftAddress, positionIds] of Object.entries(nftPositionMapping))
102+
await sumTokens2({ api, uniV3ExtraConfig: { nftAddress, positionIds, } })
103+
}
104+
105+
const tvl = async (api) => {
106+
const { factory, USDEX_PLUS, gDEX } = CONFIG[api.chain];
107+
const vaultFarms = await getVaults(api, factory);
108+
await getVaultsConnectors(api, factory, vaultFarms);
109+
await getVaultsDatas(api, vaultFarms);
110+
const sortedFarms = groupBy(vaultFarms, ({ type }) => `${type}`);
111+
112+
const lpv2Farms = Object.keys(sortedFarms)
113+
.filter((key) => !key.includes("ERC721"))
114+
.flatMap((key) => sortedFarms[key]);
115+
116+
const lpv3Farms = Object.keys(sortedFarms)
117+
.filter((key) => key.includes("ERC721"))
118+
.flatMap((key) => sortedFarms[key]);
119+
120+
await Promise.all([
121+
lpv2Balances(api, lpv2Farms),
122+
addERC721Data(api, lpv3Farms)
123+
])
124+
125+
if (USDEX_PLUS) api.removeTokenBalance(USDEX_PLUS);
126+
if (gDEX) api.removeTokenBalance(gDEX);
127+
return sumTokens2({ api, resolveLP: true });
128+
};
129+
130+
Object.keys(CONFIG).forEach((chain) => {
131+
module.exports[chain] = { tvl, };
132+
})

projects/helper/tokenMapping.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ const fixBalancesTokens = {
6060
bfc: {
6161
'0x6906Ccda405926FC3f04240187dd4fAd5DF6d555': { coingeckoId: "bitcoin-usd-btcfi", decimals: 18, },
6262
},
63+
pulse: {
64+
'0x30fcb23a906493371b1721c8feb8815804808d74': { coingeckoId: 'savings-dai', decimals: 18 },
65+
}
6366
}
6467

6568
ibcChains.forEach(chain => fixBalancesTokens[chain] = { ...ibcMappings, ...(fixBalancesTokens[chain] || {}) })

projects/helper/unwrapLPs.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ async function sumLPWithOnlyOneTokenOtherThanKnown(balances, lpToken, owner, tok
193193

194194
const PANCAKE_NFT_ADDRESS = '0x46A15B0b27311cedF172AB29E4f4766fbE7F4364'
195195
async function unwrapUniswapV3NFTs({ balances = {}, nftsAndOwners = [], block, chain = 'ethereum', owner, nftAddress, owners, blacklistedTokens = [], whitelistedTokens = [], uniV3ExtraConfig = {} }) {
196+
nftAddress = nftAddress ?? uniV3ExtraConfig.nftAddress
197+
const commonConfig = { balances, owner, owners, chain, block, blacklistedTokens, whitelistedTokens, uniV3ExtraConfig, }
196198
// https://docs.uniswap.org/contracts/v3/reference/deployments
197199
if (!nftsAndOwners.length) {
198200
if (!nftAddress)
@@ -209,39 +211,51 @@ async function unwrapUniswapV3NFTs({ balances = {}, nftsAndOwners = [], block, c
209211
default: throw new Error('missing default uniswap nft address chain: ' + chain)
210212
}
211213

212-
if ((!owners || !owners.length) && owner)
213-
owners = [owner]
214-
owners = getUniqueAddresses(owners, chain)
215-
if (Array.isArray(nftAddress))
216-
nftsAndOwners = nftAddress.map(nft => owners.map(o => [nft, o])).flat()
217-
else
218-
nftsAndOwners = owners.map(o => [nftAddress, o])
219-
}
220-
await Promise.all(nftsAndOwners.map(([nftAddress, owner]) => unwrapUniswapV3NFT({ balances, owner, nftAddress, block, chain, blacklistedTokens, whitelistedTokens, uniV3ExtraConfig, })))
214+
if (Array.isArray(nftAddress)) {
215+
await Promise.all(nftAddress.map((addr) => unwrapUniswapV3NFT({ ...commonConfig, nftAddress: addr, })))
216+
} else
217+
await unwrapUniswapV3NFT({ ...commonConfig, nftAddress, })
218+
219+
} else
220+
await Promise.all(nftsAndOwners.map(([nftAddress, owner]) => unwrapUniswapV3NFT({ ...commonConfig, owner, nftAddress, })))
221221
return balances
222222
}
223223

224224
const factories = {}
225225

226226
const getFactoryKey = (chain, nftAddress) => `${chain}:${nftAddress}`.toLowerCase()
227227

228-
async function unwrapUniswapV3NFT({ balances, owner, nftAddress, block, chain = 'ethereum', blacklistedTokens = [], whitelistedTokens = [], uniV3ExtraConfig = {}, }) {
228+
async function unwrapUniswapV3NFT({ balances, owner, owners, nftAddress, block, chain = 'ethereum', blacklistedTokens = [], whitelistedTokens = [], uniV3ExtraConfig = {}, }) {
229229

230230
blacklistedTokens = getUniqueAddresses(blacklistedTokens, chain)
231231
whitelistedTokens = getUniqueAddresses(whitelistedTokens, chain)
232232
let nftIdFetcher = uniV3ExtraConfig.nftIdFetcher ?? nftAddress
233233

234-
const nftPositions = (await sdk.api.erc20.balanceOf({ target: nftIdFetcher, owner, block, chain })).output
235234
const factoryKey = getFactoryKey(chain, nftAddress)
236235
if (!factories[factoryKey]) factories[factoryKey] = sdk.api.abi.call({ target: nftAddress, abi: wildCreditABI.factory, block, chain })
237236
let factory = (await factories[factoryKey]).output
238237
if (factory.toLowerCase() === '0xa08ae3d3f4da51c22d3c041e468bdf4c61405aab') // thruster finance has a bug where they set the pool deployer instead of the factory
239238
factory = '0x71b08f13B3c3aF35aAdEb3949AFEb1ded1016127'
240239

241-
const positionIds = (await sdk.api.abi.multiCall({
242-
block, chain, abi: wildCreditABI.tokenOfOwnerByIndex, target: nftIdFetcher,
243-
calls: Array(Number(nftPositions)).fill(0).map((_, index) => ({ params: [owner, index] })),
244-
})).output.map(positionIdCall => positionIdCall.output)
240+
let positionIds = uniV3ExtraConfig.positionIds
241+
if (!positionIds) {
242+
if (!owners && owner) owners = [owner]
243+
owners = getUniqueAddresses(owners, chain)
244+
const { output: lengths } = await sdk.api.abi.multiCall({
245+
block, chain, abi: wildCreditABI.balanceOf,
246+
calls: owners.map((params) => ({ target: nftIdFetcher, params, })),
247+
})
248+
const positionIDCalls = []
249+
for (let i = 0; i < owners.length; i++) {
250+
const length = lengths[i].output
251+
positionIDCalls.push(...createIncrementArray(length).map(j => ({ params: [owners[i], j] })))
252+
}
253+
254+
positionIds = (await sdk.api.abi.multiCall({
255+
block, chain, abi: wildCreditABI.tokenOfOwnerByIndex, target: nftIdFetcher,
256+
calls: positionIDCalls,
257+
})).output.map(positionIdCall => positionIdCall.output)
258+
}
245259

246260
const positions = (await sdk.api.abi.multiCall({
247261
block, chain, abi: wildCreditABI.positions, target: nftAddress,
@@ -846,7 +860,11 @@ async function sumTokens2({
846860
fetchCoValentTokens = false,
847861
tokenConfig = {},
848862
sumChunkSize = undefined,
849-
uniV3ExtraConfig = {},
863+
uniV3ExtraConfig = {
864+
// positionIds
865+
// nftAddress
866+
// nftIdFetcher
867+
},
850868
resolveICHIVault = false,
851869
solidlyVeNfts = [],
852870
}) {

projects/thetanuts/index.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const ADDRESSES = require('../helper/coreAssets.json')
2-
const { sumTokensExport } = require('../helper/unwrapLPs')
2+
const { sumTokensExport, sumTokens2 } = require('../helper/unwrapLPs')
33

44
// Ethereum Vaults
55
const ethCallVault = '0x9014f8E90423766343Ed4fe41668563526dF6715'
@@ -240,11 +240,11 @@ const config = {
240240
[PTrsETH_26SEP24, aPTrsETH_26SEP24,],
241241
[PTweETH_26SEP24, aPTweETH_26SEP24,],
242242
],
243-
LLVOwners: [
244-
[univ3nft_arb, arbC_LLV,],
245-
[univ3nft_arb, arbP_LLV,],
246-
[univ3nft_arb, ethC_LLV,],
247-
[univ3nft_arb, ethP_LLV,],
243+
uniV3Owners: [
244+
arbC_LLV,
245+
arbP_LLV,
246+
ethC_LLV,
247+
ethP_LLV,
248248
]
249249
},
250250
fantom: {
@@ -310,8 +310,11 @@ const config = {
310310
}
311311

312312
Object.keys(config).forEach(chain => {
313-
const { tokensAndOwners, LLVOwners } = config[chain]
313+
const { tokensAndOwners, uniV3Owners } = config[chain]
314314
module.exports[chain] = {
315-
tvl: sumTokensExport({ tokensAndOwners, resolveUniV3 : LLVOwners != null && LLVOwners.length > 0 ? true : false, uniV3nftsAndOwners : LLVOwners })
315+
tvl: async (api) => {
316+
if (uniV3Owners) await sumTokens2({ api, owners: uniV3Owners, resolveUniV3: true})
317+
return sumTokens2({ api, tokensAndOwners})
318+
}
316319
}
317320
})

0 commit comments

Comments
 (0)