@strkfarm/sdk 1.1.69 → 2.0.0-dev.1
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/dist/cli.js +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.browser.global.js +66861 -59746
- package/dist/index.browser.mjs +24970 -18579
- package/dist/index.d.ts +1969 -776
- package/dist/index.js +25259 -18845
- package/dist/index.mjs +25464 -19090
- package/package.json +80 -76
- package/src/data/extended-deposit.abi.json +3613 -0
- package/src/data/universal-vault.abi.json +135 -20
- package/src/dataTypes/address.ts +8 -1
- package/src/global.ts +240 -193
- package/src/interfaces/common.tsx +26 -2
- package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
- package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
- package/src/modules/avnu.ts +17 -4
- package/src/modules/ekubo-quoter.ts +99 -11
- package/src/modules/erc20.ts +67 -21
- package/src/modules/harvests.ts +16 -29
- package/src/modules/index.ts +5 -1
- package/src/modules/lst-apr.ts +36 -0
- package/src/modules/midas.ts +159 -0
- package/src/modules/pricer-from-api.ts +2 -2
- package/src/modules/pricer.ts +3 -38
- package/src/modules/token-market-data.ts +202 -0
- package/src/node/deployer.ts +1 -36
- package/src/strategies/autoCompounderStrk.ts +1 -1
- package/src/strategies/base-strategy.ts +20 -3
- package/src/strategies/ekubo-cl-vault.tsx +123 -306
- package/src/strategies/index.ts +4 -1
- package/src/strategies/svk-strategy.ts +247 -0
- package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +418 -0
- package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
- package/src/strategies/universal-adapters/common-adapter.ts +98 -77
- package/src/strategies/universal-adapters/extended-adapter.ts +544 -0
- package/src/strategies/universal-adapters/index.ts +5 -1
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
- package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
- package/src/strategies/universal-strategy.tsx +1098 -1180
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +28 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +48 -0
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +374 -0
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +992 -0
- package/src/strategies/vesu-rebalance.tsx +16 -19
- package/src/utils/health-factor-math.ts +11 -5
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseAdapter,
|
|
3
|
+
DepositParams,
|
|
4
|
+
WithdrawParams,
|
|
5
|
+
BaseAdapterConfig,
|
|
6
|
+
} from "./baseAdapter";
|
|
7
|
+
import { SIMPLE_SANITIZER_V2, toBigInt } from "./adapter-utils";
|
|
8
|
+
import { Protocols } from "@/interfaces";
|
|
9
|
+
import { MAX_DELAY } from "../vesu-extended-strategy/utils/constants";
|
|
10
|
+
import { SupportedPosition } from "./baseAdapter";
|
|
11
|
+
import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
|
|
12
|
+
import { Web3Number } from "@/dataTypes";
|
|
13
|
+
import { PositionInfo } from "./baseAdapter";
|
|
14
|
+
import { ManageCall } from "./baseAdapter";
|
|
15
|
+
import { ContractAddr } from "@/dataTypes";
|
|
16
|
+
import { TokenInfo } from "@/interfaces";
|
|
17
|
+
import { AVNU_EXCHANGE } from "./adapter-utils";
|
|
18
|
+
import { MAX_RETRIES } from "../vesu-extended-strategy/utils/constants";
|
|
19
|
+
import { Quote } from "@avnu/avnu-sdk";
|
|
20
|
+
import { hash, uint256 } from "starknet";
|
|
21
|
+
import { AvnuWrapper } from "@/modules/avnu";
|
|
22
|
+
import axios from "axios";
|
|
23
|
+
import { AVNU_MIDDLEWARE, SIMPLE_SANITIZER } from "./adapter-utils";
|
|
24
|
+
import { returnFormattedAmount } from "../vesu-extended-strategy/utils/helper";
|
|
25
|
+
import { logger } from "@/utils";
|
|
26
|
+
export interface AvnuAdapterConfig extends BaseAdapterConfig {
|
|
27
|
+
baseUrl: string;
|
|
28
|
+
avnuContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
|
|
29
|
+
slippage: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
33
|
+
readonly config: AvnuAdapterConfig;
|
|
34
|
+
protected avnuWrapper: AvnuWrapper;
|
|
35
|
+
|
|
36
|
+
constructor(config: AvnuAdapterConfig) {
|
|
37
|
+
super(config, AvnuAdapter.name, Protocols.AVNU);
|
|
38
|
+
this.config = config as AvnuAdapterConfig;
|
|
39
|
+
this.avnuWrapper = new AvnuWrapper();
|
|
40
|
+
}
|
|
41
|
+
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
42
|
+
protected async getAPY(
|
|
43
|
+
supportedPosition: SupportedPosition
|
|
44
|
+
): Promise<PositionAPY> {
|
|
45
|
+
return Promise.resolve({ apy: 0, type: APYType.BASE });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected async getPosition(
|
|
49
|
+
supportedPosition: SupportedPosition
|
|
50
|
+
): Promise<PositionAmount> {
|
|
51
|
+
return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "" });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
55
|
+
return Promise.resolve({
|
|
56
|
+
tokenInfo: this.config.baseToken,
|
|
57
|
+
amount: new Web3Number(0, 0),
|
|
58
|
+
usdValue: 0,
|
|
59
|
+
apy: { apy: 0, type: APYType.BASE },
|
|
60
|
+
protocol: Protocols.AVNU,
|
|
61
|
+
remarks: "",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async maxWithdraw(): Promise<PositionInfo> {
|
|
66
|
+
return Promise.resolve({
|
|
67
|
+
tokenInfo: this.config.baseToken,
|
|
68
|
+
amount: new Web3Number(0, 0),
|
|
69
|
+
usdValue: 0,
|
|
70
|
+
apy: { apy: 0, type: APYType.BASE },
|
|
71
|
+
protocol: Protocols.AVNU,
|
|
72
|
+
remarks: "",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected _getDepositLeaf(): {
|
|
77
|
+
// considering deposit is converting usdc to wbtc
|
|
78
|
+
target: ContractAddr;
|
|
79
|
+
method: string;
|
|
80
|
+
packedArguments: bigint[];
|
|
81
|
+
sanitizer: ContractAddr;
|
|
82
|
+
id: string;
|
|
83
|
+
}[] {
|
|
84
|
+
const vaultAllocator = ContractAddr.from(
|
|
85
|
+
this.config.vaultAllocator.address
|
|
86
|
+
);
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
target: this.config.supportedPositions[0].asset.address,
|
|
90
|
+
method: "approve",
|
|
91
|
+
packedArguments: [
|
|
92
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
93
|
+
],
|
|
94
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
95
|
+
id: `approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
target: AVNU_EXCHANGE,
|
|
99
|
+
method: "multi_route_swap",
|
|
100
|
+
packedArguments: [
|
|
101
|
+
this.config.supportedPositions[0].asset.address.toBigInt(), //usdc
|
|
102
|
+
this.config.supportedPositions[1].asset.address.toBigInt(), //wbtc
|
|
103
|
+
vaultAllocator.toBigInt(),
|
|
104
|
+
],
|
|
105
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
106
|
+
id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
protected _getWithdrawLeaf(): {
|
|
112
|
+
target: ContractAddr;
|
|
113
|
+
method: string;
|
|
114
|
+
packedArguments: bigint[];
|
|
115
|
+
sanitizer: ContractAddr;
|
|
116
|
+
id: string;
|
|
117
|
+
}[] {
|
|
118
|
+
const vaultAllocator = ContractAddr.from(
|
|
119
|
+
this.config.vaultAllocator.address
|
|
120
|
+
);
|
|
121
|
+
const toToken = this.config.supportedPositions[0].asset;
|
|
122
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
123
|
+
return [
|
|
124
|
+
{
|
|
125
|
+
target: fromToken.address,
|
|
126
|
+
method: "approve",
|
|
127
|
+
packedArguments: [
|
|
128
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
129
|
+
],
|
|
130
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
131
|
+
id: `approve_${fromToken.symbol}`,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
target: AVNU_EXCHANGE,
|
|
135
|
+
method: "multi_route_swap",
|
|
136
|
+
packedArguments: [
|
|
137
|
+
fromToken.address.toBigInt(), //wbtc
|
|
138
|
+
fromToken.address.toBigInt(), //usdc
|
|
139
|
+
vaultAllocator.toBigInt(),
|
|
140
|
+
],
|
|
141
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
142
|
+
id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`,
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
protected _getLegacySwapLeaf(): {
|
|
148
|
+
target: ContractAddr;
|
|
149
|
+
method: string;
|
|
150
|
+
packedArguments: bigint[];
|
|
151
|
+
sanitizer: ContractAddr;
|
|
152
|
+
id: string;
|
|
153
|
+
}[] {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
|
|
158
|
+
try {
|
|
159
|
+
console.log("params.amount", params.amount);
|
|
160
|
+
const fromToken = this.config.supportedPositions[0].asset;
|
|
161
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
162
|
+
const vaultAllocator = ContractAddr.from(
|
|
163
|
+
this.config.vaultAllocator.address
|
|
164
|
+
);
|
|
165
|
+
console.log("vaultAllocator", vaultAllocator);
|
|
166
|
+
const quote = await this.getQuotesAvnu(
|
|
167
|
+
fromToken.address.toString(),
|
|
168
|
+
toToken.address.toString(),
|
|
169
|
+
params.amount.toNumber(),
|
|
170
|
+
vaultAllocator.address.toString(),
|
|
171
|
+
toToken.decimals,
|
|
172
|
+
true
|
|
173
|
+
)
|
|
174
|
+
if (!quote) {
|
|
175
|
+
logger.error("error getting quote from avnu");
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
179
|
+
quote,
|
|
180
|
+
vaultAllocator.address
|
|
181
|
+
);
|
|
182
|
+
const swapCallData = getCalldata[0];
|
|
183
|
+
// const approveCallData = getCalldata[0];
|
|
184
|
+
const amount = uint256.bnToUint256(quote.sellAmountInUsd*10**7)
|
|
185
|
+
return [
|
|
186
|
+
{
|
|
187
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
188
|
+
call: {
|
|
189
|
+
contractAddress: fromToken.address,
|
|
190
|
+
selector: hash.getSelectorFromName("approve"),
|
|
191
|
+
calldata:[
|
|
192
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
193
|
+
toBigInt(amount.low.toString()), // amount low
|
|
194
|
+
toBigInt(amount.high.toString()), // amount high
|
|
195
|
+
] ,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
200
|
+
call: {
|
|
201
|
+
contractAddress: AVNU_EXCHANGE,
|
|
202
|
+
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
203
|
+
calldata: swapCallData,
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
} catch (error) {
|
|
208
|
+
logger.error(`Error getting Avnu quote: ${error}`);
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
//Swap wbtc to usdc
|
|
214
|
+
async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
|
|
215
|
+
try {
|
|
216
|
+
const toToken = this.config.supportedPositions[0].asset;
|
|
217
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
218
|
+
const vaultAllocator = ContractAddr.from(
|
|
219
|
+
this.config.vaultAllocator.address
|
|
220
|
+
);
|
|
221
|
+
console.log("params.amount", params.amount);
|
|
222
|
+
const quote = await this.getQuotesAvnu(
|
|
223
|
+
fromToken.address.toString(),
|
|
224
|
+
toToken.address.toString(),
|
|
225
|
+
params.amount.toNumber(),
|
|
226
|
+
vaultAllocator.address.toString(),
|
|
227
|
+
fromToken.decimals,
|
|
228
|
+
false
|
|
229
|
+
);
|
|
230
|
+
if (!quote) {
|
|
231
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
235
|
+
quote,
|
|
236
|
+
vaultAllocator.address
|
|
237
|
+
);
|
|
238
|
+
const swapCallData = getCalldata[0];
|
|
239
|
+
const amount = uint256.bnToUint256(params.amount.toWei())
|
|
240
|
+
console.log("amount", amount);
|
|
241
|
+
console.log("swapCallData", swapCallData);
|
|
242
|
+
return [
|
|
243
|
+
{
|
|
244
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
245
|
+
call: {
|
|
246
|
+
contractAddress:fromToken.address,
|
|
247
|
+
selector: hash.getSelectorFromName("approve"),
|
|
248
|
+
calldata: [
|
|
249
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
250
|
+
toBigInt(amount.low.toString()), // amount low
|
|
251
|
+
toBigInt(amount.high.toString()), // amount high
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
257
|
+
call: {
|
|
258
|
+
contractAddress: AVNU_EXCHANGE,
|
|
259
|
+
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
260
|
+
calldata: swapCallData,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
];
|
|
264
|
+
} catch (error) {
|
|
265
|
+
logger.error(`Error getting Avnu quote: ${error}`);
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async getSwapCallData(quote: Quote): Promise<bigint[][]> {
|
|
271
|
+
return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async getHealthFactor(): Promise<number> {
|
|
275
|
+
return Promise.resolve(1);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async fetchQuoteWithRetry(
|
|
279
|
+
params: Record<string, any>,
|
|
280
|
+
retries: number = 5
|
|
281
|
+
): Promise<any> {
|
|
282
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
283
|
+
try {
|
|
284
|
+
const response = await axios.get(this.config.baseUrl, { params });
|
|
285
|
+
if (response.data && response.data.length > 0) {
|
|
286
|
+
return response;
|
|
287
|
+
}
|
|
288
|
+
throw new Error("Empty response data");
|
|
289
|
+
} catch (err) {
|
|
290
|
+
logger.error(`Error fetching quote with retry: ${err}`);
|
|
291
|
+
if (attempt === retries - 1) {
|
|
292
|
+
throw err;
|
|
293
|
+
}
|
|
294
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
throw new Error("Failed to fetch quote after retries");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async getQuotesAvnu (
|
|
301
|
+
from_token_address: string,
|
|
302
|
+
to_token_address: string,
|
|
303
|
+
amount: number, //amount in btc units
|
|
304
|
+
takerAddress: string,
|
|
305
|
+
toTokenDecimals: number,
|
|
306
|
+
usdcToBtc: boolean,
|
|
307
|
+
maxIterations: number = 5,
|
|
308
|
+
tolerance: number = 10000
|
|
309
|
+
): Promise<Quote | null>{
|
|
310
|
+
try {
|
|
311
|
+
const fromToken = this.config.supportedPositions[0].asset;
|
|
312
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
313
|
+
if(!usdcToBtc) {
|
|
314
|
+
const sellAmount = returnFormattedAmount(amount, toTokenDecimals);
|
|
315
|
+
const params: Record<string, any> = {
|
|
316
|
+
sellTokenAddress: from_token_address,
|
|
317
|
+
buyTokenAddress: to_token_address,
|
|
318
|
+
takerAddress,
|
|
319
|
+
sellAmount:sellAmount,
|
|
320
|
+
};
|
|
321
|
+
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
322
|
+
if (!finalQuote.data.length) {
|
|
323
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
const dataObject: Quote = finalQuote.data[0];
|
|
327
|
+
return dataObject;
|
|
328
|
+
}
|
|
329
|
+
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
330
|
+
console.log("btcPrice", btcPrice);
|
|
331
|
+
if (!btcPrice) {
|
|
332
|
+
logger.error(`error getting btc price: ${btcPrice}`);
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
336
|
+
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
337
|
+
console.log("targetBtcBig", targetBtcBig);
|
|
338
|
+
let low = BigInt(
|
|
339
|
+
Math.floor(
|
|
340
|
+
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 0.9
|
|
341
|
+
)
|
|
342
|
+
);
|
|
343
|
+
let high = BigInt(
|
|
344
|
+
Math.floor(
|
|
345
|
+
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 1.1
|
|
346
|
+
)
|
|
347
|
+
);
|
|
348
|
+
let mid = 0n;
|
|
349
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
350
|
+
mid = (low + high) / 2n;
|
|
351
|
+
const sellAmount = returnFormattedAmount(Number(mid), 0);
|
|
352
|
+
const quote = await this.fetchQuoteWithRetry({
|
|
353
|
+
sellTokenAddress: from_token_address,
|
|
354
|
+
buyTokenAddress: to_token_address,
|
|
355
|
+
takerAddress,
|
|
356
|
+
sellAmount,
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
const gotBtc = BigInt(quote.data[0].buyAmount);
|
|
360
|
+
if (gotBtc === targetBtcBig) return quote.data[0];
|
|
361
|
+
|
|
362
|
+
if (gotBtc > targetBtcBig) {
|
|
363
|
+
high = mid;
|
|
364
|
+
} else {
|
|
365
|
+
low = mid;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (
|
|
369
|
+
gotBtc >= targetBtcBig &&
|
|
370
|
+
gotBtc <= targetBtcBig + BigInt(tolerance)
|
|
371
|
+
) {
|
|
372
|
+
return quote.data[0];
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
let sellAmount = returnFormattedAmount(
|
|
376
|
+
Number(mid),
|
|
377
|
+
0
|
|
378
|
+
);
|
|
379
|
+
const params: Record<string, any> = {
|
|
380
|
+
sellTokenAddress: from_token_address,
|
|
381
|
+
buyTokenAddress: to_token_address,
|
|
382
|
+
takerAddress,
|
|
383
|
+
sellAmount: sellAmount,
|
|
384
|
+
};
|
|
385
|
+
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
386
|
+
if (!finalQuote.data.length) {
|
|
387
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
const dataObject: Quote = finalQuote.data[0];
|
|
391
|
+
return dataObject;
|
|
392
|
+
} catch (err) {
|
|
393
|
+
logger.error(`No quotes available for this swap: ${err}`);
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
async getPriceOfToken (
|
|
399
|
+
tokenAddress: string,
|
|
400
|
+
retries: number = MAX_RETRIES
|
|
401
|
+
): Promise<number | null> {
|
|
402
|
+
try {
|
|
403
|
+
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
404
|
+
const response = await axios.get(url);
|
|
405
|
+
const length = response.data.length;
|
|
406
|
+
return response.data[length - 1].value;
|
|
407
|
+
} catch (err) {
|
|
408
|
+
if (retries > 0) {
|
|
409
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
410
|
+
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
411
|
+
} else {
|
|
412
|
+
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
}
|