Skip to content

Commit 9b9b270

Browse files
Adding Upshift Pools (#1693)
* Added Upshift Pools to Yield * Updated Calculation and Added Reward APY * Remove lock file * remove lock file --------- Co-authored-by: krishna7860 <[email protected]>
1 parent 5b15374 commit 9b9b270

File tree

2 files changed

+2100
-0
lines changed

2 files changed

+2100
-0
lines changed

src/adaptors/upshift/index.js

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
const lendingPoolABI = require('./lending-pool.json');
2+
const sdk = require('@defillama/sdk');
3+
const ethers = require('ethers');
4+
const utils = require('../utils');
5+
const axios = require('axios');
6+
7+
8+
const config = {
9+
ethereum: ["0xB7858b66dFA38b9Cb74d00421316116A7851c273", "0x80E1048eDE66ec4c364b4F22C8768fc657FF6A42", "0x18a5a3D575F34e5eBa92ac99B0976dBe26f9F869", "0xEBac5e50003d4B17Be422ff9775043cD61002f7f", "0xd684AF965b1c17D628ee0d77cae94259c41260F4", "0x5Fde59415625401278c4d41C6beFCe3790eb357f"],
10+
avax: ["0x3408b22d8895753C9A3e14e4222E981d4E9A599E"],
11+
base: ["0x4e2D90f0307A93b54ACA31dc606F93FE6b9132d2"]
12+
}
13+
const rewardConfig = {
14+
"0x3408b22d8895753C9A3e14e4222E981d4E9A599E": "0xAeAc5f82B140c0f7309f7E9Ec43019062A5e5BE2",
15+
}
16+
17+
const chainMapping = {
18+
ethereum: {
19+
chain: 'ethereum',
20+
chainId: '1',
21+
nativeToken: ethers.constants.AddressZero,
22+
decimals: 18,
23+
symbol: 'ETH',
24+
},
25+
avax: {
26+
chain: 'avax',
27+
chainId: '43114',
28+
nativeToken: ethers.constants.AddressZero,
29+
decimals: 18,
30+
symbol: 'AVAX',
31+
},
32+
base: {
33+
chain: 'base',
34+
chainId: '8453',
35+
nativeToken: ethers.constants.AddressZero,
36+
decimals: 18,
37+
symbol: 'ETH',
38+
}
39+
}
40+
41+
const APR_MULTIPLIER = 31536000;
42+
const projectName = 'upshift';
43+
44+
const getApy = async () => {
45+
const poolInfos = [];
46+
47+
const ethereumPools = await Promise.all(
48+
config.ethereum.map(async (pool) => {
49+
return await getPoolInfo(pool, 'ethereum');
50+
}),
51+
);
52+
53+
poolInfos.push(...ethereumPools);
54+
55+
const avaxPools = await Promise.all(
56+
config.avax.map(async (pool) => {
57+
return await getPoolInfo(pool, 'avax');
58+
}),
59+
);
60+
61+
poolInfos.push(...avaxPools);
62+
63+
const basePools = await Promise.all(
64+
config.base.map(async (pool) => {
65+
return await getPoolInfo(pool, 'base');
66+
}),
67+
);
68+
69+
poolInfos.push(...basePools);
70+
71+
return poolInfos;
72+
}
73+
74+
const getPoolActiveLoans = async (pool, chain) => {
75+
let loans = [];
76+
77+
let loanCount = (await sdk.api.abi.call({
78+
target: pool,
79+
abi: lendingPoolABI.find(abi => abi.name === 'getTotalLoansDeployed'),
80+
chain: chain,
81+
}))?.output;
82+
83+
const indexArray = [
84+
...Array(Number(loanCount)).keys(),
85+
];
86+
87+
loans = await Promise.all(
88+
indexArray.map(async (i) => {
89+
const loansDeployed = (await sdk.api.abi.call({
90+
target: pool,
91+
params: i,
92+
abi: lendingPoolABI.find(abi => abi.name === 'loansDeployed'),
93+
chain: chain,
94+
}))?.output;
95+
return loansDeployed;
96+
}),
97+
);
98+
99+
100+
const states = await Promise.all(
101+
loans.map(async (loan) => {
102+
const state = (await sdk.api.abi.call({
103+
target: loan,
104+
abi: 'function loanState() view returns (uint8)',
105+
chain: chain,
106+
}))?.output;
107+
return state;
108+
}),
109+
);
110+
111+
// filter loan if state is 4 (active)
112+
const activeLoans = loans.filter((loan, i) => states[i] === '4');
113+
return activeLoans;
114+
};
115+
116+
const getPoolInfo = async (pool, chain) => {
117+
118+
const symbol = (await sdk.api.abi.call({
119+
target: pool,
120+
abi: lendingPoolABI.find(abi => abi.name === 'symbol'),
121+
chain: chain,
122+
}))?.output;
123+
124+
const underlying_token = (await sdk.api.abi.call({
125+
target: pool,
126+
abi: lendingPoolABI.find(abi => abi.name === 'asset'),
127+
chain: chain,
128+
}))?.output;
129+
130+
const totalSupply = (await sdk.api.abi.call({
131+
target: pool,
132+
abi: lendingPoolABI.find(abi => abi.name === 'totalSupply'),
133+
chain: chain,
134+
}))?.output;
135+
136+
const totalAsset = (await sdk.api.abi.call({
137+
target: pool,
138+
abi: lendingPoolABI.find(abi => abi.name === 'totalAssets'),
139+
chain: chain,
140+
}))?.output;
141+
142+
const pool_decimals = (await sdk.api.abi.call({
143+
target: pool,
144+
abi: 'erc20:decimals',
145+
chain: chain,
146+
}))?.output;
147+
148+
const underlyingDecimals = (await sdk.api.abi.call({
149+
target: underlying_token,
150+
abi: 'erc20:decimals',
151+
chain: chain,
152+
}))?.output;
153+
154+
155+
const priceKey = `${utils.formatChain(chain)}:${underlying_token}`;
156+
const underlyingPrice = (await axios.get(`https://coins.llama.fi/prices/current/${priceKey}`)).data.coins[priceKey]?.price;
157+
158+
const tvlUsd = Number(ethers.utils.formatUnits(totalAsset, underlyingDecimals)) * underlyingPrice;
159+
160+
let aggregateApr = BigInt(0);
161+
162+
const loans = await getPoolActiveLoans(pool, chain);
163+
164+
const newLoans = (
165+
await Promise.all(
166+
loans?.map(async (loanAddress) => {
167+
const [_loanApr, _principalAmt, _collateral, _principalRepaid] =
168+
await Promise.all([
169+
sdk.api.abi.call({
170+
target: loanAddress,
171+
abi: 'function currentApr() view returns (uint256)',
172+
chain
173+
}),
174+
sdk.api.abi.call({
175+
target: loanAddress,
176+
abi: 'function principalAmount() view returns (uint256)',
177+
chain
178+
}),
179+
sdk.api.abi.call({
180+
target: loanAddress,
181+
abi: 'function collateralToken() view returns (address)',
182+
chain
183+
}),
184+
sdk.api.abi.call({
185+
target: loanAddress,
186+
abi: 'function principalRepaid() view returns (uint256)',
187+
chain
188+
}),
189+
sdk.api.abi.call({
190+
target: loanAddress,
191+
abi: 'function principalToken() view returns (address)',
192+
chain
193+
}),
194+
]);
195+
196+
let _principalDecimals = 18;
197+
if (_collateral.output !== ethers.constants.AddressZero) {
198+
const collateralDecimals = await sdk.api.abi.call({
199+
target: _collateral.output,
200+
abi: 'function decimals() view returns (uint8)',
201+
chain
202+
});
203+
_principalDecimals = collateralDecimals.output;
204+
}
205+
// handle aprs
206+
aggregateApr += _loanApr.output || BigInt(0);
207+
208+
209+
const loanApr = Number(_loanApr.output || 0) / 100;
210+
211+
const allocation =
212+
Number(ethers.utils.formatUnits(_principalAmt.output, _principalDecimals)) /
213+
Number(ethers.utils.formatUnits(totalSupply, _principalDecimals));
214+
215+
const newLoanObj = {
216+
address: loanAddress,
217+
apr: loanApr,
218+
allocation,
219+
};
220+
221+
return newLoanObj;
222+
}),
223+
)
224+
).filter((l) => l !== undefined);
225+
226+
const weightedAverage = newLoans.reduce(
227+
(acc, { apr, allocation }) => acc + apr * allocation,
228+
0,
229+
);
230+
231+
if (rewardConfig[pool]) {
232+
const rewardDistributor = rewardConfig[pool];
233+
234+
const rewardToken = [chainMapping[chain].nativeToken];
235+
236+
const totalStaked = await sdk.api.abi.call({
237+
target: rewardDistributor,
238+
abi: 'function totalStaked() view returns (uint256)',
239+
chain
240+
});
241+
const rewardsPerSecond = await sdk.api.abi.call({
242+
target: rewardDistributor,
243+
abi: 'function rewardsPerSecond() view returns (uint256)',
244+
chain
245+
});
246+
247+
const priceKey = `${utils.formatChain(chain)}:${rewardToken[0]}`;
248+
const rewardTokenPrice = (await axios.get(`https://coins.llama.fi/prices/current/${priceKey}`)).data.coins[priceKey]?.price;
249+
250+
const rewardAPR =
251+
((Number(ethers.utils.formatUnits(rewardsPerSecond.output, chainMapping[chain].decimals)) *
252+
APR_MULTIPLIER *
253+
rewardTokenPrice) /
254+
(ethers.utils.formatUnits(totalStaked.output, pool_decimals) * Number(1))) *
255+
100;
256+
257+
return {
258+
pool: `${pool}-${utils.formatChain(chain)}`,
259+
chain: utils.formatChain(chain),
260+
project: projectName,
261+
symbol: symbol,
262+
tvlUsd: tvlUsd,
263+
apyBase: weightedAverage,
264+
apyReward: rewardAPR,
265+
rewardTokens: rewardToken,
266+
underlyingTokens: [underlying_token],
267+
}
268+
}
269+
270+
return {
271+
pool: `${pool}-${utils.formatChain(chain)}`,
272+
chain: utils.formatChain(chain),
273+
project: projectName,
274+
symbol: symbol,
275+
tvlUsd: tvlUsd,
276+
apyBase: weightedAverage,
277+
underlyingTokens: [underlying_token],
278+
}
279+
};
280+
281+
module.exports = {
282+
timetravel: false,
283+
apy: getApy,
284+
url: 'https://www.upshift.finance/'
285+
};

0 commit comments

Comments
 (0)