@strkfarm/sdk 2.0.0-dev.5 → 2.0.0-dev.6

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.
@@ -1,4 +1,9 @@
1
- import { BaseAdapter, DepositParams, WithdrawParams, BaseAdapterConfig } from "./baseAdapter";
1
+ import {
2
+ BaseAdapter,
3
+ DepositParams,
4
+ WithdrawParams,
5
+ BaseAdapterConfig,
6
+ } from "./baseAdapter";
2
7
  import { Protocols } from "@/interfaces";
3
8
  import { SupportedPosition } from "./baseAdapter";
4
9
  import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
@@ -11,7 +16,12 @@ import { StandardMerkleTree } from "@/utils";
11
16
  import { hash, uint256 } from "starknet";
12
17
  import { Global } from "@/global";
13
18
  import { AdapterLeafType, GenerateCallFn } from "./baseAdapter";
14
- import { AVNU_LEGACY_SANITIZER, EXTENDED_SANITIZER, SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
19
+ import {
20
+ AVNU_LEGACY_SANITIZER,
21
+ EXTENDED_SANITIZER,
22
+ SIMPLE_SANITIZER,
23
+ toBigInt,
24
+ } from "./adapter-utils";
15
25
  import ExtendedWrapper, {
16
26
  AssetOperationStatus,
17
27
  AssetOperationType,
@@ -61,12 +71,15 @@ export class ExtendedAdapter extends BaseAdapter<
61
71
  ): Promise<PositionAPY> {
62
72
  /** Considering supportedPosiiton.isDebt as side parameter to get the funding rates */
63
73
  const side = supportedPosition.isDebt ? "LONG" : "SHORT";
64
- const fundingRates = await this.client.getFundingRates(this.config.extendedMarketName, side);
74
+ const fundingRates = await this.client.getFundingRates(
75
+ this.config.extendedMarketName,
76
+ side
77
+ );
65
78
  if (fundingRates.status !== "OK") {
66
79
  logger.error("error getting funding rates", fundingRates);
67
80
  return { apy: 0, type: APYType.BASE };
68
81
  }
69
- const fundingRate:FundingRate = fundingRates.data[0];
82
+ const fundingRate: FundingRate = fundingRates.data[0];
70
83
  const apy = Number(fundingRate.f) * 365 * 24;
71
84
  return { apy: apy, type: APYType.BASE };
72
85
  }
@@ -118,14 +131,14 @@ export class ExtendedAdapter extends BaseAdapter<
118
131
  sanitizer: ContractAddr;
119
132
  id: string;
120
133
  }[] {
121
- const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
134
+ const usdceToken = Global.getDefaultTokens().find(
135
+ (token) => token.symbol === "USDCe"
136
+ );
122
137
  return [
123
138
  {
124
139
  target: this.config.supportedPositions[0].asset.address,
125
140
  method: "approve",
126
- packedArguments: [
127
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
128
- ],
141
+ packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
129
142
  id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
130
143
  sanitizer: AVNU_LEGACY_SANITIZER,
131
144
  },
@@ -155,19 +168,27 @@ export class ExtendedAdapter extends BaseAdapter<
155
168
 
156
169
  getSwapFromLegacyLeaf(): AdapterLeafType<DepositParams> {
157
170
  const leafConfigs = this._getSwapFromLegacyLeaf();
158
- const leaves = leafConfigs.map(config => {
171
+ const leaves = leafConfigs.map((config) => {
159
172
  const { target, method, packedArguments, sanitizer, id } = config;
160
- const leaf = this.constructSimpleLeafData({
161
- id: id,
162
- target,
163
- method,
164
- packedArguments
165
- }, sanitizer);
173
+ const leaf = this.constructSimpleLeafData(
174
+ {
175
+ id: id,
176
+ target,
177
+ method,
178
+ packedArguments,
179
+ },
180
+ sanitizer
181
+ );
166
182
  return leaf;
167
183
  });
168
- return { leaves, callConstructor: this.getSwapFromLegacyCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
184
+ return {
185
+ leaves,
186
+ callConstructor: this.getSwapFromLegacyCall.bind(
187
+ this
188
+ ) as unknown as GenerateCallFn<DepositParams>,
189
+ };
169
190
  }
170
-
191
+
171
192
  protected _getSwapFromLegacyLeaf(): {
172
193
  target: ContractAddr;
173
194
  method: string;
@@ -175,14 +196,14 @@ export class ExtendedAdapter extends BaseAdapter<
175
196
  sanitizer: ContractAddr;
176
197
  id: string;
177
198
  }[] {
178
- const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
199
+ const usdceToken = Global.getDefaultTokens().find(
200
+ (token) => token.symbol === "USDCe"
201
+ );
179
202
  return [
180
203
  {
181
204
  target: usdceToken!.address,
182
205
  method: "approve",
183
- packedArguments: [
184
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
185
- ],
206
+ packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
186
207
  id: `extendedswaplegacyapprove_${usdceToken!.symbol}`,
187
208
  sanitizer: AVNU_LEGACY_SANITIZER,
188
209
  },
@@ -193,10 +214,9 @@ export class ExtendedAdapter extends BaseAdapter<
193
214
  id: `extended_swap_to_new_${usdceToken!.symbol}`,
194
215
  sanitizer: AVNU_LEGACY_SANITIZER,
195
216
  },
196
- ]
217
+ ];
197
218
  }
198
219
 
199
-
200
220
  protected _getWithdrawLeaf(): {
201
221
  target: ContractAddr;
202
222
  method: string;
@@ -213,12 +233,14 @@ export class ExtendedAdapter extends BaseAdapter<
213
233
  async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
214
234
  try {
215
235
  const usdcToken = this.config.supportedPositions[0].asset;
216
- const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
217
- const salt = Math.floor(
218
- Math.random() * 10 ** usdcToken.decimals
236
+ const usdceToken = Global.getDefaultTokens().find(
237
+ (token) => token.symbol === "USDCe"
219
238
  );
239
+ const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
220
240
  // Give approval for more amount than the required amount
221
- const amount = uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
241
+ const amount = uint256.bnToUint256(
242
+ params.amount.multipliedBy(10).toWei()
243
+ );
222
244
  const quotes = await this.config.avnuAdapter.getQuotesAvnu(
223
245
  usdcToken.address.toString(),
224
246
  usdceToken!.address.toString(),
@@ -226,15 +248,17 @@ export class ExtendedAdapter extends BaseAdapter<
226
248
  this.config.avnuAdapter.config.vaultAllocator.address.toString(),
227
249
  usdceToken!.decimals,
228
250
  false
229
- )
251
+ );
230
252
 
231
253
  if (!quotes) {
232
254
  logger.error("error getting quotes from avnu");
233
255
  return [];
234
256
  }
235
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes!);
257
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(
258
+ quotes!
259
+ );
236
260
  const swapCallData = getCalldata[0];
237
- //change extended sanitizer here
261
+ //change extended sanitizer here
238
262
  return [
239
263
  {
240
264
  sanitizer: AVNU_LEGACY_SANITIZER,
@@ -287,35 +311,44 @@ export class ExtendedAdapter extends BaseAdapter<
287
311
  }
288
312
  }
289
313
 
290
- getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): { proofs: string[][], callConstructor: GenerateCallFn<DepositParams> | GenerateCallFn<WithdrawParams> } {
314
+ getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): {
315
+ proofs: string[][];
316
+ callConstructor:
317
+ | GenerateCallFn<DepositParams>
318
+ | GenerateCallFn<WithdrawParams>;
319
+ } {
291
320
  let proofGroups: string[][] = [];
292
321
 
293
- const ids = this.getSwapFromLegacyLeaf().leaves.map(l => l.readableId)
322
+ const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
294
323
  // console.log(`${this.name}::getProofs ids: ${ids}`);
295
324
  for (const [i, v] of tree.entries()) {
296
- // console.log(`${this.name}::getProofs v: ${v.readableId}`);
325
+ // console.log(`${this.name}::getProofs v: ${v.readableId}`);
297
326
  if (ids.includes(v.readableId)) {
298
- //console.log(`${this.name}::getProofs found id: ${v.readableId}`);
327
+ //console.log(`${this.name}::getProofs found id: ${v.readableId}`);
299
328
  proofGroups.push(tree.getProof(i));
300
329
  }
301
330
  }
302
331
  if (proofGroups.length != ids.length) {
303
- throw new Error(`Not all proofs found for IDs: ${ids.join(', ')}`);
332
+ throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
304
333
  }
305
334
 
306
335
  // find leaf adapter
307
336
  return {
308
337
  proofs: proofGroups,
309
- callConstructor: this.getSwapFromLegacyCall.bind(this)
310
- };
311
- }
338
+ callConstructor: this.getSwapFromLegacyCall.bind(this),
339
+ };
340
+ }
312
341
 
313
342
  async getSwapFromLegacyCall(params: DepositParams): Promise<ManageCall[]> {
314
343
  try {
315
344
  const usdcToken = this.config.supportedPositions[0].asset;
316
- const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
345
+ const usdceToken = Global.getDefaultTokens().find(
346
+ (token) => token.symbol === "USDCe"
347
+ );
317
348
  // Give approval for more amount than the required amount
318
- const amount = uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
349
+ const amount = uint256.bnToUint256(
350
+ params.amount.multipliedBy(10).toWei()
351
+ );
319
352
  const quotes = await this.config.avnuAdapter.getQuotesAvnu(
320
353
  usdceToken!.address.toString(),
321
354
  usdcToken!.address.toString(),
@@ -323,15 +356,17 @@ export class ExtendedAdapter extends BaseAdapter<
323
356
  this.config.avnuAdapter.config.vaultAllocator.address.toString(),
324
357
  usdcToken!.decimals,
325
358
  false
326
- )
359
+ );
327
360
 
328
361
  if (!quotes) {
329
362
  logger.error("error getting quotes from avnu");
330
363
  return [];
331
364
  }
332
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes!);
365
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(
366
+ quotes!
367
+ );
333
368
  const swapCallData = getCalldata[0];
334
- //change extended sanitizer here
369
+ //change extended sanitizer here
335
370
  return [
336
371
  {
337
372
  sanitizer: AVNU_LEGACY_SANITIZER,
@@ -352,7 +387,7 @@ export class ExtendedAdapter extends BaseAdapter<
352
387
  selector: hash.getSelectorFromName("swap_to_new"),
353
388
  calldata: swapCallData,
354
389
  },
355
- }
390
+ },
356
391
  ];
357
392
  } catch (error) {
358
393
  logger.error(`Error creating Deposit Call: ${error}`);
@@ -377,9 +412,14 @@ export class ExtendedAdapter extends BaseAdapter<
377
412
  if (!this.client) {
378
413
  throw new Error("Client not initialized");
379
414
  }
380
- const withdrawalRequest = await this.client.withdrawUSDC(amount.toFixed(2));
415
+ const withdrawalRequest = await this.client.withdrawUSDC(
416
+ amount.toFixed(2)
417
+ );
381
418
  if (withdrawalRequest.status === "OK") {
382
- const withdrawalStatus = await this.getDepositOrWithdrawalStatus(withdrawalRequest.data, AssetOperationType.WITHDRAWAL);
419
+ const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
420
+ withdrawalRequest.data,
421
+ AssetOperationType.WITHDRAWAL
422
+ );
383
423
  return withdrawalStatus;
384
424
  }
385
425
  return false;
@@ -461,21 +501,46 @@ export class ExtendedAdapter extends BaseAdapter<
461
501
  logger.error("error initializing client");
462
502
  return null;
463
503
  }
464
- await new Promise((resolve) => setTimeout(resolve, 5000));
465
- const orderhistory = await this.getOrderHistory(marketName);
504
+ let orderhistory = await this.getOrderHistory(marketName);
466
505
 
467
506
  if (!orderhistory || orderhistory.length === 0) {
468
- logger.error(`error getting order: ${orderId}`);
469
- return null;
507
+ logger.error(`error getting order history: ${orderId}`);
508
+ } else {
509
+ const order = orderhistory
510
+ .slice(0, 5)
511
+ .find((order) => order.id.toString() === orderId);
512
+ if (order) {
513
+ return order;
514
+ }
470
515
  }
471
- const order = orderhistory
472
- .slice(0, 3)
473
- .find((order) => order.id.toString() === orderId);
474
- if (!order) {
475
- logger.error(`error getting order: ${order}`);
476
- return null;
516
+
517
+ // Retry logic: 3 more attempts with 3 second delay each
518
+ for (let attempt = 1; attempt <= 3; attempt++) {
519
+ await new Promise((resolve) => setTimeout(resolve, 3000));
520
+ orderhistory = await this.getOrderHistory(marketName);
521
+
522
+ if (!orderhistory || orderhistory.length === 0) {
523
+ logger.error(
524
+ `error getting order history on retry ${attempt}: ${orderId}`
525
+ );
526
+ continue;
527
+ }
528
+
529
+ const order = orderhistory
530
+ .slice(0, 5)
531
+ .find((order) => order.id.toString() === orderId);
532
+
533
+ if (order) {
534
+ return order;
535
+ }
536
+
537
+ logger.error(
538
+ `order not found in top 5 entries on retry ${attempt}: ${orderId}`
539
+ );
477
540
  }
478
- return order;
541
+
542
+ logger.error(`error getting order after all retries: ${orderId}`);
543
+ return null;
479
544
  }
480
545
 
481
546
  async fetchOrderBookBTCUSDC(): Promise<{
@@ -543,10 +608,10 @@ export class ExtendedAdapter extends BaseAdapter<
543
608
  }
544
609
  const { ask, bid } = await this.fetchOrderBookBTCUSDC();
545
610
  const spread = ask.minus(bid);
546
- let price = ask
547
- .plus(bid)
548
- .div(2)
549
- side === OrderSide.SELL ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
611
+ let price = ask.plus(bid).div(2);
612
+ side === OrderSide.SELL
613
+ ? (price = price.minus(spread.times(0.2 * attempt)))
614
+ : (price = price.plus(spread.times(0.2 * attempt)));
550
615
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
551
616
  this.config.extendedPrecision
552
617
  ); // gives the amount of wbtc
@@ -562,7 +627,10 @@ export class ExtendedAdapter extends BaseAdapter<
562
627
  return null;
563
628
  }
564
629
  await new Promise((resolve) => setTimeout(resolve, 5000));
565
- const openOrder = await this.getOrderStatus(result.position_id, this.config.extendedMarketName);
630
+ const openOrder = await this.getOrderStatus(
631
+ result.position_id,
632
+ this.config.extendedMarketName
633
+ );
566
634
  if (!openOrder || openOrder.status !== OrderStatus.FILLED) {
567
635
  if (attempt >= maxAttempts) {
568
636
  logger.error("Max retries reached — could not verify open position");
@@ -585,7 +653,9 @@ export class ExtendedAdapter extends BaseAdapter<
585
653
  };
586
654
  }
587
655
  } catch (err: any) {
588
- logger.error(`createShortOrder failed on attempt ${attempt}: ${err.message}`);
656
+ logger.error(
657
+ `createShortOrder failed on attempt ${attempt}: ${err.message}`
658
+ );
589
659
 
590
660
  if (attempt < maxAttempts) {
591
661
  const backoff = 1200 * attempt;
@@ -635,26 +705,33 @@ export class ExtendedAdapter extends BaseAdapter<
635
705
  }
636
706
  }
637
707
 
638
- async getDepositOrWithdrawalStatus(orderId: number | string, operationsType: AssetOperationType): Promise<boolean> {
639
- try{
708
+ async getDepositOrWithdrawalStatus(
709
+ orderId: number | string,
710
+ operationsType: AssetOperationType
711
+ ): Promise<boolean> {
712
+ try {
640
713
  let transferHistory = await this.client.getAssetOperations({
641
- operationsType:[operationsType],
642
- operationsStatus:[AssetOperationStatus.COMPLETED]
643
- })
644
- if(operationsType === AssetOperationType.DEPOSIT){
645
- const myTransferStatus = transferHistory.data.find(operation => operation.transactionHash === orderId);
714
+ operationsType: [operationsType],
715
+ operationsStatus: [AssetOperationStatus.COMPLETED],
716
+ });
717
+ if (operationsType === AssetOperationType.DEPOSIT) {
718
+ const myTransferStatus = transferHistory.data.find(
719
+ (operation) => operation.transactionHash === orderId
720
+ );
646
721
  if (!myTransferStatus) {
647
722
  return true;
648
723
  }
649
724
  return true;
650
- }else{
651
- const myTransferStatus = transferHistory.data.find(operation => operation.id.toString() === orderId.toString());
725
+ } else {
726
+ const myTransferStatus = transferHistory.data.find(
727
+ (operation) => operation.id.toString() === orderId.toString()
728
+ );
652
729
  if (!myTransferStatus) {
653
730
  return true;
654
731
  }
655
732
  return true;
656
733
  }
657
- }catch(err){
734
+ } catch (err) {
658
735
  logger.error(`error getting deposit or withdrawal status: ${err}`);
659
736
  return false;
660
737
  }
@@ -66,12 +66,10 @@ export const calculateAmountDistribution = async (
66
66
  vesu_leverage: 0,
67
67
  };
68
68
  }
69
- const extendedBTCExposure =
69
+ const extendedExposureUSD =
70
70
  extendedPosition.length > 0
71
- ? new Web3Number(extendedPosition[0].size, WBTC_TOKEN_DECIMALS)
71
+ ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS)
72
72
  : new Web3Number(0, WBTC_TOKEN_DECIMALS);
73
- const extendedExposureUSD =
74
- extendedBTCExposure.multipliedBy(collateralPrice);
75
73
  const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
76
74
  const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
77
75
  const numerator2 = extendedExposureUSD.toNumber();
@@ -238,8 +238,8 @@ export class VesuExtendedMultiplierStrategy<
238
238
  const balance = await this.getUnusedBalance();
239
239
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
240
240
  /** The LIMIT_BALANCE is the bffer amount to keep in the investing Cycle */
241
- const amountToInvest = balance.amount.plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
242
-
241
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
242
+ logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
243
243
  if (amountToInvest.lessThan(0)) {
244
244
  return {
245
245
  shouldInvest: false,
@@ -301,6 +301,7 @@ export class VesuExtendedMultiplierStrategy<
301
301
  vesuLeverage: 0,
302
302
  };
303
303
  }
304
+ logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
304
305
  return {
305
306
  shouldInvest: true,
306
307
  vesuAmount: vesu_amount,
@@ -384,16 +385,16 @@ export class VesuExtendedMultiplierStrategy<
384
385
  }
385
386
  const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
386
387
  const usdcAmountOnExtended = parseFloat(
387
- extendedHoldings.availableForTrade
388
+ extendedHoldings.availableForWithdrawal
388
389
  );
389
- if (extendedAmount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcAmountOnExtended).greaterThan(0)) {
390
+ if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
390
391
  //move assets to extended
391
392
  try {
392
393
  const { calls: extendedCalls } = await this.moveAssets(
393
394
  {
394
395
  to: Protocols.EXTENDED.name,
395
396
  from: Protocols.VAULT.name,
396
- amount: extendedAmount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcAmountOnExtended),
397
+ amount: extendedAmount.minus(usdcAmountOnExtended),
397
398
  },
398
399
  extendedAdapter,
399
400
  vesuAdapter
@@ -659,7 +660,7 @@ export class VesuExtendedMultiplierStrategy<
659
660
  };
660
661
  }
661
662
  const extendedHoldingAmount = new Web3Number(
662
- extendedHoldings.availableForTrade,
663
+ extendedHoldings.availableForWithdrawal,
663
664
  USDC_TOKEN_DECIMALS
664
665
  );
665
666
  const {
@@ -719,7 +720,7 @@ export class VesuExtendedMultiplierStrategy<
719
720
  return {
720
721
  extendedAmountInBTC: new Web3Number(0, 0),
721
722
  calls: [],
722
- };;
723
+ };
723
724
  }
724
725
  }
725
726