@curvefi/llamalend-api 1.0.4 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/lint.yml +2 -2
- package/.github/workflows/publish.yml +11 -7
- package/eslint.config.mjs +87 -0
- package/lib/cache/index.js +18 -19
- package/lib/constants/L2Networks.js +1 -1
- package/lib/constants/aliases.js +28 -28
- package/lib/constants/coins.js +16 -16
- package/lib/constants/llammas.js +1 -1
- package/lib/constants/utils.js +8 -10
- package/lib/external-api.d.ts +8 -6
- package/lib/external-api.js +136 -397
- package/lib/index.d.ts +12 -11
- package/lib/index.js +49 -82
- package/lib/interfaces.d.ts +3 -18
- package/lib/lendMarkets/LendMarketTemplate.js +2438 -4440
- package/lib/lendMarkets/lendMarketConstructor.js +2 -2
- package/lib/llamalend.js +510 -722
- package/lib/mintMarkets/MintMarketTemplate.js +1469 -2799
- package/lib/mintMarkets/mintMarketConstructor.js +1 -1
- package/lib/st-crvUSD.js +172 -488
- package/lib/utils.d.ts +2 -2
- package/lib/utils.js +318 -548
- package/package.json +21 -16
- package/src/cache/index.ts +1 -0
- package/src/external-api.ts +27 -148
- package/src/index.ts +3 -1
- package/src/interfaces.ts +4 -19
- package/src/lendMarkets/LendMarketTemplate.ts +5 -5
- package/src/llamalend.ts +2 -2
- package/src/mintMarkets/MintMarketTemplate.ts +7 -7
- package/src/utils.ts +6 -6
- package/tsconfig.json +1 -1
- package/.eslintrc.json +0 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curvefi/llamalend-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "JavaScript library for Curve Lending",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"author": "Macket",
|
|
@@ -17,26 +17,31 @@
|
|
|
17
17
|
"build": "rm -rf lib && tsc -p tsconfig.build.json",
|
|
18
18
|
"lint": "eslint src --ext .ts"
|
|
19
19
|
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": "^22.0.0"
|
|
22
|
+
},
|
|
20
23
|
"type": "module",
|
|
21
24
|
"devDependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@types/
|
|
25
|
-
"@types/
|
|
26
|
-
"@
|
|
27
|
-
"@
|
|
25
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
26
|
+
"@eslint/js": "^9.23.0",
|
|
27
|
+
"@types/chai": "^5.2.1",
|
|
28
|
+
"@types/memoizee": "^0.4.12",
|
|
29
|
+
"@types/mocha": "^10.0.10",
|
|
30
|
+
"@types/node": "^22.13.13",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
|
32
|
+
"@typescript-eslint/parser": "^8.28.0",
|
|
28
33
|
"babel-eslint": "^10.1.0",
|
|
29
|
-
"chai": "^
|
|
30
|
-
"eslint": "^
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
+
"chai": "^5.2.0",
|
|
35
|
+
"eslint": "^9.23.0",
|
|
36
|
+
"globals": "^16.0.0",
|
|
37
|
+
"mocha": "^11.1.0",
|
|
38
|
+
"typescript": "^5.8.2",
|
|
39
|
+
"vue-eslint-parser": "^10.1.1"
|
|
34
40
|
},
|
|
35
41
|
"dependencies": {
|
|
36
|
-
"axios": "^0.21.1",
|
|
37
|
-
"bignumber.js": "^9.0.1",
|
|
38
42
|
"@curvefi/ethcall": "6.0.13",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
43
|
+
"bignumber.js": "^9.1.2",
|
|
44
|
+
"ethers": "^6.13.5",
|
|
45
|
+
"memoizee": "^0.4.17"
|
|
41
46
|
}
|
|
42
47
|
}
|
package/src/cache/index.ts
CHANGED
package/src/external-api.ts
CHANGED
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ethers } from "ethers";
|
|
1
|
+
import {ethers} from "ethers";
|
|
3
2
|
import memoize from "memoizee";
|
|
4
|
-
import
|
|
5
|
-
import { llamalend } from "./llamalend.js";
|
|
3
|
+
import {llamalend} from "./llamalend.js";
|
|
6
4
|
import {
|
|
5
|
+
IDict,
|
|
7
6
|
IExtendedPoolDataFromApi,
|
|
7
|
+
IMarketData,
|
|
8
8
|
INetworkName,
|
|
9
9
|
IPoolFactory,
|
|
10
|
-
I1inchSwapData,
|
|
11
|
-
IDict,
|
|
12
|
-
IMarketData,
|
|
13
10
|
IQuoteOdos,
|
|
11
|
+
IResponseApi,
|
|
14
12
|
} from "./interfaces";
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
const _getPoolsFromApi = memoize(
|
|
18
16
|
async (network: INetworkName, poolFactory: IPoolFactory ): Promise<IExtendedPoolDataFromApi> => {
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
return
|
|
17
|
+
const response = await fetch(`https://api.curve.fi/api/getPools/${network}/${poolFactory}`);
|
|
18
|
+
const { data } = await response.json() as { data?: IExtendedPoolDataFromApi, success: boolean };
|
|
19
|
+
return data ?? { poolData: [], tvl: 0, tvlAll: 0 };
|
|
22
20
|
},
|
|
23
21
|
{
|
|
24
22
|
promise: true,
|
|
@@ -117,14 +115,16 @@ export const _getUsdPricesFromApi = async (): Promise<IDict<number>> => {
|
|
|
117
115
|
return priceDictByMaxTvl
|
|
118
116
|
}
|
|
119
117
|
|
|
118
|
+
type UserCollateral = { total_deposit_precise: string, total_deposit_from_user: number, total_deposit_usd_value: number }
|
|
120
119
|
export const _getUserCollateral = memoize(
|
|
121
|
-
async (network: INetworkName, controller: string, user: string): Promise<
|
|
120
|
+
async (network: INetworkName, controller: string, user: string): Promise<UserCollateral> => {
|
|
122
121
|
const url = `https://prices.curve.fi/v1/lending/collateral_events/${network}/${controller}/${user}`;
|
|
123
|
-
const response = await
|
|
122
|
+
const response = await fetch(url);
|
|
123
|
+
const data = await response.json() as UserCollateral;
|
|
124
124
|
return {
|
|
125
|
-
total_deposit_precise:
|
|
126
|
-
total_deposit_from_user:
|
|
127
|
-
total_deposit_usd_value:
|
|
125
|
+
total_deposit_precise: data.total_deposit_precise,
|
|
126
|
+
total_deposit_from_user: data.total_deposit_from_user,
|
|
127
|
+
total_deposit_usd_value: data.total_deposit_usd_value,
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
{
|
|
@@ -136,8 +136,9 @@ export const _getUserCollateral = memoize(
|
|
|
136
136
|
export const _getUserCollateralCrvUsd = memoize(
|
|
137
137
|
async (network: INetworkName, controller: string, user: string): Promise<string> => {
|
|
138
138
|
const url = `https://prices.curve.fi/v1/crvusd/collateral_events/${network}/${controller}/${user}`;
|
|
139
|
-
const response = await
|
|
140
|
-
|
|
139
|
+
const response = await fetch(url);
|
|
140
|
+
const { total_deposit } = await response.json() as { total_deposit: string };
|
|
141
|
+
return total_deposit;
|
|
141
142
|
},
|
|
142
143
|
{
|
|
143
144
|
promise: true,
|
|
@@ -148,16 +149,12 @@ export const _getUserCollateralCrvUsd = memoize(
|
|
|
148
149
|
export const _getMarketsData = memoize(
|
|
149
150
|
async (network: INetworkName): Promise<IMarketData> => {
|
|
150
151
|
const url = `https://api.curve.fi/api/getLendingVaults/${network}/oneway`;
|
|
151
|
-
const response = await
|
|
152
|
-
url,
|
|
153
|
-
{
|
|
154
|
-
headers: {"accept": "application/json"},
|
|
155
|
-
validateStatus: () => true,
|
|
156
|
-
});
|
|
152
|
+
const response = await fetch(url, { headers: {"accept": "application/json"} });
|
|
157
153
|
if (response.status !== 200) {
|
|
158
154
|
throw Error(`Fetch error: ${response.status} ${response.statusText}`);
|
|
159
155
|
}
|
|
160
|
-
|
|
156
|
+
|
|
157
|
+
return (await response.json() as IResponseApi).data as IMarketData;
|
|
161
158
|
},
|
|
162
159
|
{
|
|
163
160
|
promise: true,
|
|
@@ -177,17 +174,12 @@ export const _getQuoteOdos = async (fromToken: string, toToken: string, _amount:
|
|
|
177
174
|
`&to_address=${ethers.getAddress(toToken)}&amount=${_amount.toString()}&slippage=${slippage}&pathVizImage=${pathVizImage}` +
|
|
178
175
|
`&caller_address=${ethers.getAddress(llamalend.constants.ALIASES.leverage_zap)}&blacklist=${ethers.getAddress(blacklist)}`;
|
|
179
176
|
|
|
180
|
-
const response = await
|
|
181
|
-
url,
|
|
182
|
-
{
|
|
183
|
-
headers: {"accept": "application/json"},
|
|
184
|
-
validateStatus: () => true,
|
|
185
|
-
});
|
|
177
|
+
const response = await fetch(url, { headers: {"accept": "application/json"} });
|
|
186
178
|
if (response.status !== 200) {
|
|
187
179
|
throw Error(`Odos quote error - ${response.status} ${response.statusText}`);
|
|
188
180
|
}
|
|
189
|
-
|
|
190
|
-
return { ...
|
|
181
|
+
const data = await response.json() as Omit<IQuoteOdos, 'slippage'>;
|
|
182
|
+
return { ...data, slippage };
|
|
191
183
|
}
|
|
192
184
|
|
|
193
185
|
export const _getExpectedOdos = async (fromToken: string, toToken: string, _amount: bigint, blacklist: string) => {
|
|
@@ -198,125 +190,12 @@ export const _assembleTxOdos = memoize(
|
|
|
198
190
|
async (pathId: string): Promise<string> => {
|
|
199
191
|
const url = `https://prices.curve.fi/odos/assemble?user=${ethers.getAddress(llamalend.constants.ALIASES.leverage_zap)}&path_id=${pathId}`;
|
|
200
192
|
|
|
201
|
-
const response = await
|
|
202
|
-
url,
|
|
203
|
-
{
|
|
204
|
-
headers: {'Content-Type': 'application/json'},
|
|
205
|
-
validateStatus: () => true,
|
|
206
|
-
});
|
|
193
|
+
const response = await fetch(url, { headers: {'Content-Type': 'application/json'} });
|
|
207
194
|
if (response.status !== 200) {
|
|
208
195
|
throw Error(`Odos assemble error - ${response.status} ${response.statusText}`);
|
|
209
196
|
}
|
|
210
|
-
|
|
211
|
-
return
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
promise: true,
|
|
215
|
-
maxAge: 10 * 1000, // 10s
|
|
216
|
-
}
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
export const _getSpotPriceOdos = memoize(
|
|
220
|
-
async (fromToken: string, toToken: string): Promise<string | undefined> => {
|
|
221
|
-
fromToken = ethers.getAddress(fromToken);
|
|
222
|
-
toToken = ethers.getAddress(toToken);
|
|
223
|
-
const url = `https://prices.curve.fi/odos/prices?chain_id=${llamalend.chainId}&tokens=${fromToken},${toToken}`;
|
|
224
|
-
const response = await axios.get(
|
|
225
|
-
url,
|
|
226
|
-
{
|
|
227
|
-
headers: {"accept": "application/json"},
|
|
228
|
-
validateStatus: () => true,
|
|
229
|
-
});
|
|
230
|
-
if (response.status !== 200) {
|
|
231
|
-
throw Error(`Odos spot prices error - ${response.status} ${response.statusText}`);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const pricesFromOdos = response.data.tokenPrices;
|
|
235
|
-
const pricesFromApi: IDict<string> = {};
|
|
236
|
-
for (const coin of [fromToken, toToken]) {
|
|
237
|
-
if (pricesFromOdos[coin] !== 0) continue;
|
|
238
|
-
const _pricesFromApi = await _getUsdPricesFromApi();
|
|
239
|
-
pricesFromApi[coin] = String(_pricesFromApi[coin] || 0);
|
|
240
|
-
}
|
|
241
|
-
const prices = { ...pricesFromOdos, ...pricesFromApi };
|
|
242
|
-
if (BigNumber(prices[fromToken]).eq(0) || BigNumber(prices[toToken]).eq( 0)) return undefined;
|
|
243
|
-
|
|
244
|
-
return (new BigNumber(prices[toToken])).div(prices[fromToken]).toString()
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
promise: true,
|
|
248
|
-
maxAge: 10 * 1000, // 10s
|
|
249
|
-
}
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
// --- 1INCH ---
|
|
253
|
-
|
|
254
|
-
export const _getExpected1inch = memoize(
|
|
255
|
-
async (fromToken: string, toToken: string, _amount: bigint): Promise<string> => {
|
|
256
|
-
if (_amount === BigInt(0)) return "0.0";
|
|
257
|
-
const url = `https://prices.curve.fi/1inch/swap/v6.0/${llamalend.chainId}/quote?src=${fromToken}&dst=${toToken}&amount=${_amount}&excludedProtocols=${llamalend.constants.EXCLUDED_PROTOCOLS_1INCH}&includeTokensInfo=true&includeProtocols=true`;
|
|
258
|
-
const response = await axios.get(
|
|
259
|
-
url,
|
|
260
|
-
{
|
|
261
|
-
headers: {"accept": "application/json"},
|
|
262
|
-
validateStatus: () => true,
|
|
263
|
-
});
|
|
264
|
-
if (response.status !== 200) {
|
|
265
|
-
throw Error(`1inch error: ${response.status} ${response.statusText}`);
|
|
266
|
-
}
|
|
267
|
-
return response.data.dstAmount;
|
|
268
|
-
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
promise: true,
|
|
272
|
-
maxAge: 10 * 1000, // 10s
|
|
273
|
-
}
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
export const _getSwapData1inch = memoize(
|
|
277
|
-
async (fromToken: string, toToken: string, _amount: bigint, slippage: number): Promise<I1inchSwapData> => {
|
|
278
|
-
if (_amount === BigInt(0)) throw Error("Amount must be > 0");
|
|
279
|
-
const url = `https://prices.curve.fi/1inch/swap/v6.0/${llamalend.chainId}/swap?src=${fromToken}&dst=${toToken}&amount=${_amount}&from_=${llamalend.constants.ALIASES.leverage_zap}&slippage=${slippage}&excludedProtocols=${llamalend.constants.EXCLUDED_PROTOCOLS_1INCH}&includeTokensInfo=true&includeProtocols=true&disableEstimate=true`;
|
|
280
|
-
const response = await axios.get(
|
|
281
|
-
url,
|
|
282
|
-
{
|
|
283
|
-
headers: {"accept": "application/json"},
|
|
284
|
-
validateStatus: () => true,
|
|
285
|
-
});
|
|
286
|
-
if (response.status !== 200) {
|
|
287
|
-
throw Error(`1inch error: ${response.status} ${response.statusText}`);
|
|
288
|
-
}
|
|
289
|
-
return response.data;
|
|
290
|
-
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
promise: true,
|
|
294
|
-
maxAge: 10 * 1000, // 10s
|
|
295
|
-
}
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
export const _getSpotPrice1inch = memoize(
|
|
299
|
-
async (fromToken: string, toToken: string): Promise<string | undefined> => {
|
|
300
|
-
const url = `https://prices.curve.fi/1inch/price/v1.1/${llamalend.chainId}?tokens=${fromToken},${toToken}¤cy=USD`;
|
|
301
|
-
const response = await axios.get(
|
|
302
|
-
url,
|
|
303
|
-
{
|
|
304
|
-
headers: {"accept": "application/json"},
|
|
305
|
-
validateStatus: () => true,
|
|
306
|
-
});
|
|
307
|
-
if (response.status !== 200) {
|
|
308
|
-
throw Error(`1inch error: ${response.status} ${response.statusText}`);
|
|
309
|
-
}
|
|
310
|
-
const pricesFromApi: IDict<string> = {};
|
|
311
|
-
for (const coin in response.data) {
|
|
312
|
-
if (response.data[coin] !== "0") continue;
|
|
313
|
-
const _pricesFromApi = await _getUsdPricesFromApi();
|
|
314
|
-
pricesFromApi[coin] = String(_pricesFromApi[coin] || 0);
|
|
315
|
-
}
|
|
316
|
-
const prices = { ...response.data, ...pricesFromApi };
|
|
317
|
-
if (prices[fromToken] === '0' || prices[toToken] === '0') return undefined;
|
|
318
|
-
|
|
319
|
-
return (new BigNumber(prices[toToken])).div(prices[fromToken]).toString()
|
|
197
|
+
const { transaction } = await response.json() as { transaction: { data: string } };
|
|
198
|
+
return transaction.data;
|
|
320
199
|
},
|
|
321
200
|
{
|
|
322
201
|
promise: true,
|
package/src/index.ts
CHANGED
|
@@ -83,7 +83,9 @@ const llamalend = {
|
|
|
83
83
|
getGasPriceFromL2,
|
|
84
84
|
getGasInfoForL2,
|
|
85
85
|
fetchStats: _llamalend.fetchStats,
|
|
86
|
-
|
|
86
|
+
mintMarkets: {
|
|
87
|
+
getMarketList :_llamalend.getMintMarketList,
|
|
88
|
+
},
|
|
87
89
|
lendMarkets: {
|
|
88
90
|
fetchMarkets: _llamalend.fetchLendMarkets,
|
|
89
91
|
getMarketList: _llamalend.getLendMarketList,
|
package/src/interfaces.ts
CHANGED
|
@@ -123,25 +123,6 @@ export interface IReward {
|
|
|
123
123
|
apy: number
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
export type T1inchRouteStep = {
|
|
127
|
-
name: string,
|
|
128
|
-
part: number,
|
|
129
|
-
fromTokenAddress: string,
|
|
130
|
-
toTokenAddress: string,
|
|
131
|
-
}[]
|
|
132
|
-
|
|
133
|
-
export interface I1inchRoute {
|
|
134
|
-
part: number,
|
|
135
|
-
hops: T1inchRouteStep[],
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export interface I1inchSwapData {
|
|
139
|
-
tx: { data: string },
|
|
140
|
-
dstAmount: string,
|
|
141
|
-
protocols: I1inchRoute[],
|
|
142
|
-
slippage: number,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
126
|
interface Rates {
|
|
146
127
|
borrowApr: number;
|
|
147
128
|
borrowApy: number;
|
|
@@ -235,3 +216,7 @@ export interface ILlamma {
|
|
|
235
216
|
A: number,
|
|
236
217
|
monetary_policy_abi: any
|
|
237
218
|
}
|
|
219
|
+
|
|
220
|
+
export interface IResponseApi {
|
|
221
|
+
data: any
|
|
222
|
+
}
|
|
@@ -700,7 +700,7 @@ export class LendMarketTemplate {
|
|
|
700
700
|
return [baseApyBN.times(100).toNumber(), boostedApyBN.times(100).toNumber()]
|
|
701
701
|
}
|
|
702
702
|
|
|
703
|
-
private async vaultCrvApr(
|
|
703
|
+
private async vaultCrvApr(): Promise<[baseApy: number, boostedApy: number]> {
|
|
704
704
|
if (this.vaultRewardsOnly()) throw Error(`${this.name} has Rewards-Only Gauge. Use stats.rewardsApy instead`);
|
|
705
705
|
|
|
706
706
|
// const isDisabledChain = [1313161554].includes(llamalend.chainId); // Disable Aurora
|
|
@@ -765,7 +765,7 @@ export class LendMarketTemplate {
|
|
|
765
765
|
return await this._vaultClaimCrv(false) as string;
|
|
766
766
|
}
|
|
767
767
|
|
|
768
|
-
private vaultRewardTokens = memoize(async (
|
|
768
|
+
private vaultRewardTokens = memoize(async (): Promise<{token: string, symbol: string, decimals: number}[]> => {
|
|
769
769
|
if (this.addresses.gauge === llamalend.constants.ZERO_ADDRESS) return []
|
|
770
770
|
|
|
771
771
|
// if (useApi) {
|
|
@@ -828,7 +828,7 @@ export class LendMarketTemplate {
|
|
|
828
828
|
// }
|
|
829
829
|
|
|
830
830
|
const apy: IReward[] = [];
|
|
831
|
-
const rewardTokens = await this.vaultRewardTokens(
|
|
831
|
+
const rewardTokens = await this.vaultRewardTokens();
|
|
832
832
|
for (const rewardToken of rewardTokens) {
|
|
833
833
|
const gaugeContract = llamalend.contracts[this.addresses.gauge].multicallContract;
|
|
834
834
|
const lpTokenContract = llamalend.contracts[this.addresses.vault].multicallContract;
|
|
@@ -1863,7 +1863,7 @@ export class LendMarketTemplate {
|
|
|
1863
1863
|
|
|
1864
1864
|
const _debt = parseUnits(debt);
|
|
1865
1865
|
const contract = llamalend.contracts[this.addresses.controller].contract;
|
|
1866
|
-
const [
|
|
1866
|
+
const [, n1] = await this.userBands(address);
|
|
1867
1867
|
const { borrowed } = await this.userState(address);
|
|
1868
1868
|
const n = (BN(borrowed).gt(0)) ? MAX_ACTIVE_BAND : n1 - 1; // In liquidation mode it doesn't matter if active band moves
|
|
1869
1869
|
const gas = await contract.repay.estimateGas(_debt, address, n, llamalend.constantOptions);
|
|
@@ -2859,7 +2859,7 @@ export class LendMarketTemplate {
|
|
|
2859
2859
|
try {
|
|
2860
2860
|
_n1 = await llamalend.contracts[this.addresses.controller].contract.calculate_debt_n1(_stateCollateral - _stateRepayCollateral, _stateDebt - _repayExpected, _N);
|
|
2861
2861
|
_n2 = _n1 + (_N - BigInt(1));
|
|
2862
|
-
} catch
|
|
2862
|
+
} catch {
|
|
2863
2863
|
console.log("Full repayment");
|
|
2864
2864
|
}
|
|
2865
2865
|
|
package/src/llamalend.ts
CHANGED
|
@@ -288,7 +288,7 @@ class Llamalend implements ILlamalend {
|
|
|
288
288
|
} else if (!providerSettings.url?.startsWith("https://rpc.gnosischain.com")) {
|
|
289
289
|
try {
|
|
290
290
|
this.signer = await this.provider.getSigner();
|
|
291
|
-
} catch
|
|
291
|
+
} catch {
|
|
292
292
|
this.signer = null;
|
|
293
293
|
}
|
|
294
294
|
}
|
|
@@ -335,7 +335,7 @@ class Llamalend implements ILlamalend {
|
|
|
335
335
|
if (this.signer) {
|
|
336
336
|
try {
|
|
337
337
|
this.signerAddress = await this.signer.getAddress();
|
|
338
|
-
} catch
|
|
338
|
+
} catch {
|
|
339
339
|
this.signer = null;
|
|
340
340
|
}
|
|
341
341
|
} else {
|
|
@@ -237,8 +237,8 @@ export class MintMarketTemplate {
|
|
|
237
237
|
.map((x) => formatUnits(x * BigInt(100)));
|
|
238
238
|
|
|
239
239
|
// (1+rate)**(365*86400)-1 ~= (e**(rate*365*86400))-1
|
|
240
|
-
const rate = String(((2.718281828459 ** (toBN(_rate).times(365).times(86400))
|
|
241
|
-
const future_rate = String(((2.718281828459 ** (toBN(_mp_rate).times(365).times(86400))
|
|
240
|
+
const rate = String(((2.718281828459 ** Number((toBN(_rate).times(365).times(86400)))) - 1) * 100);
|
|
241
|
+
const future_rate = String(((2.718281828459 ** Number((toBN(_mp_rate).times(365).times(86400)))) - 1) * 100);
|
|
242
242
|
|
|
243
243
|
return { fee, admin_fee, rate, future_rate, liquidation_discount, loan_discount }
|
|
244
244
|
},
|
|
@@ -273,7 +273,7 @@ export class MintMarketTemplate {
|
|
|
273
273
|
llammaContract.min_band(),
|
|
274
274
|
]
|
|
275
275
|
|
|
276
|
-
return (await llamalend.multicallProvider.all(calls1) as BigNumber[]).map((_b) => _b
|
|
276
|
+
return (await llamalend.multicallProvider.all(calls1) as BigNumber[]).map((_b) => Number(_b)) as [number, number];
|
|
277
277
|
},
|
|
278
278
|
{
|
|
279
279
|
promise: true,
|
|
@@ -281,7 +281,7 @@ export class MintMarketTemplate {
|
|
|
281
281
|
});
|
|
282
282
|
|
|
283
283
|
private statsActiveBand = memoize(async (): Promise<number> => {
|
|
284
|
-
return (await llamalend.contracts[this.address].contract.active_band_with_skip())
|
|
284
|
+
return Number((await llamalend.contracts[this.address].contract.active_band_with_skip()))
|
|
285
285
|
},
|
|
286
286
|
{
|
|
287
287
|
promise: true,
|
|
@@ -430,7 +430,7 @@ export class MintMarketTemplate {
|
|
|
430
430
|
address = _getAddress(address);
|
|
431
431
|
const _bands = await llamalend.contracts[this.address].contract.read_user_tick_numbers(address, llamalend.constantOptions) as BigNumber[];
|
|
432
432
|
|
|
433
|
-
return _bands.map((_t) => _t
|
|
433
|
+
return _bands.map((_t) => Number(_t)).reverse();
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
public async userRange(address = ""): Promise<number> {
|
|
@@ -1057,7 +1057,7 @@ export class MintMarketTemplate {
|
|
|
1057
1057
|
|
|
1058
1058
|
const _debt = parseUnits(debt);
|
|
1059
1059
|
const contract = llamalend.contracts[this.controller].contract;
|
|
1060
|
-
const [
|
|
1060
|
+
const [, n1] = await this.userBands(address);
|
|
1061
1061
|
const { stablecoin } = await this.userState(address);
|
|
1062
1062
|
const n = (BN(stablecoin).gt(0)) ? MAX_ACTIVE_BAND : n1 - 1; // In liquidation mode it doesn't matter if active band moves
|
|
1063
1063
|
const gas = await contract.repay.estimateGas(_debt, address, n, isEth(this.collateral), llamalend.constantOptions);
|
|
@@ -1693,7 +1693,7 @@ export class MintMarketTemplate {
|
|
|
1693
1693
|
try {
|
|
1694
1694
|
_n1 = await llamalend.contracts[this.deleverageZap].contract.calculate_debt_n1(_collateral, routeIdx, address);
|
|
1695
1695
|
_n2 = _n1 + BigInt(N - 1);
|
|
1696
|
-
} catch
|
|
1696
|
+
} catch {
|
|
1697
1697
|
console.log("Full repayment");
|
|
1698
1698
|
}
|
|
1699
1699
|
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
1
|
import { ethers, BigNumberish, Numeric } from "ethers";
|
|
3
2
|
import { Call } from "@curvefi/ethcall";
|
|
4
3
|
import BigNumber from 'bignumber.js';
|
|
@@ -359,10 +358,11 @@ export const _getUsdRate = async (assetId: string): Promise<number> => {
|
|
|
359
358
|
const url = [nativeTokenName, 'ethereum', 'bitcoin', 'link', 'curve-dao-token', 'stasis-eurs'].includes(assetId.toLowerCase()) ?
|
|
360
359
|
`https://api.coingecko.com/api/v3/simple/price?ids=${assetId}&vs_currencies=usd` :
|
|
361
360
|
`https://api.coingecko.com/api/v3/simple/token_price/${chainName}?contract_addresses=${assetId}&vs_currencies=usd`
|
|
362
|
-
const response = await
|
|
361
|
+
const response = await fetch(url);
|
|
362
|
+
const data = await response.json() as Record<string, { usd: number }>;
|
|
363
363
|
try {
|
|
364
|
-
_usdRatesCache[assetId] = {'rate':
|
|
365
|
-
} catch
|
|
364
|
+
_usdRatesCache[assetId] = {'rate': data[assetId]['usd'] ?? 0, 'time': Date.now()};
|
|
365
|
+
} catch { // TODO pay attention!
|
|
366
366
|
_usdRatesCache[assetId] = {'rate': 0, 'time': Date.now()};
|
|
367
367
|
}
|
|
368
368
|
}
|
|
@@ -457,8 +457,8 @@ export const getLsdApy = memoize(async(name: 'wstETH' | 'sfrxETH'): Promise<{
|
|
|
457
457
|
baseApy: number,
|
|
458
458
|
apyMean30d: number,
|
|
459
459
|
}> => {
|
|
460
|
-
const response = await
|
|
461
|
-
const {data} = response as { data: { chain: string, project: string, symbol: string, apy: number, apyBase: number, apyMean30d: number }[] };
|
|
460
|
+
const response = await fetch('https://yields.llama.fi/pools');
|
|
461
|
+
const {data} = await response.json() as { data: { chain: string, project: string, symbol: string, apy: number, apyBase: number, apyMean30d: number }[] };
|
|
462
462
|
|
|
463
463
|
const params = {
|
|
464
464
|
'wstETH': {
|
package/tsconfig.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/* Basic Options */
|
|
6
6
|
// "incremental": true, /* Enable incremental compilation */
|
|
7
|
-
"target": "
|
|
7
|
+
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
|
8
8
|
"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
|
9
9
|
"lib": ["ES2020"], /* Specify library files to be included in the compilation. */
|
|
10
10
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
package/.eslintrc.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"browser": true,
|
|
4
|
-
"es6": true
|
|
5
|
-
},
|
|
6
|
-
"extends": "eslint:recommended",
|
|
7
|
-
"parser": "vue-eslint-parser",
|
|
8
|
-
"parserOptions": {
|
|
9
|
-
"parser": "babel-eslint",
|
|
10
|
-
"sourceType": "module",
|
|
11
|
-
"allowImportExportEverywhere": false
|
|
12
|
-
},
|
|
13
|
-
"rules": {
|
|
14
|
-
"func-names": 0,
|
|
15
|
-
"no-nested-ternary": 0,
|
|
16
|
-
"max-len": 0,
|
|
17
|
-
"arrow-parens": ["error", "always"],
|
|
18
|
-
"no-underscore-dangle": 0,
|
|
19
|
-
"comma-dangle": ["error", {
|
|
20
|
-
"arrays": "always-multiline",
|
|
21
|
-
"objects": "always-multiline",
|
|
22
|
-
"imports": "always-multiline",
|
|
23
|
-
"exports": "always-multiline",
|
|
24
|
-
"functions": "never"
|
|
25
|
-
}],
|
|
26
|
-
"no-use-before-define": ["error", "nofunc"],
|
|
27
|
-
"no-empty": ["error", { "allowEmptyCatch": true }],
|
|
28
|
-
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
|
|
29
|
-
"indent": ["error", 4, { "flatTernaryExpressions": true, "SwitchCase": 1 }]
|
|
30
|
-
},
|
|
31
|
-
"overrides": [{
|
|
32
|
-
"files": ["**/*.ts"],
|
|
33
|
-
"parser": "@typescript-eslint/parser",
|
|
34
|
-
"plugins": ["@typescript-eslint"],
|
|
35
|
-
"extends": ["plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended"],
|
|
36
|
-
"rules": {
|
|
37
|
-
"@typescript-eslint/ban-ts-comment": "off"
|
|
38
|
-
}
|
|
39
|
-
}]
|
|
40
|
-
}
|