Skip to content

Commit 4fb3a88

Browse files
Add impermax-v3 adapter (DefiLlama#14130)
1 parent 9f266cd commit 4fb3a88

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

projects/impermax-v3/index.js

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
const sdk = require('@defillama/sdk');
2+
const axios = require('axios');
3+
const { sumTokens2, addUniV3LikePosition } = require('../helper/unwrapLPs');
4+
const { nullAddress } = require('../helper/tokenMapping');
5+
6+
const config = {
7+
arbitrum: {
8+
factories: [
9+
'0x4FF3262Ba2983Ee8950d9d082f03277a58BF7eb1'
10+
],
11+
positionsApi: 'https://arbitrum-nftlp-uniswapv3.up.railway.app/positions'
12+
},
13+
base: {
14+
factories: [
15+
'0x175712cD666FbcfE8B69866a3088D7bf17a47685',
16+
],
17+
positionsApi: 'https://base-nftlp-uniswapv3.up.railway.app/positions'
18+
},
19+
};
20+
21+
const blacklistedPools = {
22+
arbitrum: [],
23+
base: []
24+
};
25+
26+
const abi = {
27+
// Borrowables
28+
underlying: "address:underlying",
29+
totalBalance: "uint256:totalBalance",
30+
totalBorrows: "function totalBorrows() view returns (uint112)",
31+
32+
// Lending Pools
33+
allLendingPoolsLength: "uint256:allLendingPoolsLength",
34+
allLendingPools: "function allLendingPools(uint256) view returns (address)",
35+
getLendingPool: "function getLendingPool(address) view returns (bool initialized, uint24 lendingPoolId, address collateral, address borrowable0, address borrowable1)",
36+
37+
// UniV3 pools
38+
slot0: "function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)",
39+
};
40+
41+
async function tvl(api) {
42+
const { factories, positionsApi } = config[api.chain];
43+
const blacklist = blacklistedPools[api.chain] || [];
44+
45+
// All NFTLP positions
46+
if (positionsApi) {
47+
await processUniV3Positions(api, positionsApi);
48+
}
49+
50+
await processBorrowables(api, factories, blacklist);
51+
52+
return api.getBalances();
53+
}
54+
55+
async function processUniV3Positions(api, positionsApiUrl) {
56+
console.log(`Fetching positions from API: ${positionsApiUrl}`);
57+
const response = await axios.get(positionsApiUrl);
58+
const positions = response.data;
59+
60+
if (!Array.isArray(positions) || positions.length === 0) {
61+
console.log(`No positions found with api ${positionsApiUrl}`);
62+
return;
63+
}
64+
65+
const poolsMap = {};
66+
positions.forEach(position => {
67+
if (!position.uniswapV3PoolId || position.liquidity === '0') return;
68+
69+
const poolId = position.uniswapV3PoolId.toLowerCase();
70+
if (!poolsMap[poolId]) {
71+
poolsMap[poolId] = {
72+
token0: position.token0Id,
73+
token1: position.token1Id,
74+
positions: []
75+
};
76+
}
77+
78+
poolsMap[poolId].positions.push({
79+
liquidity: position.liquidity,
80+
tickLower: position.tickLower,
81+
tickUpper: position.tickUpper
82+
});
83+
});
84+
85+
// Get tick of all unique pools
86+
const poolAddresses = Object.keys(poolsMap);
87+
const slot0 = await api.multiCall({
88+
abi: abi.slot0,
89+
calls: poolAddresses,
90+
permitFailure: true
91+
});
92+
93+
poolAddresses.forEach((poolAddress, i) => {
94+
const poolData = poolsMap[poolAddress];
95+
const slotData = slot0[i];
96+
97+
poolData.positions.forEach(position => {
98+
addUniV3LikePosition({
99+
api,
100+
token0: poolData.token0,
101+
token1: poolData.token1,
102+
tick: slotData.tick,
103+
liquidity: position.liquidity,
104+
tickLower: position.tickLower,
105+
tickUpper: position.tickUpper
106+
});
107+
});
108+
});
109+
}
110+
111+
// Same as impermax-v2 adapter
112+
async function processBorrowables(api, factories, blacklist) {
113+
const pools = [];
114+
115+
await Promise.all(factories.map(async (factory) => {
116+
const lendingPools = await api.fetchList({
117+
lengthAbi: abi.allLendingPoolsLength,
118+
itemAbi: abi.allLendingPools,
119+
target: factory
120+
});
121+
122+
const filteredPools = lendingPools.filter(pool => !blacklist.includes(pool.toLowerCase()));
123+
124+
const poolData = await api.multiCall({
125+
target: factory,
126+
abi: abi.getLendingPool,
127+
calls: filteredPools,
128+
permitFailure: true,
129+
});
130+
131+
const initializedPools = poolData.filter(pool => pool.initialized);
132+
initializedPools.forEach(i => {
133+
pools.push(i.borrowable0, i.borrowable1);
134+
});
135+
}));
136+
137+
const underlyings = await api.multiCall({
138+
abi: abi.underlying,
139+
calls: pools,
140+
permitFailure: true,
141+
});
142+
143+
const tokensAndOwners = pools
144+
.map((owner, i) => [underlyings[i], owner])
145+
.filter(([token]) => token !== nullAddress);
146+
147+
return sumTokens2({ api, tokensAndOwners });
148+
}
149+
150+
// Same as impermax-v2 adapter
151+
async function borrowed(api) {
152+
const { factories } = config[api.chain]
153+
const blacklist = blacklistedPools[api.chain]
154+
const balances = {}
155+
const borrowables = []
156+
await Promise.all(factories.map(async (factory) => {
157+
const lendingPools = await api.fetchList({ lengthAbi: abi.allLendingPoolsLength, itemAbi: abi.allLendingPools, target: factory })
158+
159+
const filteredPoolData = lendingPools.filter(pool => {
160+
return !blacklist.includes(pool.toLowerCase())
161+
})
162+
163+
const poolData = await api.multiCall({
164+
target: factory,
165+
abi: abi.getLendingPool,
166+
calls: filteredPoolData,
167+
permitFailure: true,
168+
})
169+
170+
poolData.forEach(i => {
171+
borrowables.push(i.borrowable0, i.borrowable1)
172+
})
173+
}))
174+
175+
const underlyings = await api.multiCall({
176+
abi: abi.underlying,
177+
calls: borrowables,
178+
permitFailure: true,
179+
})
180+
181+
const borrowed = await api.multiCall({
182+
abi: abi.totalBorrows,
183+
calls: borrowables,
184+
permitFailure: true,
185+
})
186+
187+
underlyings.forEach((v, i) => {
188+
sdk.util.sumSingleBalance(balances, v, borrowed[i], api.chain)
189+
})
190+
return balances
191+
}
192+
193+
194+
const module_exports = {};
195+
196+
Object.keys(config).forEach(chain => {
197+
module_exports[chain] = {
198+
tvl,
199+
borrowed
200+
};
201+
});
202+
203+
module.exports = module_exports;

0 commit comments

Comments
 (0)