@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.
Files changed (52) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +66861 -59746
  4. package/dist/index.browser.mjs +24970 -18579
  5. package/dist/index.d.ts +1969 -776
  6. package/dist/index.js +25259 -18845
  7. package/dist/index.mjs +25464 -19090
  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 +8 -1
  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 -11
  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.ts +3 -38
  26. package/src/modules/token-market-data.ts +202 -0
  27. package/src/node/deployer.ts +1 -36
  28. package/src/strategies/autoCompounderStrk.ts +1 -1
  29. package/src/strategies/base-strategy.ts +20 -3
  30. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  31. package/src/strategies/index.ts +4 -1
  32. package/src/strategies/svk-strategy.ts +247 -0
  33. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  34. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  35. package/src/strategies/universal-adapters/avnu-adapter.ts +418 -0
  36. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  37. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  38. package/src/strategies/universal-adapters/extended-adapter.ts +544 -0
  39. package/src/strategies/universal-adapters/index.ts +5 -1
  40. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  41. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  42. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  43. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  44. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  45. package/src/strategies/universal-strategy.tsx +1098 -1180
  46. package/src/strategies/vesu-extended-strategy/services/operationService.ts +28 -0
  47. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  48. package/src/strategies/vesu-extended-strategy/utils/constants.ts +48 -0
  49. package/src/strategies/vesu-extended-strategy/utils/helper.ts +374 -0
  50. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +992 -0
  51. package/src/strategies/vesu-rebalance.tsx +16 -19
  52. package/src/utils/health-factor-math.ts +11 -5
@@ -0,0 +1,544 @@
1
+ import { BaseAdapter, DepositParams, WithdrawParams, BaseAdapterConfig } from "./baseAdapter";
2
+ import { Protocols } from "@/interfaces";
3
+ import { SupportedPosition } from "./baseAdapter";
4
+ import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
5
+ import { Web3Number } from "@/dataTypes";
6
+ import { PositionInfo } from "./baseAdapter";
7
+ import { ManageCall } from "./baseAdapter";
8
+ import { ContractAddr } from "@/dataTypes";
9
+ import { AVNU_EXCHANGE_FOR_LEGACY_USDC } from "./adapter-utils";
10
+ import { hash, uint256 } from "starknet";
11
+ import { Global } from "@/global";
12
+ import { AVNU_LEGACY_SANITIZER, EXTENDED_SANITIZER, SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
13
+ import ExtendedWrapper, {
14
+ AssetOperationStatus,
15
+ AssetOperationType,
16
+ FundingRate,
17
+ OrderSide,
18
+ Position,
19
+ TimeInForce,
20
+ } from "@/modules/ExtendedWrapperSDk";
21
+ import { Balance, OpenOrder, OrderStatus } from "@/modules/ExtendedWrapperSDk";
22
+ import axios from "axios";
23
+ import { AvnuAdapter } from "./avnu-adapter";
24
+ import { logger } from "@/utils";
25
+ export interface ExtendedAdapterConfig extends BaseAdapterConfig {
26
+ vaultIdExtended: number;
27
+ extendedContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
28
+ extendedBackendUrl: string;
29
+ extendedApiKey: string;
30
+ extendedTimeout: number;
31
+ extendedRetries: number;
32
+ extendedBaseUrl: string;
33
+ extendedMarketName: string;
34
+ extendedPrecision: number;
35
+ avnuAdapter: AvnuAdapter;
36
+ }
37
+
38
+ export class ExtendedAdapter extends BaseAdapter<
39
+ DepositParams,
40
+ WithdrawParams
41
+ > {
42
+ readonly config: ExtendedAdapterConfig;
43
+ readonly client: ExtendedWrapper;
44
+
45
+ constructor(config: ExtendedAdapterConfig) {
46
+ super(config, ExtendedAdapter.name, Protocols.EXTENDED);
47
+ this.config = config as ExtendedAdapterConfig;
48
+ const client = new ExtendedWrapper({
49
+ baseUrl: this.config.extendedBackendUrl,
50
+ apiKey: this.config.extendedApiKey,
51
+ timeout: this.config.extendedTimeout,
52
+ retries: this.config.extendedRetries,
53
+ });
54
+ this.client = client;
55
+ }
56
+ //abstract means the method has no implementation in this class; instead, child classes must implement it.
57
+ protected async getAPY(
58
+ supportedPosition: SupportedPosition
59
+ ): Promise<PositionAPY> {
60
+ /** Considering supportedPosiiton.isDebt as side parameter to get the funding rates */
61
+ const side = supportedPosition.isDebt ? "LONG" : "SHORT";
62
+ const fundingRates = await this.client.getFundingRates(this.config.extendedMarketName, side);
63
+ if (fundingRates.status !== "OK") {
64
+ logger.error("error getting funding rates", fundingRates);
65
+ return { apy: 0, type: APYType.BASE };
66
+ }
67
+ const fundingRate:FundingRate = fundingRates.data[0];
68
+ const apy = Number(fundingRate.f) * 365 * 24;
69
+ return { apy: apy, type: APYType.BASE };
70
+ }
71
+
72
+ protected async getPosition(
73
+ supportedPosition: SupportedPosition
74
+ ): Promise<PositionAmount> {
75
+ if (!this.client) {
76
+ throw new Error("Client not initialized");
77
+ }
78
+ const holdings = await this.getExtendedDepositAmount();
79
+ if (!holdings) {
80
+ throw new Error("No position found");
81
+ }
82
+ // equity is the total amount on extended
83
+ const amount = holdings.equity;
84
+ return Promise.resolve({
85
+ amount: new Web3Number(amount, 0),
86
+ remarks: `${holdings.availableForWithdrawal} ${holdings.equity}`,
87
+ });
88
+ }
89
+
90
+ async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
91
+ return Promise.resolve({
92
+ tokenInfo: this.config.baseToken,
93
+ amount: new Web3Number(0, 0),
94
+ usdValue: 0,
95
+ apy: { apy: 0, type: APYType.BASE },
96
+ protocol: Protocols.EXTENDED,
97
+ remarks: "",
98
+ });
99
+ }
100
+
101
+ async maxWithdraw(): Promise<PositionInfo> {
102
+ return Promise.resolve({
103
+ tokenInfo: this.config.baseToken,
104
+ amount: new Web3Number(0, 0),
105
+ usdValue: 0,
106
+ apy: { apy: 0, type: APYType.BASE },
107
+ protocol: Protocols.EXTENDED,
108
+ remarks: "",
109
+ });
110
+ }
111
+
112
+ protected _getDepositLeaf(): {
113
+ target: ContractAddr;
114
+ method: string;
115
+ packedArguments: bigint[];
116
+ sanitizer: ContractAddr;
117
+ id: string;
118
+ }[] {
119
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
120
+ return [
121
+ {
122
+ target: this.config.supportedPositions[0].asset.address,
123
+ method: "approve",
124
+ packedArguments: [
125
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
126
+ ],
127
+ id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
128
+ sanitizer: AVNU_LEGACY_SANITIZER,
129
+ },
130
+ {
131
+ target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
132
+ method: "swap_to_legacy",
133
+ packedArguments: [],
134
+ id: `extended_swap_to_legacy_${this.config.supportedPositions[0].asset.symbol}`,
135
+ sanitizer: AVNU_LEGACY_SANITIZER,
136
+ },
137
+ {
138
+ target: usdceToken!.address,
139
+ method: "approve",
140
+ packedArguments: [this.config.extendedContract.toBigInt()],
141
+ id: `extended_approve_${usdceToken!.symbol}`,
142
+ sanitizer: SIMPLE_SANITIZER,
143
+ },
144
+ {
145
+ target: this.config.extendedContract,
146
+ method: "deposit",
147
+ packedArguments: [BigInt(this.config.vaultIdExtended)],
148
+ sanitizer: EXTENDED_SANITIZER,
149
+ id: `extended_deposit_${usdceToken!.symbol}`,
150
+ },
151
+ ];
152
+ }
153
+
154
+ protected _getWithdrawLeaf(): {
155
+ target: ContractAddr;
156
+ method: string;
157
+ packedArguments: bigint[];
158
+ sanitizer: ContractAddr;
159
+ id: string;
160
+ }[] {
161
+ /**
162
+ * Withdraw is done via extended wrapper
163
+ */
164
+ return [];
165
+ }
166
+
167
+ async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
168
+ try {
169
+ const usdcToken = this.config.supportedPositions[0].asset;
170
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
171
+ const salt = Math.floor(
172
+ Math.random() * 10 ** usdcToken.decimals
173
+ );
174
+ const amount = uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
175
+ const quotes = await this.config.avnuAdapter.getQuotesAvnu(
176
+ usdcToken.address.toString(),
177
+ usdceToken!.address.toString(),
178
+ params.amount.toNumber(),
179
+ this.config.avnuAdapter.config.vaultAllocator.address.toString(),
180
+ usdceToken!.decimals,
181
+ false
182
+ )
183
+
184
+ if (!quotes) {
185
+ logger.error("error getting quotes from avnu");
186
+ return [];
187
+ }
188
+
189
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes!);
190
+ const swapCallData = getCalldata[0];
191
+ //change extended sanitizer here
192
+ return [
193
+ {
194
+ sanitizer: AVNU_LEGACY_SANITIZER,
195
+ call: {
196
+ contractAddress: usdcToken.address,
197
+ selector: hash.getSelectorFromName("approve"),
198
+ calldata: [
199
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
200
+ toBigInt(amount.low.toString()), // amount low
201
+ toBigInt(amount.high.toString()), // amount high
202
+ ],
203
+ },
204
+ },
205
+ {
206
+ sanitizer: AVNU_LEGACY_SANITIZER,
207
+ call: {
208
+ contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
209
+ selector: hash.getSelectorFromName("swap_to_legacy"),
210
+ calldata: swapCallData,
211
+ },
212
+ },
213
+ {
214
+ sanitizer: SIMPLE_SANITIZER,
215
+ call: {
216
+ contractAddress: usdceToken!.address,
217
+ selector: hash.getSelectorFromName("approve"),
218
+ calldata: [
219
+ this.config.extendedContract.toBigInt(),
220
+ toBigInt(amount.low.toString()), // amount low
221
+ toBigInt(amount.high.toString()), // amount high
222
+ ],
223
+ },
224
+ },
225
+ {
226
+ sanitizer: EXTENDED_SANITIZER,
227
+ call: {
228
+ contractAddress: this.config.extendedContract,
229
+ selector: hash.getSelectorFromName("deposit"),
230
+ calldata: [
231
+ BigInt(this.config.vaultIdExtended),
232
+ BigInt(params.amount.toWei()),
233
+ BigInt(salt),
234
+ ],
235
+ },
236
+ },
237
+ ];
238
+ } catch (error) {
239
+ logger.error(`Error creating Deposit Call: ${error}`);
240
+ return [];
241
+ }
242
+ }
243
+
244
+ //Swap wbtc to usdc
245
+ async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
246
+ try {
247
+ if (!this.client) {
248
+ throw new Error("Client not initialized");
249
+ }
250
+ return [];
251
+ } catch (error) {
252
+ logger.error(`Error creating Withdraw Call: ${error}`);
253
+ return [];
254
+ }
255
+ }
256
+
257
+ async withdrawFromExtended(amount: Web3Number): Promise<boolean> {
258
+ try {
259
+ if (!this.client) {
260
+ throw new Error("Client not initialized");
261
+ }
262
+ const withdrawalRequest = this.client.withdrawUSDC(amount.toString());
263
+ if ((await withdrawalRequest).status === "OK") {
264
+ console.log("Withdrawal request successful");
265
+ return true;
266
+ }
267
+ return false;
268
+ } catch (error) {
269
+ logger.error(`Error creating Withdraw Call: ${error}`);
270
+ return false;
271
+ }
272
+ }
273
+
274
+ async getHealthFactor(): Promise<number> {
275
+ return Promise.resolve(1);
276
+ }
277
+
278
+ async getExtendedDepositAmount(): Promise<Balance | undefined> {
279
+ if (this.client === null) {
280
+ logger.error("error initializing client");
281
+ return undefined;
282
+ }
283
+ const result = await this.client.getHoldings();
284
+ if (!result) {
285
+ logger.error(`error getting holdings: ${result}`);
286
+ return undefined;
287
+ }
288
+ const holdings = result.data;
289
+ if (!holdings) {
290
+ logger.error(`error getting holdings: ${holdings}`);
291
+ return undefined;
292
+ }
293
+ return holdings;
294
+ }
295
+
296
+ async setLeverage(leverage: string, marketName: string): Promise<boolean> {
297
+ if (this.client === null) {
298
+ logger.error("error initializing client");
299
+ return false;
300
+ }
301
+ const res = await this.client.updateLeverage({
302
+ leverage: leverage,
303
+ market: marketName,
304
+ });
305
+ if (res.status === "OK") {
306
+ return true;
307
+ }
308
+ return false;
309
+ }
310
+
311
+ async getAllOpenPositions(): Promise<Position[] | null> {
312
+ if (this.client === null) {
313
+ logger.error("error initializing client");
314
+ return null;
315
+ }
316
+ const response = await this.client.getPositionsForMarket(
317
+ this.config.extendedMarketName
318
+ );
319
+ if (response.status === "OK") {
320
+ if (response.data.length === 0) {
321
+ return [];
322
+ } else {
323
+ return response.data;
324
+ }
325
+ }
326
+ return null;
327
+ }
328
+
329
+ async getOrderHistory(marketName: string): Promise<OpenOrder[] | null> {
330
+ if (this.client === null) {
331
+ logger.error("error initializing client");
332
+ return null;
333
+ }
334
+ const result = await this.client.getOrderHistory(marketName);
335
+ return result.data;
336
+ }
337
+
338
+ async getOrderStatus(
339
+ orderId: string,
340
+ marketName: string
341
+ ): Promise<OpenOrder | null> {
342
+ if (this.client === null) {
343
+ logger.error("error initializing client");
344
+ return null;
345
+ }
346
+ const orderhistory = await this.getOrderHistory(marketName);
347
+
348
+ if (!orderhistory || orderhistory.length === 0) {
349
+ logger.error(`error getting order: ${orderId}`);
350
+ return null;
351
+ }
352
+ const order = orderhistory
353
+ .slice(0, 3)
354
+ .find((order) => order.id.toString() === orderId);
355
+ if (!order) {
356
+ logger.error(`error getting order: ${order}`);
357
+ return null;
358
+ }
359
+ return order;
360
+ }
361
+
362
+ async fetchOrderBookBTCUSDC(): Promise<{
363
+ status: boolean;
364
+ bid: Web3Number;
365
+ ask: Web3Number;
366
+ }> {
367
+ try {
368
+ const res = await axios.get(
369
+ `${this.config.extendedBaseUrl}/api/v1/info/markets/${this.config.extendedMarketName}/orderbook`
370
+ );
371
+ let ask_price = new Web3Number(0, 0);
372
+ let bid_price = new Web3Number(0, 0);
373
+ if (res.data.status !== "OK") {
374
+ return {
375
+ status: false,
376
+ bid: bid_price,
377
+ ask: ask_price,
378
+ };
379
+ }
380
+ const data = res.data.data;
381
+ const bid = data.bid[0];
382
+ const ask = data.ask[0];
383
+ ask_price = new Web3Number(ask.price, 0);
384
+ bid_price = new Web3Number(bid.price, 0);
385
+
386
+ return {
387
+ status: false,
388
+ bid: bid_price, // check for quantity as well, not at the moment though
389
+ ask: ask_price, // check for quantity as well, not at the moment though
390
+ };
391
+ } catch (err) {
392
+ logger.error(`the err is: ${err}`);
393
+ return {
394
+ status: false,
395
+ bid: new Web3Number(0, 0),
396
+ ask: new Web3Number(0, 0),
397
+ };
398
+ }
399
+ }
400
+
401
+ async createOrder(
402
+ leverage: string,
403
+ btcAmount: number,
404
+ side: OrderSide,
405
+ attempt = 1,
406
+ maxAttempts = 5
407
+ ): Promise<{ position_id: string; btc_exposure: string } | null> {
408
+ try {
409
+ if (this.client === null) {
410
+ logger.error("error initializing client");
411
+ return null;
412
+ }
413
+ const setLeverage = await this.setLeverage(
414
+ leverage,
415
+ this.config.extendedMarketName
416
+ );
417
+ if (!setLeverage) {
418
+ logger.error("error depositing or setting leverage");
419
+ return null;
420
+ }
421
+ const positions = await this.getAllOpenPositions();
422
+ if (positions === null) {
423
+ return null;
424
+ }
425
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
426
+ const spread = ask.minus(bid);
427
+ let price = ask
428
+ .plus(bid)
429
+ .div(2)
430
+ side === OrderSide.SELL ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
431
+ const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
432
+ this.config.extendedPrecision
433
+ ); // gives the amount of wbtc
434
+
435
+ const result = await this.createExtendedPositon(
436
+ this.client,
437
+ this.config.extendedMarketName,
438
+ amount_in_token,
439
+ price.toFixed(0),
440
+ side
441
+ );
442
+ if (!result) {
443
+ return null;
444
+ }
445
+ await new Promise((resolve) => setTimeout(resolve, 5000));
446
+ const openOrder = await this.getOrderStatus(result.position_id, this.config.extendedMarketName);
447
+ if (!openOrder || openOrder.status !== OrderStatus.FILLED) {
448
+ if (attempt >= maxAttempts) {
449
+ logger.error("Max retries reached — could not verify open position");
450
+ return null;
451
+ } else {
452
+ const backoff = 2000 * attempt;
453
+ await new Promise((resolve) => setTimeout(resolve, backoff));
454
+ return this.createOrder(
455
+ leverage,
456
+ btcAmount,
457
+ side,
458
+ attempt + 1,
459
+ maxAttempts
460
+ );
461
+ }
462
+ } else {
463
+ return {
464
+ position_id: result.position_id,
465
+ btc_exposure: openOrder.qty,
466
+ };
467
+ }
468
+ } catch (err: any) {
469
+ logger.error(`createShortOrder failed on attempt ${attempt}: ${err.message}`);
470
+
471
+ if (attempt < maxAttempts) {
472
+ const backoff = 1200 * attempt;
473
+ console.log(`Retrying after ${backoff}ms...`);
474
+ await new Promise((resolve) => setTimeout(resolve, backoff));
475
+ return this.createOrder(
476
+ leverage,
477
+ btcAmount,
478
+ side,
479
+ attempt + 1,
480
+ maxAttempts
481
+ );
482
+ }
483
+ logger.error("Max retry attempts reached — aborting createShortOrder");
484
+ return null;
485
+ }
486
+ }
487
+
488
+ async createExtendedPositon(
489
+ client: ExtendedWrapper,
490
+ marketName: string,
491
+ amount: string,
492
+ price: string,
493
+ side: OrderSide
494
+ ) {
495
+ try {
496
+ const result =
497
+ side === OrderSide.SELL
498
+ ? await client.createSellOrder(marketName, amount, price, {
499
+ postOnly: false,
500
+ timeInForce: TimeInForce.IOC,
501
+ })
502
+ : await client.createBuyOrder(marketName, amount, price, {
503
+ postOnly: false,
504
+ timeInForce: TimeInForce.IOC,
505
+ });
506
+ if (result.data.id) {
507
+ const position_id = result.data.id.toString();
508
+ return {
509
+ position_id,
510
+ };
511
+ }
512
+ return null;
513
+ } catch (err) {
514
+ console.log("Error opening short extended position", err);
515
+ return null;
516
+ }
517
+ }
518
+
519
+ async getDepositOrWithdrawalStatus(orderId: number | string, operationsType: AssetOperationType): Promise<boolean> {
520
+ try{
521
+ let transferHistory = await this.client.getAssetOperations({
522
+ operationsType:[operationsType],
523
+ operationsStatus:[AssetOperationStatus.COMPLETED]
524
+ })
525
+ console.log("transferHistory", transferHistory);
526
+ if(operationsType === AssetOperationType.DEPOSIT){
527
+ const myTransferStatus = transferHistory.data.find(operation => operation.transactionHash === orderId);
528
+ if (!myTransferStatus) {
529
+ return false;
530
+ }
531
+ return true;
532
+ }else{
533
+ const myTransferStatus = transferHistory.data.find(operation => operation.id === orderId);
534
+ if (!myTransferStatus) {
535
+ return false;
536
+ }
537
+ return true;
538
+ }
539
+ }catch(err){
540
+ logger.error(`error getting deposit or withdrawal status: ${err}`);
541
+ return false;
542
+ }
543
+ }
544
+ }
@@ -1,4 +1,8 @@
1
1
  export * from "./baseAdapter";
2
2
  export * from "./common-adapter";
3
3
  export * from "./vesu-adapter";
4
- export * from "./adapter-utils";
4
+ export * from "./vesu-supply-only-adapter";
5
+ export * from "./vesu-multiply-adapter";
6
+ export * from "./extended-adapter";
7
+ export * from "./adapter-utils";
8
+ export * from "./unused-balance-adapter";
@@ -0,0 +1,109 @@
1
+ import { ContractAddr, Web3Number } from "@/dataTypes";
2
+ import { APYType, BaseAdapter, BaseAdapterConfig, DepositParams, ManageCall, PositionAmount, PositionAPY, PositionInfo, SupportedPosition, WithdrawParams } from "./baseAdapter";
3
+ import { Contract, uint256 } from "starknet";
4
+ import erc20Abi from "@/data/erc20.abi.json";
5
+ import { ERC20, TokenMarketData } from "@/modules";
6
+ import { Protocols } from "@/interfaces";
7
+
8
+ export interface UnusedBalanceAdapterConfig extends BaseAdapterConfig {}
9
+
10
+ export class UnusedBalanceAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
11
+ readonly config: UnusedBalanceAdapterConfig;
12
+ readonly tokenMarketData: TokenMarketData;
13
+
14
+ constructor(config: UnusedBalanceAdapterConfig) {
15
+ super(config, UnusedBalanceAdapter.name, Protocols.NONE);
16
+ this.config = config;
17
+ this.tokenMarketData = new TokenMarketData(this.config.pricer, this.config.networkConfig);
18
+ }
19
+
20
+ protected async getAPY(_supportedPosition: SupportedPosition): Promise<PositionAPY> {
21
+ const isSupported = this.tokenMarketData.isAPYSupported(this.config.baseToken);
22
+ const apy = isSupported ? await this.tokenMarketData.getAPY(this.config.baseToken) : 0;
23
+ return { apy: apy, type: isSupported ? APYType.LST : APYType.BASE };
24
+ }
25
+
26
+ protected async getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount> {
27
+ try {
28
+ const balance = await (new ERC20(this.config.networkConfig)).balanceOf(supportedPosition.asset.address, this.config.vaultAllocator.address, supportedPosition.asset.decimals);
29
+ return {
30
+ amount: balance,
31
+ remarks: "Unused balance"
32
+ }
33
+ } catch (_e) {
34
+ throw new Error(`${UnusedBalanceAdapter.name}: Failed to get position for ${supportedPosition.asset.symbol}`);
35
+ }
36
+ }
37
+
38
+ async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
39
+ const baseToken = this.config.baseToken;
40
+ if (!amount) {
41
+ const infinite = new Web3Number('999999999999999999999999999', baseToken.decimals);
42
+ return {
43
+ tokenInfo: baseToken,
44
+ amount: infinite,
45
+ usdValue: Number.POSITIVE_INFINITY,
46
+ remarks: "Max deposit (infinity)",
47
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
48
+ protocol: this.protocol
49
+ };
50
+ }
51
+ const usdValue = await this.getUSDValue(baseToken, amount);
52
+ return {
53
+ tokenInfo: baseToken,
54
+ amount,
55
+ usdValue,
56
+ remarks: "Deposit amount",
57
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
58
+ protocol: this.protocol
59
+ };
60
+ }
61
+
62
+ async maxWithdraw(): Promise<PositionInfo> {
63
+ const baseToken = this.config.baseToken;
64
+ const current = await this.getPosition({ asset: baseToken, isDebt: false });
65
+ const usdValue = await this.getUSDValue(baseToken, current.amount);
66
+ return {
67
+ tokenInfo: baseToken,
68
+ amount: current.amount,
69
+ usdValue,
70
+ remarks: "Max withdraw",
71
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
72
+ protocol: this.protocol
73
+ };
74
+ }
75
+
76
+ protected _getDepositLeaf(): {
77
+ target: ContractAddr,
78
+ method: string,
79
+ packedArguments: bigint[];
80
+ sanitizer: ContractAddr,
81
+ id: string
82
+ }[] {
83
+ return [];
84
+ }
85
+
86
+ protected _getWithdrawLeaf(): {
87
+ target: ContractAddr,
88
+ method: string,
89
+ packedArguments: bigint[];
90
+ sanitizer: ContractAddr,
91
+ id: string
92
+ }[] {
93
+ return [];
94
+ }
95
+
96
+ async getHealthFactor(): Promise<number> {
97
+ return Promise.resolve(10);
98
+ }
99
+
100
+ getDepositCall(params: DepositParams): Promise<ManageCall[]> {
101
+ return Promise.resolve([]);
102
+ }
103
+
104
+ getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
105
+ return Promise.resolve([]);
106
+ }
107
+ }
108
+
109
+