Skip to content

Commit f35eb4e

Browse files
authored
Merge pull request #2072 from tkspring-henry/feature/termmax
feat(termmax): Add additional Ethereum vault address
2 parents 6c7c73a + b188586 commit f35eb4e

File tree

1 file changed

+162
-1
lines changed

1 file changed

+162
-1
lines changed

src/adaptors/termmax/index.js

Lines changed: 162 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const VAULTS = {
1111
'0x984408C88a9B042BF3e2ddf921Cd1fAFB4b735D1',
1212
'0xDEB8a9C0546A01b7e5CeE8e44Fd0C8D8B96a1f6e',
1313
'0xdC4d99aB6c69943b4E17431357AbC5b54B4C2F56',
14+
'0xDAdeAcC03a59639C0ecE5ec4fF3BC0d9920A47eC',
1415
],
1516
},
1617
Arbitrum: {
@@ -33,6 +34,22 @@ const VAULTS = {
3334
},
3435
};
3536

37+
const VAULTS_V1 = {
38+
Ethereum: {
39+
alias: 'eth',
40+
chain: 'ethereum',
41+
chainId: 1,
42+
addresses: [
43+
'0x6aa8b4366d3BcFa51473677e9C961BAbADCec4e3',
44+
'0x09400f3a0b358eb408060f5a3272ed7e3b7664e0',
45+
'0x581AA6F8D7498E68E02D4fB6abFA7972c9d86286',
46+
'0xf4B8dCD6509B3Cb87DA9C491cB0728a2F3088d3F',
47+
'0xB3Bad0e31E08395eaaE76bE47985D074A4112F38',
48+
'0x0d6b6280915313e7322dcb4d71d511a93a75d98d',
49+
],
50+
},
51+
};
52+
3653
async function getMerklOpportunities() {
3754
const res = await axios.get(
3855
new URL('https://api.merkl.xyz/v4/opportunities?name=termmax')
@@ -147,7 +164,9 @@ async function apy() {
147164
.toNumber();
148165

149166
const url = new URL(
150-
`https://app.termmax.ts.finance/earn/${address.toLowerCase()}`
167+
`https://app.termmax.ts.finance/earn/${
168+
vaultData.alias
169+
}/${address.toLowerCase()}`
151170
);
152171
url.searchParams.set('chain', vaultData.alias);
153172

@@ -185,6 +204,148 @@ async function apy() {
185204
};
186205
promises.push(task());
187206
}
207+
for (const [chain, vaultData] of Object.entries(VAULTS_V1)) {
208+
const task = async () => {
209+
const calls = vaultData.addresses.map((address) => ({
210+
target: address,
211+
}));
212+
const [apy, asset, decimals, names, totalAssets] = await Promise.all([
213+
sdk.api.abi.multiCall({
214+
calls,
215+
abi: {
216+
name: 'apy',
217+
type: 'function',
218+
inputs: [],
219+
outputs: [{ type: 'uint256' }],
220+
},
221+
chain: vaultData.chain,
222+
}),
223+
sdk.api.abi.multiCall({
224+
calls,
225+
abi: {
226+
name: 'asset',
227+
type: 'function',
228+
inputs: [],
229+
outputs: [{ type: 'address' }],
230+
},
231+
chain: vaultData.chain,
232+
}),
233+
sdk.api.abi.multiCall({
234+
calls,
235+
abi: {
236+
name: 'decimals',
237+
type: 'function',
238+
inputs: [],
239+
outputs: [{ type: 'uint8' }],
240+
},
241+
chain: vaultData.chain,
242+
}),
243+
sdk.api.abi.multiCall({
244+
calls,
245+
abi: {
246+
name: 'name',
247+
type: 'function',
248+
inputs: [],
249+
outputs: [{ type: 'string' }],
250+
},
251+
chain: vaultData.chain,
252+
}),
253+
sdk.api.abi.multiCall({
254+
calls,
255+
abi: {
256+
name: 'totalAssets',
257+
type: 'function',
258+
inputs: [],
259+
outputs: [{ type: 'uint256' }],
260+
},
261+
chain: vaultData.chain,
262+
}),
263+
]);
264+
const assetNames = await sdk.api.abi.multiCall({
265+
calls: asset.output.map((o) => ({ target: o.output })),
266+
abi: {
267+
name: 'symbol',
268+
type: 'function',
269+
inputs: [],
270+
outputs: [{ type: 'string' }],
271+
},
272+
chain: vaultData.chain,
273+
});
274+
275+
const assetAddresses = new Set(asset.output.map((o) => o.output));
276+
const priceMap = new Map();
277+
{
278+
const promises = [];
279+
for (const assetAddress of assetAddresses) {
280+
const url = new URL(
281+
`https://coins.llama.fi/prices/current/${vaultData.chain}:${assetAddress}`
282+
);
283+
promises.push(
284+
axios.get(url).then((response) => {
285+
const priceKey = `${vaultData.chain}:${assetAddress}`;
286+
priceMap.set(
287+
assetAddress,
288+
response.data.coins[priceKey]?.price || 0
289+
);
290+
})
291+
);
292+
}
293+
await Promise.all(promises);
294+
}
295+
296+
for (let i = 0; i < vaultData.addresses.length; i++) {
297+
const address = vaultData.addresses[i];
298+
const assetAddress = asset.output[i].output;
299+
300+
const readableApy = new BigNumber(apy.output[i].output)
301+
.div(new BigNumber(10).pow(6))
302+
.toNumber();
303+
const tvlUsd = new BigNumber(totalAssets.output[i].output)
304+
.div(new BigNumber(10).pow(decimals.output[i].output))
305+
.times(priceMap.get(assetAddress) || 0)
306+
.toNumber();
307+
308+
const url = new URL(
309+
`https://app.termmax.ts.finance/earn/${
310+
vaultData.alias
311+
}/${address.toLowerCase()}`
312+
);
313+
url.searchParams.set('chain', vaultData.alias);
314+
315+
const pool = {
316+
pool: `${address}-${chain.toLowerCase()}`,
317+
chain,
318+
project: 'termmax',
319+
symbol: assetNames.output[i].output,
320+
tvlUsd,
321+
apyBase: readableApy,
322+
url: String(url),
323+
underlyingTokens: [assetAddress],
324+
poolMeta: names.output[i].output,
325+
};
326+
327+
const opportunity = opportunities.find(
328+
(o) =>
329+
o.chainId === vaultData.chainId &&
330+
o.identifier.toLowerCase() === address.toLowerCase()
331+
);
332+
if (opportunity) {
333+
pool.apyReward = opportunity.apr;
334+
335+
const breakdowns =
336+
(opportunity.rewardsRecord &&
337+
opportunity.rewardsRecord.breakdowns) ||
338+
[];
339+
pool.rewardTokens = breakdowns
340+
.map((b) => b.token.address)
341+
.filter((a) => a);
342+
}
343+
344+
pools.push(pool);
345+
}
346+
};
347+
promises.push(task());
348+
}
188349
await Promise.all(promises);
189350
return pools;
190351
}

0 commit comments

Comments
 (0)