@strkfarm/sdk 1.1.70 → 2.0.0-dev.2

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.
Files changed (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +67016 -59681
  4. package/dist/index.browser.mjs +29832 -23221
  5. package/dist/index.d.ts +2006 -787
  6. package/dist/index.js +25403 -18769
  7. package/dist/index.mjs +25333 -18739
  8. package/package.json +80 -76
  9. package/src/data/extended-deposit.abi.json +3613 -0
  10. package/src/data/universal-vault.abi.json +135 -20
  11. package/src/dataTypes/address.ts +7 -0
  12. package/src/global.ts +240 -193
  13. package/src/interfaces/common.tsx +26 -2
  14. package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
  15. package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
  16. package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
  17. package/src/modules/avnu.ts +17 -4
  18. package/src/modules/ekubo-quoter.ts +99 -10
  19. package/src/modules/erc20.ts +67 -21
  20. package/src/modules/harvests.ts +16 -29
  21. package/src/modules/index.ts +5 -1
  22. package/src/modules/lst-apr.ts +36 -0
  23. package/src/modules/midas.ts +159 -0
  24. package/src/modules/pricer-from-api.ts +2 -2
  25. package/src/modules/pricer-lst.ts +1 -1
  26. package/src/modules/pricer.ts +3 -38
  27. package/src/modules/token-market-data.ts +202 -0
  28. package/src/node/deployer.ts +1 -36
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +20 -3
  31. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  32. package/src/strategies/index.ts +4 -1
  33. package/src/strategies/svk-strategy.ts +247 -0
  34. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  35. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  36. package/src/strategies/universal-adapters/avnu-adapter.ts +411 -0
  37. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  38. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  39. package/src/strategies/universal-adapters/extended-adapter.ts +661 -0
  40. package/src/strategies/universal-adapters/index.ts +5 -1
  41. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  42. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  43. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  44. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  45. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  46. package/src/strategies/universal-strategy.tsx +1098 -1180
  47. package/src/strategies/vesu-extended-strategy/services/operationService.ts +34 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +49 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +376 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1134 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -0,0 +1,411 @@
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
+ toToken.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
+ const fromToken = this.config.supportedPositions[0].asset;
160
+ const toToken = this.config.supportedPositions[1].asset;
161
+ const vaultAllocator = ContractAddr.from(
162
+ this.config.vaultAllocator.address
163
+ );
164
+ const quote = await this.getQuotesAvnu(
165
+ fromToken.address.toString(),
166
+ toToken.address.toString(),
167
+ params.amount.toNumber(),
168
+ vaultAllocator.address.toString(),
169
+ toToken.decimals,
170
+ true
171
+ )
172
+ if (!quote) {
173
+ logger.error("error getting quote from avnu");
174
+ return [];
175
+ }
176
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
177
+ quote,
178
+ vaultAllocator.address
179
+ );
180
+ const swapCallData = getCalldata[0];
181
+ // const approveCallData = getCalldata[0];
182
+ const amount = uint256.bnToUint256(quote.sellAmountInUsd*10**7)
183
+ return [
184
+ {
185
+ sanitizer: SIMPLE_SANITIZER,
186
+ call: {
187
+ contractAddress: fromToken.address,
188
+ selector: hash.getSelectorFromName("approve"),
189
+ calldata:[
190
+ AVNU_EXCHANGE.toBigInt(),
191
+ toBigInt(amount.low.toString()), // amount low
192
+ toBigInt(amount.high.toString()), // amount high
193
+ ] ,
194
+ },
195
+ },
196
+ {
197
+ sanitizer: SIMPLE_SANITIZER,
198
+ call: {
199
+ contractAddress: AVNU_EXCHANGE,
200
+ selector: hash.getSelectorFromName("multi_route_swap"),
201
+ calldata: swapCallData,
202
+ },
203
+ },
204
+ ];
205
+ } catch (error) {
206
+ logger.error(`Error getting Avnu quote: ${error}`);
207
+ return [];
208
+ }
209
+ }
210
+
211
+ //Swap wbtc to usdc
212
+ async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
213
+ try {
214
+ const toToken = this.config.supportedPositions[0].asset;
215
+ const fromToken = this.config.supportedPositions[1].asset;
216
+ const vaultAllocator = ContractAddr.from(
217
+ this.config.vaultAllocator.address
218
+ );
219
+ const quote = await this.getQuotesAvnu(
220
+ fromToken.address.toString(),
221
+ toToken.address.toString(),
222
+ params.amount.toNumber(),
223
+ vaultAllocator.address.toString(),
224
+ fromToken.decimals,
225
+ false
226
+ );
227
+ if (!quote) {
228
+ logger.error("No quotes available for this swap, error in quotes avnu");
229
+ return [];
230
+ }
231
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
232
+ quote,
233
+ vaultAllocator.address
234
+ );
235
+ const swapCallData = getCalldata[0];
236
+ const amount = uint256.bnToUint256(params.amount.toWei())
237
+ return [
238
+ {
239
+ sanitizer: SIMPLE_SANITIZER,
240
+ call: {
241
+ contractAddress:fromToken.address,
242
+ selector: hash.getSelectorFromName("approve"),
243
+ calldata: [
244
+ AVNU_EXCHANGE.toBigInt(),
245
+ toBigInt(amount.low.toString()), // amount low
246
+ toBigInt(amount.high.toString()), // amount high
247
+ ],
248
+ },
249
+ },
250
+ {
251
+ sanitizer: SIMPLE_SANITIZER,
252
+ call: {
253
+ contractAddress: AVNU_EXCHANGE,
254
+ selector: hash.getSelectorFromName("multi_route_swap"),
255
+ calldata: swapCallData,
256
+ },
257
+ },
258
+ ];
259
+ } catch (error) {
260
+ logger.error(`Error getting Avnu quote: ${error}`);
261
+ return [];
262
+ }
263
+ }
264
+
265
+ async getSwapCallData(quote: Quote): Promise<bigint[][]> {
266
+ return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
267
+ }
268
+
269
+ async getHealthFactor(): Promise<number> {
270
+ return Promise.resolve(1);
271
+ }
272
+
273
+ async fetchQuoteWithRetry(
274
+ params: Record<string, any>,
275
+ retries: number = 5
276
+ ): Promise<any> {
277
+ for (let attempt = 0; attempt < retries; attempt++) {
278
+ try {
279
+ const response = await axios.get(this.config.baseUrl, { params });
280
+ if (response.data && response.data.length > 0) {
281
+ return response;
282
+ }
283
+ throw new Error("Empty response data");
284
+ } catch (err) {
285
+ logger.error(`Error fetching quote with retry: ${err}`);
286
+ if (attempt === retries - 1) {
287
+ throw err;
288
+ }
289
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
290
+ }
291
+ }
292
+ throw new Error("Failed to fetch quote after retries");
293
+ }
294
+
295
+ async getQuotesAvnu (
296
+ from_token_address: string,
297
+ to_token_address: string,
298
+ amount: number, //amount in btc units
299
+ takerAddress: string,
300
+ toTokenDecimals: number,
301
+ usdcToBtc: boolean,
302
+ maxIterations: number = 5,
303
+ tolerance: number = 10000
304
+ ): Promise<Quote | null>{
305
+ try {
306
+ const fromToken = this.config.supportedPositions[0].asset;
307
+ const toToken = this.config.supportedPositions[1].asset;
308
+ if(!usdcToBtc) {
309
+ const sellAmount = returnFormattedAmount(amount, toTokenDecimals);
310
+ const params: Record<string, any> = {
311
+ sellTokenAddress: from_token_address,
312
+ buyTokenAddress: to_token_address,
313
+ takerAddress,
314
+ sellAmount:sellAmount,
315
+ };
316
+ const finalQuote = await this.fetchQuoteWithRetry(params);
317
+ if (!finalQuote.data.length) {
318
+ logger.error("No quotes available for this swap, error in quotes avnu");
319
+ return null;
320
+ }
321
+ const dataObject: Quote = finalQuote.data[0];
322
+ return dataObject;
323
+ }
324
+ const btcPrice = await this.getPriceOfToken(toToken.address.toString());
325
+ if (!btcPrice) {
326
+ logger.error(`error getting btc price: ${btcPrice}`);
327
+ return null;
328
+ }
329
+ const estimatedUsdcAmount = Math.floor(amount * btcPrice);
330
+ const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
331
+ let low = BigInt(
332
+ Math.floor(
333
+ (estimatedUsdcAmount * 10 ** fromToken.decimals) * 0.9
334
+ )
335
+ );
336
+ let high = BigInt(
337
+ Math.floor(
338
+ (estimatedUsdcAmount * 10 ** fromToken.decimals) * 1.1
339
+ )
340
+ );
341
+ let mid = 0n;
342
+ for (let i = 0; i < maxIterations; i++) {
343
+ mid = (low + high) / 2n;
344
+ const sellAmount = returnFormattedAmount(Number(mid), 0);
345
+ const quote = await this.fetchQuoteWithRetry({
346
+ sellTokenAddress: from_token_address,
347
+ buyTokenAddress: to_token_address,
348
+ takerAddress,
349
+ sellAmount,
350
+ });
351
+
352
+ const gotBtc = BigInt(quote.data[0].buyAmount);
353
+ if (gotBtc === targetBtcBig) return quote.data[0];
354
+
355
+ if (gotBtc > targetBtcBig) {
356
+ high = mid;
357
+ } else {
358
+ low = mid;
359
+ }
360
+
361
+ if (
362
+ gotBtc >= targetBtcBig &&
363
+ gotBtc <= targetBtcBig + BigInt(tolerance)
364
+ ) {
365
+ return quote.data[0];
366
+ }
367
+ }
368
+ let sellAmount = returnFormattedAmount(
369
+ Number(mid),
370
+ 0
371
+ );
372
+ const params: Record<string, any> = {
373
+ sellTokenAddress: from_token_address,
374
+ buyTokenAddress: to_token_address,
375
+ takerAddress,
376
+ sellAmount: sellAmount,
377
+ };
378
+ const finalQuote = await this.fetchQuoteWithRetry(params);
379
+ if (!finalQuote.data.length) {
380
+ logger.error("No quotes available for this swap, error in quotes avnu");
381
+ return null;
382
+ }
383
+ const dataObject: Quote = finalQuote.data[0];
384
+ return dataObject;
385
+ } catch (err) {
386
+ logger.error(`No quotes available for this swap: ${err}`);
387
+ return null;
388
+ }
389
+ };
390
+
391
+ async getPriceOfToken (
392
+ tokenAddress: string,
393
+ retries: number = MAX_RETRIES
394
+ ): Promise<number | null> {
395
+ try {
396
+ const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
397
+ const response = await axios.get(url);
398
+ const length = response.data.length;
399
+ return response.data[length - 1].value;
400
+ } catch (err) {
401
+ if (retries > 0) {
402
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
403
+ return this.getPriceOfToken(tokenAddress, retries - 1);
404
+ } else {
405
+ logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
406
+ return null;
407
+ }
408
+ }
409
+ };
410
+
411
+ }