@strkfarm/sdk 2.0.0-dev.21 → 2.0.0-dev.23

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.
@@ -8,12 +8,21 @@ import {
8
8
  UNIVERSAL_MANAGE_IDS,
9
9
  UniversalStrategySettings,
10
10
  } from "../universal-strategy";
11
- import { calculateExtendedLevergae } from "./utils/helper";
11
+ import { calculateDebtAmount, calculateDeltaDebtAmount, calculateExtendedLevergae } from "./utils/helper";
12
12
  import { logger } from "@/utils";
13
13
  import { AUDIT_URL } from "../universal-lst-muliplier-strategy";
14
14
  import { getNoRiskTags } from "@/interfaces";
15
15
  import { _riskFactor } from "../universal-lst-muliplier-strategy";
16
- import { BUFFER_USDC_IN_WITHDRAWAL, LIMIT_BALANCE, LIMIT_BALANCE_VALUE, MINIMUM_EXTENDED_POSITION_SIZE, USDC_TOKEN_DECIMALS, WALLET_ADDRESS, WBTC_TOKEN_DECIMALS } from "./utils/constants";
16
+ import {
17
+ BUFFER_USDC_IN_WITHDRAWAL,
18
+ LIMIT_BALANCE,
19
+ LIMIT_BALANCE_VALUE,
20
+ MAX_LTV_BTC_USDC,
21
+ MINIMUM_EXTENDED_POSITION_SIZE,
22
+ USDC_TOKEN_DECIMALS,
23
+ WALLET_ADDRESS,
24
+ WBTC_TOKEN_DECIMALS,
25
+ } from "./utils/constants";
17
26
  import { CycleType } from "./types/transaction-metadata";
18
27
  import { PricerBase } from "@/modules/pricerBase";
19
28
  import { ContractAddr, Web3Number } from "@/dataTypes";
@@ -22,7 +31,10 @@ import { ERC20 } from "@/modules";
22
31
  import { Balance, OrderSide } from "@/modules/ExtendedWrapperSDk";
23
32
  import { Protocols } from "@/interfaces";
24
33
  import { MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP } from "./utils/constants";
25
- import { getInvestmentSteps, getFAQs } from "../universal-lst-muliplier-strategy";
34
+ import {
35
+ getInvestmentSteps,
36
+ getFAQs,
37
+ } from "../universal-lst-muliplier-strategy";
26
38
  import { getContractDetails } from "../universal-strategy";
27
39
  import { highlightTextWithLinks } from "@/interfaces";
28
40
  import { PositionInfo } from "../universal-adapters";
@@ -50,13 +62,15 @@ import {
50
62
  calculateAmountDistribution,
51
63
  calculateAmountDistributionForWithdrawal,
52
64
  calculateVesuLeverage,
53
- calculateVesUPositionSizeGivenExtended
65
+ calculateVesUPositionSizeGivenExtended,
54
66
  } from "./utils/helper";
55
67
  import { SingleTokenInfo } from "../base-strategy";
56
68
  import { Call } from "starknet";
57
69
  import { PositionTypeAvnuExtended } from "../universal-strategy";
58
- import { TransactionMetadata, TransactionResult } from "./types/transaction-metadata";
59
-
70
+ import {
71
+ TransactionMetadata,
72
+ TransactionResult,
73
+ } from "./types/transaction-metadata";
60
74
 
61
75
  export interface VesuExtendedStrategySettings
62
76
  extends UniversalStrategySettings {
@@ -71,10 +85,11 @@ export interface VesuExtendedStrategySettings
71
85
  }
72
86
 
73
87
  export class VesuExtendedMultiplierStrategy<
74
- S extends VesuExtendedStrategySettings
75
- >
88
+ S extends VesuExtendedStrategySettings
89
+ >
76
90
  extends SVKStrategy<S>
77
- implements Operations {
91
+ implements Operations
92
+ {
78
93
  constructor(
79
94
  config: IConfig,
80
95
  pricer: PricerBase,
@@ -122,8 +137,7 @@ export class VesuExtendedMultiplierStrategy<
122
137
  usdceToken.decimals
123
138
  );
124
139
  const price = await this.pricer.getPrice(usdceToken.symbol);
125
- const usdValue =
126
- Number(balance.toFixed(usdceToken.decimals)) * price.price;
140
+ const usdValue = Number(balance.toFixed(usdceToken.decimals)) * price.price;
127
141
  return {
128
142
  tokenInfo: usdceToken,
129
143
  amount: balance,
@@ -131,7 +145,6 @@ export class VesuExtendedMultiplierStrategy<
131
145
  };
132
146
  }
133
147
 
134
-
135
148
  async getUnusedBalanceWBTC(): Promise<SingleTokenInfo> {
136
149
  const collateralToken = this.metadata.additionalInfo.borrowable_assets[0]!;
137
150
  const balance = await new ERC20(this.config).balanceOf(
@@ -182,9 +195,12 @@ export class VesuExtendedMultiplierStrategy<
182
195
  return extendedAdapter.adapter as ExtendedAdapter;
183
196
  }
184
197
 
185
- async moveAssetsToVaultAllocator(amount: Web3Number, extendedAdapter: ExtendedAdapter): Promise<{
186
- calls: Call[],
187
- status: boolean,
198
+ async moveAssetsToVaultAllocator(
199
+ amount: Web3Number,
200
+ extendedAdapter: ExtendedAdapter
201
+ ): Promise<{
202
+ calls: Call[];
203
+ status: boolean;
188
204
  }> {
189
205
  try {
190
206
  const usdceToken = Global.getDefaultTokens().find(
@@ -195,12 +211,22 @@ export class VesuExtendedMultiplierStrategy<
195
211
  WALLET_ADDRESS,
196
212
  usdceToken.decimals
197
213
  );
198
- logger.info(`${VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`);
214
+ logger.info(
215
+ `${VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`
216
+ );
199
217
  const amountToBeTransferred = amount.minimum(walletBalance);
200
- logger.info(`${VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`);
201
-
218
+ logger.info(
219
+ `${
220
+ VesuExtendedMultiplierStrategy.name
221
+ }::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`
222
+ );
223
+
202
224
  if (amountToBeTransferred.lessThan(0)) {
203
- logger.error(`${VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`);
225
+ logger.error(
226
+ `${
227
+ VesuExtendedMultiplierStrategy.name
228
+ }::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`
229
+ );
204
230
  return {
205
231
  calls: [],
206
232
  status: false,
@@ -246,12 +272,19 @@ export class VesuExtendedMultiplierStrategy<
246
272
  collateralPrice: number;
247
273
  debtPrice: number;
248
274
  vesuLeverage: number;
275
+ debtAmountToBeRepaid: Web3Number;
249
276
  }> {
250
277
  try {
251
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
278
+ logger.info(
279
+ `${VesuExtendedMultiplierStrategy.name}::shouldInvest starting`
280
+ );
252
281
  const vesuAdapter = await this.getVesuAdapter();
253
282
  const extendedAdapter = await this.getExtendedAdapter();
254
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
283
+ logger.info(
284
+ `${
285
+ VesuExtendedMultiplierStrategy.name
286
+ }::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`
287
+ );
255
288
 
256
289
  if (!vesuAdapter) {
257
290
  logger.error(
@@ -265,6 +298,7 @@ export class VesuExtendedMultiplierStrategy<
265
298
  collateralPrice: 0,
266
299
  debtPrice: 0,
267
300
  vesuLeverage: 0,
301
+ debtAmountToBeRepaid: new Web3Number(0, 0),
268
302
  };
269
303
  }
270
304
  if (!extendedAdapter) {
@@ -279,6 +313,7 @@ export class VesuExtendedMultiplierStrategy<
279
313
  collateralPrice: 0,
280
314
  debtPrice: 0,
281
315
  vesuLeverage: 0,
316
+ debtAmountToBeRepaid: new Web3Number(0, 0),
282
317
  };
283
318
  }
284
319
  if (!extendedAdapter.client) {
@@ -293,10 +328,13 @@ export class VesuExtendedMultiplierStrategy<
293
328
  collateralPrice: 0,
294
329
  debtPrice: 0,
295
330
  vesuLeverage: 0,
331
+ debtAmountToBeRepaid: new Web3Number(0, 0),
296
332
  };
297
333
  }
298
334
 
299
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
335
+ logger.info(
336
+ `${VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`
337
+ );
300
338
  const balance = await this.getUnusedBalance();
301
339
 
302
340
  if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
@@ -311,14 +349,23 @@ export class VesuExtendedMultiplierStrategy<
311
349
  collateralPrice: 0,
312
350
  debtPrice: 0,
313
351
  vesuLeverage: 0,
352
+ debtAmountToBeRepaid: new Web3Number(0, 0),
314
353
  };
315
354
  }
316
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
317
- const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
355
+ logger.info(
356
+ `${VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`
357
+ );
358
+ const usdcBalanceOnExtended =
359
+ await extendedAdapter.getExtendedDepositAmount();
318
360
 
319
361
  if (usdcBalanceOnExtended) {
320
- const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
321
- if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
362
+ const availableForWithdrawal = parseFloat(
363
+ usdcBalanceOnExtended.availableForWithdrawal
364
+ );
365
+ if (
366
+ !Number.isFinite(availableForWithdrawal) ||
367
+ availableForWithdrawal < 0
368
+ ) {
322
369
  logger.error(
323
370
  `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
324
371
  );
@@ -330,13 +377,18 @@ export class VesuExtendedMultiplierStrategy<
330
377
  collateralPrice: 0,
331
378
  debtPrice: 0,
332
379
  vesuLeverage: 0,
380
+ debtAmountToBeRepaid: new Web3Number(0, 0),
333
381
  };
334
382
  }
335
383
  }
336
384
 
337
385
  /** The LIMIT_BALANCE is the bffer amount to keep in the investing Cycle */
338
- const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
339
-
386
+ const amountToInvest = new Web3Number(
387
+ balance.usdValue,
388
+ USDC_TOKEN_DECIMALS
389
+ )
390
+ .plus(usdcBalanceOnExtended?.availableForTrade ?? 0)
391
+ .multipliedBy(1 - LIMIT_BALANCE);
340
392
 
341
393
  const amountToInvestNumber = amountToInvest.toNumber();
342
394
  if (!Number.isFinite(amountToInvestNumber)) {
@@ -351,10 +403,14 @@ export class VesuExtendedMultiplierStrategy<
351
403
  collateralPrice: 0,
352
404
  debtPrice: 0,
353
405
  vesuLeverage: 0,
406
+ debtAmountToBeRepaid: new Web3Number(0, 0),
354
407
  };
355
408
  }
356
409
 
357
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
410
+ logger.info(
411
+ `${VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`
412
+ );
413
+
358
414
  if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
359
415
  return {
360
416
  shouldInvest: false,
@@ -364,6 +420,7 @@ export class VesuExtendedMultiplierStrategy<
364
420
  collateralPrice: 0,
365
421
  debtPrice: 0,
366
422
  vesuLeverage: 0,
423
+ debtAmountToBeRepaid: new Web3Number(0, 0),
367
424
  };
368
425
  }
369
426
 
@@ -378,18 +435,18 @@ export class VesuExtendedMultiplierStrategy<
378
435
  collateralPrice: 0,
379
436
  debtPrice: 0,
380
437
  vesuLeverage: 0,
438
+ debtAmountToBeRepaid: new Web3Number(0, 0),
381
439
  };
382
440
  }
383
- const { collateralTokenAmount } =
441
+ const { collateralTokenAmount, debtTokenAmount } =
384
442
  await vesuAdapter.vesuAdapter.getAssetPrices();
385
443
 
386
- const {
387
- collateralPrice,
388
- debtPrice
389
- } = await this.getAssetPrices();
444
+ const { collateralPrice, debtPrice } = await this.getAssetPrices();
390
445
 
391
-
392
- if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
446
+ if (
447
+ !Number.isFinite(collateralPrice.price) ||
448
+ collateralPrice.price <= 0
449
+ ) {
393
450
  logger.error(
394
451
  `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
395
452
  );
@@ -401,6 +458,7 @@ export class VesuExtendedMultiplierStrategy<
401
458
  collateralPrice: 0,
402
459
  debtPrice: 0,
403
460
  vesuLeverage: 0,
461
+ debtAmountToBeRepaid: new Web3Number(0, 0),
404
462
  };
405
463
  }
406
464
  if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
@@ -415,12 +473,35 @@ export class VesuExtendedMultiplierStrategy<
415
473
  collateralPrice: 0,
416
474
  debtPrice: 0,
417
475
  vesuLeverage: 0,
476
+ debtAmountToBeRepaid: new Web3Number(0, 0),
418
477
  };
419
478
  }
420
479
 
480
+ const debtAmountToBeRepaid = calculateDeltaDebtAmount(
481
+ MAX_LTV_BTC_USDC,
482
+ collateralTokenAmount,
483
+ debtTokenAmount,
484
+ collateralPrice.price,
485
+ debtPrice.price,
486
+ this.metadata.additionalInfo.targetHealthFactor
487
+ );
488
+ if (!debtAmountToBeRepaid) {
489
+ logger.error("error calculating debt amount to be repaid");
490
+ return {
491
+ shouldInvest: false,
492
+ vesuAmount: new Web3Number(0, 0),
493
+ extendedAmount: new Web3Number(0, 0),
494
+ extendedLeverage: 0,
495
+ collateralPrice: 0,
496
+ debtPrice: 0,
497
+ vesuLeverage: 0,
498
+ debtAmountToBeRepaid: new Web3Number(0, 0),
499
+ };
500
+ }
501
+ const amountToInvestAfterRepayingDebt = amountToInvest.minus(debtAmountToBeRepaid);
421
502
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } =
422
503
  await calculateAmountDistribution(
423
- amountToInvest.toNumber(),
504
+ amountToInvestAfterRepayingDebt.toNumber(),
424
505
  extendedAdapter.client,
425
506
  extendedAdapter.config.extendedMarketName,
426
507
  collateralPrice.price,
@@ -445,9 +526,14 @@ export class VesuExtendedMultiplierStrategy<
445
526
  collateralPrice: 0,
446
527
  debtPrice: 0,
447
528
  vesuLeverage: 0,
529
+ debtAmountToBeRepaid: new Web3Number(0, 0),
448
530
  };
449
531
  }
450
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
532
+ logger.info(
533
+ `${
534
+ VesuExtendedMultiplierStrategy.name
535
+ }::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`
536
+ );
451
537
  return {
452
538
  shouldInvest: true,
453
539
  vesuAmount: vesu_amount,
@@ -456,6 +542,7 @@ export class VesuExtendedMultiplierStrategy<
456
542
  vesuLeverage: vesu_leverage,
457
543
  collateralPrice: collateralPrice.price,
458
544
  debtPrice: debtPrice.price,
545
+ debtAmountToBeRepaid: debtAmountToBeRepaid,
459
546
  };
460
547
  } catch (err) {
461
548
  logger.error(`error deciding invest: ${err}`);
@@ -467,11 +554,15 @@ export class VesuExtendedMultiplierStrategy<
467
554
  collateralPrice: 0,
468
555
  debtPrice: 0,
469
556
  vesuLeverage: 0,
557
+ debtAmountToBeRepaid: new Web3Number(0, 0),
470
558
  };
471
559
  }
472
560
  }
473
561
 
474
- async shouldMoveAssets(extendedAmount: Web3Number, vesuAmount: Web3Number): Promise<TransactionResult[]> {
562
+ async shouldMoveAssets(
563
+ extendedAmount: Web3Number,
564
+ vesuAmount: Web3Number
565
+ ): Promise<TransactionResult[]> {
475
566
  try {
476
567
  const vesuAdapter = await this.getVesuAdapter();
477
568
  const extendedAdapter = await this.getExtendedAdapter();
@@ -488,37 +579,58 @@ export class VesuExtendedMultiplierStrategy<
488
579
  return [];
489
580
  }
490
581
  const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
491
- const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
492
- extendedHoldings.availableForWithdrawal
582
+ /**
583
+ * Trade is the correct metric, since we can close position for some vesu amount, otherwise underutilisation of funds will be a huge issue
584
+ */
585
+ const usdcAmountOnExtendedAvailableForTrade = parseFloat(
586
+ extendedHoldings.availableForTrade
493
587
  );
494
588
 
495
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
589
+ logger.info(
590
+ `${
591
+ VesuExtendedMultiplierStrategy.name
592
+ }::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForTrade}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`
593
+ );
496
594
 
497
595
  let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
498
596
  let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
499
597
 
500
- if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
501
- totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
598
+ if (
599
+ extendedAmount.isNegative() &&
600
+ extendedAmount
601
+ .abs()
602
+ .greaterThan(extendedAdapter.minimumExtendedMovementAmount)
603
+ ) {
604
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(
605
+ extendedAmount.abs()
606
+ );
502
607
  }
503
608
 
504
609
  // Calculate remaining Extended difference (target vs current)
505
610
  // If extendedAmount was negative, we've already accounted for that withdrawal
506
611
  // So we calculate based on what Extended will be after that withdrawal
507
612
  const extendedTargetAmount = extendedAmount.abs(); // Use absolute value as target
508
- let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
613
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForTrade;
509
614
 
510
615
  if (extendedAmount.isNegative()) {
511
- projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
616
+ projectedExtendedBalance =
617
+ projectedExtendedBalance - extendedAmount.abs().toNumber();
512
618
  }
513
619
 
514
- const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
620
+ const extendedAmountDifference = extendedTargetAmount.minus(
621
+ projectedExtendedBalance
622
+ );
515
623
  const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
516
624
 
517
625
  // Track additional Extended movements
518
626
  if (extendedAmountDifference.lessThan(0)) {
519
- totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
627
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(
628
+ extendedAmountDifferenceAbs
629
+ );
520
630
  } else if (extendedAmountDifference.greaterThan(0)) {
521
- totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
631
+ totalExtendedDeposit = totalExtendedDeposit.plus(
632
+ extendedAmountDifference
633
+ );
522
634
  }
523
635
 
524
636
  const vesuTargetAmount = vesuAmount.abs();
@@ -529,19 +641,31 @@ export class VesuExtendedMultiplierStrategy<
529
641
  let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
530
642
  const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
531
643
 
532
- logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`);
533
- let calls: Call[] = [];
644
+ logger.info(
645
+ `${
646
+ VesuExtendedMultiplierStrategy.name
647
+ }::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`
648
+ );
534
649
  let transactionResults: TransactionResult[] = [];
535
650
 
536
651
  // Handle negative extendedAmount (initial withdrawal needed)
537
- if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
652
+ if (
653
+ extendedAmount.isNegative() &&
654
+ extendedAmount
655
+ .abs()
656
+ .greaterThan(extendedAdapter.minimumExtendedMovementAmount)
657
+ ) {
538
658
  try {
539
- const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
659
+ const {
660
+ calls: extendedCalls,
661
+ status: extendedStatus,
662
+ transactionMetadata: extendedTransactionMetadata,
663
+ } = await this.moveAssets(
540
664
  {
541
665
  to: Protocols.VAULT.name,
542
666
  from: Protocols.EXTENDED.name,
543
667
  amount: extendedAmount.abs(),
544
- cycleType: CycleType.INVESTMENT
668
+ cycleType: CycleType.INVESTMENT,
545
669
  },
546
670
  extendedAdapter,
547
671
  vesuAdapter
@@ -554,30 +678,73 @@ export class VesuExtendedMultiplierStrategy<
554
678
  ...extendedTransactionMetadata,
555
679
  transactionType: "DEPOSIT",
556
680
  },
557
- })
681
+ });
558
682
  } else {
559
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", CycleType.INVESTMENT)];
683
+ return [
684
+ this.createTransactionResult(
685
+ [],
686
+ false,
687
+ {
688
+ from: Protocols.EXTENDED.name,
689
+ to: Protocols.VAULT.name,
690
+ amount: extendedAmount.abs(),
691
+ },
692
+ "NONE",
693
+ CycleType.INVESTMENT
694
+ ),
695
+ ];
560
696
  }
561
697
  } catch (err) {
562
698
  logger.error(`Failed moving assets to vault: ${err}`);
563
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", CycleType.INVESTMENT)];
699
+ return [
700
+ this.createTransactionResult(
701
+ [],
702
+ false,
703
+ {
704
+ from: Protocols.EXTENDED.name,
705
+ to: Protocols.VAULT.name,
706
+ amount: extendedAmount.abs(),
707
+ },
708
+ "NONE",
709
+ CycleType.INVESTMENT
710
+ ),
711
+ ];
564
712
  }
565
713
  }
566
714
 
567
- if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
715
+ if (
716
+ vesuAmount.isNegative() &&
717
+ vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)
718
+ ) {
568
719
  try {
569
- const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
720
+ const {
721
+ calls: vesuCalls,
722
+ status: vesuStatus,
723
+ transactionMetadata: vesuTransactionMetadata,
724
+ } = await this.moveAssets(
570
725
  {
571
726
  to: Protocols.EXTENDED.name,
572
727
  from: Protocols.VESU.name,
573
728
  amount: vesuAmount.abs(),
574
- cycleType: CycleType.INVESTMENT
729
+ cycleType: CycleType.INVESTMENT,
575
730
  },
576
731
  extendedAdapter,
577
732
  vesuAdapter
578
733
  );
579
734
  if (!vesuStatus) {
580
- return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", CycleType.INVESTMENT)];
735
+ return [
736
+ this.createTransactionResult(
737
+ [],
738
+ false,
739
+ {
740
+ from: Protocols.VESU.name,
741
+ to: Protocols.EXTENDED.name,
742
+ amount: vesuAmount.abs(),
743
+ },
744
+ "NONE",
745
+ CycleType.INVESTMENT
746
+ ),
747
+ ];
581
748
  }
582
749
  transactionResults.push({
583
750
  status: vesuStatus,
@@ -585,24 +752,46 @@ export class VesuExtendedMultiplierStrategy<
585
752
  transactionMetadata: {
586
753
  ...vesuTransactionMetadata,
587
754
  transactionType: "DEPOSIT",
588
- }
589
- })
755
+ },
756
+ });
590
757
  } catch (err) {
591
- logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
592
- return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", CycleType.INVESTMENT)];
758
+ logger.error(
759
+ `Failed moving assets to extended via vault allocator: ${err}`
760
+ );
761
+ return [
762
+ this.createTransactionResult(
763
+ [],
764
+ false,
765
+ {
766
+ from: Protocols.VESU.name,
767
+ to: Protocols.EXTENDED.name,
768
+ amount: vesuAmount.abs(),
769
+ },
770
+ "NONE",
771
+ CycleType.INVESTMENT
772
+ ),
773
+ ];
593
774
  }
594
775
  }
595
776
 
596
777
  // Handle Extended adjustments based on calculated difference
597
- if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
778
+ if (
779
+ extendedAmountDifferenceAbs.greaterThan(
780
+ extendedAdapter.minimumExtendedMovementAmount
781
+ )
782
+ ) {
598
783
  if (extendedAmountDifference.greaterThan(0)) {
599
784
  try {
600
- const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
785
+ const {
786
+ calls: extendedCalls,
787
+ status: extendedStatus,
788
+ transactionMetadata: extendedTransactionMetadata,
789
+ } = await this.moveAssets(
601
790
  {
602
791
  to: Protocols.EXTENDED.name,
603
792
  from: Protocols.VAULT.name,
604
793
  amount: extendedAmountDifference,
605
- cycleType: CycleType.INVESTMENT
794
+ cycleType: CycleType.INVESTMENT,
606
795
  },
607
796
  extendedAdapter,
608
797
  vesuAdapter
@@ -611,24 +800,54 @@ export class VesuExtendedMultiplierStrategy<
611
800
  transactionResults.push({
612
801
  status: extendedStatus,
613
802
  calls: extendedCalls,
614
- transactionMetadata: extendedTransactionMetadata
615
- })
803
+ transactionMetadata: extendedTransactionMetadata,
804
+ });
616
805
  } else {
617
- logger.error(`Failed to move assets to extended - operation returned false status`);
618
- return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", CycleType.INVESTMENT)];
806
+ logger.error(
807
+ `Failed to move assets to extended - operation returned false status`
808
+ );
809
+ return [
810
+ this.createTransactionResult(
811
+ [],
812
+ false,
813
+ {
814
+ from: Protocols.VAULT.name,
815
+ to: Protocols.EXTENDED.name,
816
+ amount: extendedAmountDifference,
817
+ },
818
+ "NONE",
819
+ CycleType.INVESTMENT
820
+ ),
821
+ ];
619
822
  }
620
823
  } catch (err) {
621
824
  logger.error(`Failed moving assets to extended: ${err}`);
622
- return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", CycleType.INVESTMENT)];
825
+ return [
826
+ this.createTransactionResult(
827
+ [],
828
+ false,
829
+ {
830
+ from: Protocols.VAULT.name,
831
+ to: Protocols.EXTENDED.name,
832
+ amount: extendedAmountDifference,
833
+ },
834
+ "NONE",
835
+ CycleType.INVESTMENT
836
+ ),
837
+ ];
623
838
  }
624
839
  } else if (extendedAmountDifference.lessThan(0)) {
625
840
  try {
626
- const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
841
+ const {
842
+ calls: extendedCalls,
843
+ status: extendedStatus,
844
+ transactionMetadata: extendedTransactionMetadata,
845
+ } = await this.moveAssets(
627
846
  {
628
847
  to: Protocols.VAULT.name,
629
848
  from: Protocols.EXTENDED.name,
630
849
  amount: extendedAmountDifferenceAbs,
631
- cycleType: CycleType.INVESTMENT
850
+ cycleType: CycleType.INVESTMENT,
632
851
  },
633
852
  extendedAdapter,
634
853
  vesuAdapter
@@ -640,21 +859,51 @@ export class VesuExtendedMultiplierStrategy<
640
859
  transactionMetadata: {
641
860
  ...extendedTransactionMetadata,
642
861
  transactionType: "DEPOSIT",
643
- }
644
- })
862
+ },
863
+ });
645
864
  } else {
646
- logger.error(`Failed to withdraw from extended - operation returned false status`);
647
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", CycleType.INVESTMENT)];
865
+ logger.error(
866
+ `Failed to withdraw from extended - operation returned false status`
867
+ );
868
+ return [
869
+ this.createTransactionResult(
870
+ [],
871
+ false,
872
+ {
873
+ from: Protocols.EXTENDED.name,
874
+ to: Protocols.VAULT.name,
875
+ amount: extendedAmountDifferenceAbs,
876
+ },
877
+ "NONE",
878
+ CycleType.INVESTMENT
879
+ ),
880
+ ];
648
881
  }
649
882
  } catch (err) {
650
883
  logger.error(`Failed moving assets from extended to vault: ${err}`);
651
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", CycleType.INVESTMENT)];
884
+ return [
885
+ this.createTransactionResult(
886
+ [],
887
+ false,
888
+ {
889
+ from: Protocols.EXTENDED.name,
890
+ to: Protocols.VAULT.name,
891
+ amount: extendedAmountDifferenceAbs,
892
+ },
893
+ "NONE",
894
+ CycleType.INVESTMENT
895
+ ),
896
+ ];
652
897
  }
653
898
  }
654
899
  }
655
900
 
656
901
  // Handle Vesu adjustments based on calculated difference (already adjusted for Extended movements)
657
- if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
902
+ if (
903
+ vesuAmountDifferenceAbs.greaterThan(
904
+ vesuAdapter.minimumVesuMovementAmount
905
+ )
906
+ ) {
658
907
  if (vesuAmountDifference.lessThanOrEqualTo(0)) {
659
908
  logger.warn(
660
909
  `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
@@ -662,19 +911,37 @@ export class VesuExtendedMultiplierStrategy<
662
911
  } else {
663
912
  // Move assets from Extended to Vault (which will then go to Vesu)
664
913
  try {
665
- const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
914
+ const {
915
+ calls: vesuCalls,
916
+ status: vesuStatus,
917
+ transactionMetadata: vesuTransactionMetadata,
918
+ } = await this.moveAssets(
666
919
  {
667
920
  to: Protocols.VAULT.name,
668
921
  from: Protocols.EXTENDED.name,
669
922
  amount: vesuAmountDifference,
670
- cycleType: CycleType.INVESTMENT
923
+ cycleType: CycleType.INVESTMENT,
671
924
  },
672
925
  extendedAdapter,
673
926
  vesuAdapter
674
927
  );
675
928
  if (!vesuStatus) {
676
- logger.error(`Failed to move assets to vesu - operation returned false status`);
677
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", CycleType.INVESTMENT)];
929
+ logger.error(
930
+ `Failed to move assets to vesu - operation returned false status`
931
+ );
932
+ return [
933
+ this.createTransactionResult(
934
+ [],
935
+ false,
936
+ {
937
+ from: Protocols.EXTENDED.name,
938
+ to: Protocols.VAULT.name,
939
+ amount: vesuAmountDifference,
940
+ },
941
+ "NONE",
942
+ CycleType.INVESTMENT
943
+ ),
944
+ ];
678
945
  }
679
946
  transactionResults.push({
680
947
  status: vesuStatus,
@@ -682,19 +949,42 @@ export class VesuExtendedMultiplierStrategy<
682
949
  transactionMetadata: {
683
950
  ...vesuTransactionMetadata,
684
951
  transactionType: "DEPOSIT",
685
- }
686
- })
952
+ },
953
+ });
687
954
  } catch (err) {
688
955
  logger.error(`Failed moving assets to vault: ${err}`);
689
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", CycleType.INVESTMENT)];
956
+ return [
957
+ this.createTransactionResult(
958
+ [],
959
+ false,
960
+ {
961
+ from: Protocols.EXTENDED.name,
962
+ to: Protocols.VAULT.name,
963
+ amount: vesuAmountDifference,
964
+ },
965
+ "NONE",
966
+ CycleType.INVESTMENT
967
+ ),
968
+ ];
690
969
  }
691
970
  }
692
971
  }
693
-
694
972
  return transactionResults;
695
973
  } catch (err) {
696
974
  logger.error(`Failed moving assets to vesu: ${err}`);
697
- return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE", CycleType.INVESTMENT)];
975
+ return [
976
+ this.createTransactionResult(
977
+ [],
978
+ false,
979
+ {
980
+ from: Protocols.EXTENDED.name,
981
+ to: Protocols.VAULT.name,
982
+ amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
983
+ },
984
+ "NONE",
985
+ CycleType.INVESTMENT
986
+ ),
987
+ ];
698
988
  }
699
989
  }
700
990
 
@@ -705,7 +995,7 @@ export class VesuExtendedMultiplierStrategy<
705
995
  calls: Call[],
706
996
  status: boolean,
707
997
  params: { from: string; to: string; amount: Web3Number },
708
- transactionType: 'DEPOSIT' | 'WITHDRAWAL' | 'NONE',
998
+ transactionType: "DEPOSIT" | "WITHDRAWAL" | "NONE",
709
999
  cycleType: CycleType
710
1000
  ): TransactionResult {
711
1001
  if (status) {
@@ -717,14 +1007,34 @@ export class VesuExtendedMultiplierStrategy<
717
1007
  protocolTo: params.to,
718
1008
  transactionType: transactionType,
719
1009
  usdAmount: params.amount.abs().toFixed(),
720
- status: 'PENDING',
721
- cycleType: cycleType
722
- }
1010
+ status: "PENDING",
1011
+ cycleType: cycleType,
1012
+ },
723
1013
  };
724
1014
  }
725
- return { calls: [], status: false, transactionMetadata: { protocolFrom: '', protocolTo: '', transactionType: 'DEPOSIT', usdAmount: '0', status: 'FAILED', cycleType: cycleType } };
1015
+ return {
1016
+ calls: [],
1017
+ status: false,
1018
+ transactionMetadata: {
1019
+ protocolFrom: "",
1020
+ protocolTo: "",
1021
+ transactionType: "DEPOSIT",
1022
+ usdAmount: "0",
1023
+ status: "FAILED",
1024
+ cycleType: cycleType,
1025
+ },
1026
+ };
726
1027
  }
727
1028
 
1029
+ /**
1030
+ * This method is used to move assets between protocols
1031
+ * @param params - The parameters for the move assets operation
1032
+ * @param extendedAdapter - The extended adapter
1033
+ * @param vesuAdapter - The vesu adapter
1034
+ * @returns The transaction result
1035
+ * If Extended amount is greater than amount of withdrawal from extended, then we need to open a long position
1036
+ * so that the amount of withdrawal from extended is fullfilled
1037
+ */
728
1038
  async moveAssets(
729
1039
  params: {
730
1040
  amount: Web3Number;
@@ -733,7 +1043,7 @@ export class VesuExtendedMultiplierStrategy<
733
1043
  cycleType: CycleType;
734
1044
  },
735
1045
  extendedAdapter: ExtendedAdapter,
736
- vesuAdapter: VesuMultiplyAdapter,
1046
+ vesuAdapter: VesuMultiplyAdapter
737
1047
  ): Promise<TransactionResult> {
738
1048
  try {
739
1049
  // Validate amount is positive before starting operations
@@ -741,40 +1051,53 @@ export class VesuExtendedMultiplierStrategy<
741
1051
  logger.error(
742
1052
  `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
743
1053
  );
744
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1054
+ return this.createTransactionResult(
1055
+ [],
1056
+ false,
1057
+ params,
1058
+ "NONE",
1059
+ params.cycleType
1060
+ );
745
1061
  }
746
1062
 
747
1063
  // Check minimum movement amounts before starting operations
748
- const amountAbs = params.amount.abs();
749
- if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
750
- if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
751
- logger.warn(
752
- `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
753
- );
754
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
755
- }
756
- }
757
- if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
758
- if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
759
- logger.warn(
760
- `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
761
- );
762
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
763
- }
764
- }
1064
+ // const amountAbs = params.amount.abs();
1065
+ // if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
1066
+ // if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
1067
+ // logger.warn(
1068
+ // `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
1069
+ // );
1070
+ // return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1071
+ // }
1072
+ // }
1073
+ // if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
1074
+ // if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
1075
+ // logger.warn(
1076
+ // `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
1077
+ // );
1078
+ // return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1079
+ // }
1080
+ // }
765
1081
 
766
1082
  const avnuAdapter = await this.getAvnuAdapter();
767
1083
  if (!avnuAdapter) {
768
1084
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
769
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1085
+ return this.createTransactionResult(
1086
+ [],
1087
+ false,
1088
+ params,
1089
+ "NONE",
1090
+ params.cycleType
1091
+ );
770
1092
  }
771
1093
  logger.info(`moveAssets params, ${JSON.stringify(params)}`);
772
1094
  const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
773
- const {
774
- collateralPrice,
775
- } = await this.getAssetPrices();
1095
+ const { collateralPrice } = await this.getAssetPrices();
776
1096
 
777
- if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VAULT.name) {
1097
+ if (
1098
+ params.to === Protocols.EXTENDED.name &&
1099
+ params.from === Protocols.VAULT.name
1100
+ ) {
778
1101
  const proofsInfo = extendedAdapter.getProofs(
779
1102
  true,
780
1103
  this.getMerkleTree()
@@ -786,84 +1109,204 @@ export class VesuExtendedMultiplierStrategy<
786
1109
  await proofsInfo.callConstructor({ amount: params.amount })
787
1110
  );
788
1111
  calls.push(call);
789
- return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
790
- } else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
1112
+ return this.createTransactionResult(
1113
+ calls,
1114
+ true,
1115
+ params,
1116
+ "DEPOSIT",
1117
+ params.cycleType
1118
+ );
1119
+ } else if (
1120
+ params.to === Protocols.VAULT.name &&
1121
+ params.from === Protocols.EXTENDED.name
1122
+ ) {
791
1123
  const extendedLeverage = calculateExtendedLevergae();
792
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
1124
+ const extendedHoldings =
1125
+ await extendedAdapter.getExtendedDepositAmount();
793
1126
  if (!extendedHoldings) {
794
1127
  logger.error(`error getting extended holdings: ${extendedHoldings}`);
795
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1128
+ return this.createTransactionResult(
1129
+ [],
1130
+ false,
1131
+ params,
1132
+ "NONE",
1133
+ params.cycleType
1134
+ );
796
1135
  }
797
1136
  const extendedHoldingAmount = new Web3Number(
798
1137
  extendedHoldings.availableForWithdrawal,
799
1138
  USDC_TOKEN_DECIMALS
800
1139
  );
801
- logger.info(`${VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
1140
+ logger.info(
1141
+ `${
1142
+ VesuExtendedMultiplierStrategy.name
1143
+ }::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`
1144
+ );
802
1145
  if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
803
- const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
804
- logger.info(`${VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
805
- const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
806
- const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
807
- extendedLeverage.toString(),
808
- btcAmount.toNumber(),
809
- OrderSide.BUY
810
- ) : await extendedAdapter.createOrder(
811
- extendedLeverage.toString(),
812
- 0.000034, // just in case amount falls short then we need to create a withdrawal
813
- OrderSide.BUY
814
- )
1146
+ const leftAmountAfterWithdrawalAmountInAccount = new Web3Number(
1147
+ Math.ceil(
1148
+ params.amount.abs().minus(extendedHoldingAmount).toNumber()
1149
+ ),
1150
+ USDC_TOKEN_DECIMALS
1151
+ );
1152
+ logger.info(
1153
+ `${
1154
+ VesuExtendedMultiplierStrategy.name
1155
+ }::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`
1156
+ );
1157
+ let priceOfBTC;
1158
+ const { ask, bid, status } =
1159
+ await extendedAdapter.fetchOrderBookBTCUSDC();
1160
+ const price = ask.plus(bid).dividedBy(2);
1161
+ if (status) {
1162
+ priceOfBTC = price;
1163
+ } else {
1164
+ logger.error(`error fetching order book btc usdc: ${status}`);
1165
+ priceOfBTC = collateralPrice.price;
1166
+ }
1167
+ const btcAmount =
1168
+ leftAmountAfterWithdrawalAmountInAccount.dividedBy(priceOfBTC);
1169
+ /**
1170
+ * If amount for withdrawal is greater than the amount in extended available for withdrawal,
1171
+ * then we need to open a long position depending on the difference between the two
1172
+ */
1173
+ const openLongPosition = btcAmount
1174
+ .multipliedBy(3)
1175
+ .greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)
1176
+ ? await extendedAdapter.createOrder(
1177
+ extendedLeverage.toString(),
1178
+ btcAmount.toNumber(),
1179
+ OrderSide.BUY
1180
+ )
1181
+ : await extendedAdapter.createOrder(
1182
+ extendedLeverage.toString(),
1183
+ 0.000034, // just in case amount falls short then we need to create a withdrawal
1184
+ OrderSide.BUY
1185
+ );
815
1186
  if (!openLongPosition) {
816
1187
  logger.error(`error opening long position: ${openLongPosition}`);
817
1188
  }
818
- const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
819
- if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
820
- logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
821
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1189
+ const updatedHoldings =
1190
+ await extendedAdapter.getExtendedDepositAmount();
1191
+ if (
1192
+ !updatedHoldings ||
1193
+ new Web3Number(
1194
+ updatedHoldings.availableForWithdrawal,
1195
+ USDC_TOKEN_DECIMALS
1196
+ ).lessThan(params.amount.abs())
1197
+ ) {
1198
+ logger.error(
1199
+ `Insufficient balance after opening position. Available: ${
1200
+ updatedHoldings?.availableForWithdrawal
1201
+ }, Needed: ${params.amount.abs()}`
1202
+ );
1203
+ return this.createTransactionResult(
1204
+ [],
1205
+ false,
1206
+ params,
1207
+ "NONE",
1208
+ params.cycleType
1209
+ );
822
1210
  }
823
1211
  }
824
1212
  const {
825
1213
  status: withdrawalFromExtendedStatus,
826
1214
  receivedTxnHash: withdrawalFromExtendedTxnHash,
827
- } =
828
- await extendedAdapter.withdrawFromExtended(params.amount);
1215
+ } = await extendedAdapter.withdrawFromExtended(params.amount);
829
1216
  /**
830
1217
  * This logic needs fixing
831
1218
  */
832
- logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
1219
+ logger.info(
1220
+ `withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`
1221
+ );
833
1222
  if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
834
1223
  /**
835
- * We need to move assets from my wallet back to vault contract
836
- */
837
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
838
- logger.info(`extendedHoldings after withdrawal ${extendedHoldings?.availableForWithdrawal}`);
839
- await new Promise(resolve => setTimeout(resolve, 5000));
840
- const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
1224
+ * We need to move assets from my wallet back to vault contract
1225
+ */
1226
+ const extendedHoldings =
1227
+ await extendedAdapter.getExtendedDepositAmount();
1228
+ logger.info(
1229
+ `extendedHoldings after withdrawal ${extendedHoldings?.availableForWithdrawal}`
1230
+ );
1231
+ await new Promise((resolve) => setTimeout(resolve, 5000));
1232
+ const { calls, status } = await this.moveAssetsToVaultAllocator(
1233
+ params.amount,
1234
+ extendedAdapter
1235
+ );
841
1236
  if (calls.length > 0 && status) {
842
- return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
1237
+ return this.createTransactionResult(
1238
+ calls,
1239
+ true,
1240
+ params,
1241
+ "WITHDRAWAL",
1242
+ params.cycleType
1243
+ );
843
1244
  } else {
844
1245
  /**
845
1246
  * This is a fallback scenario, where the funds were withdrawn from extended, but didn't get transferred to the wallet
846
1247
  * We need to return a successful transaction result, but with no calls
847
1248
  * Db update will be handled by the risk engine for this specific case
848
1249
  */
849
- return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
1250
+ return this.createTransactionResult(
1251
+ [],
1252
+ true,
1253
+ params,
1254
+ "WITHDRAWAL",
1255
+ params.cycleType
1256
+ );
850
1257
  }
851
- } else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
852
- logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
853
- return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
1258
+ } else if (
1259
+ withdrawalFromExtendedStatus &&
1260
+ !withdrawalFromExtendedTxnHash
1261
+ ) {
1262
+ logger.error(
1263
+ "withdrawal from extended successful, but funds didn't get transferred to the wallet"
1264
+ );
1265
+ return this.createTransactionResult(
1266
+ [],
1267
+ true,
1268
+ params,
1269
+ "WITHDRAWAL",
1270
+ params.cycleType
1271
+ );
854
1272
  } else {
855
1273
  logger.error("withdrawal from extended failed");
856
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1274
+ return this.createTransactionResult(
1275
+ [],
1276
+ false,
1277
+ params,
1278
+ "NONE",
1279
+ params.cycleType
1280
+ );
857
1281
  }
858
- } else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
859
- const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, PositionTypeAvnuExtended.CLOSE);
1282
+ } else if (
1283
+ params.to === Protocols.VAULT.name &&
1284
+ params.from === Protocols.VESU.name
1285
+ ) {
1286
+ const isPriceDifferenceBetweenAvnuAndExtended =
1287
+ await this.checkPriceDifferenceBetweenAvnuAndExtended(
1288
+ extendedAdapter,
1289
+ vesuAdapter,
1290
+ avnuAdapter,
1291
+ PositionTypeAvnuExtended.CLOSE
1292
+ );
860
1293
  if (!isPriceDifferenceBetweenAvnuAndExtended) {
861
- logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
862
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1294
+ logger.warn(
1295
+ `price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`
1296
+ );
1297
+ return this.createTransactionResult(
1298
+ [],
1299
+ false,
1300
+ params,
1301
+ "NONE",
1302
+ params.cycleType
1303
+ );
863
1304
  }
864
- //withdraw from vesu
1305
+ //withdraw from vesu
865
1306
  const vesuAmountInBTC = new Web3Number(
866
- params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
1307
+ params.amount
1308
+ .dividedBy(collateralPrice.price)
1309
+ .toFixed(WBTC_TOKEN_DECIMALS),
867
1310
  collateralToken.decimals
868
1311
  );
869
1312
  const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
@@ -874,19 +1317,45 @@ export class VesuExtendedMultiplierStrategy<
874
1317
  await proofsInfo.callConstructor({ amount: vesuAmountInBTC })
875
1318
  );
876
1319
  calls.push(call);
877
- const swapProofsInfo = avnuAdapter.getProofs(false, this.getMerkleTree());
1320
+ const swapProofsInfo = avnuAdapter.getProofs(
1321
+ false,
1322
+ this.getMerkleTree()
1323
+ );
878
1324
  const swapProofGroups = swapProofsInfo.proofs;
879
1325
  const swapCall = this.getManageCall(
880
1326
  swapProofGroups,
881
1327
  await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
882
1328
  );
883
1329
  calls.push(swapCall);
884
- return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
885
- } else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
886
- const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, PositionTypeAvnuExtended.CLOSE);
1330
+ return this.createTransactionResult(
1331
+ calls,
1332
+ true,
1333
+ params,
1334
+ "WITHDRAWAL",
1335
+ params.cycleType
1336
+ );
1337
+ } else if (
1338
+ params.to === Protocols.EXTENDED.name &&
1339
+ params.from === Protocols.VESU.name
1340
+ ) {
1341
+ const isPriceDifferenceBetweenAvnuAndExtended =
1342
+ await this.checkPriceDifferenceBetweenAvnuAndExtended(
1343
+ extendedAdapter,
1344
+ vesuAdapter,
1345
+ avnuAdapter,
1346
+ PositionTypeAvnuExtended.CLOSE
1347
+ );
887
1348
  if (!isPriceDifferenceBetweenAvnuAndExtended) {
888
- logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
889
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1349
+ logger.warn(
1350
+ `price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`
1351
+ );
1352
+ return this.createTransactionResult(
1353
+ [],
1354
+ false,
1355
+ params,
1356
+ "NONE",
1357
+ params.cycleType
1358
+ );
890
1359
  }
891
1360
  const vesuAmountInBTC = new Web3Number(
892
1361
  params.amount.dividedBy(collateralPrice.price).toNumber(),
@@ -900,7 +1369,10 @@ export class VesuExtendedMultiplierStrategy<
900
1369
  await proofsInfo.callConstructor({ amount: vesuAmountInBTC })
901
1370
  );
902
1371
  calls.push(call);
903
- const swapProofsInfo = avnuAdapter.getProofs(false, this.getMerkleTree());
1372
+ const swapProofsInfo = avnuAdapter.getProofs(
1373
+ false,
1374
+ this.getMerkleTree()
1375
+ );
904
1376
  const swapProofGroups = swapProofsInfo.proofs;
905
1377
  const swapCall = this.getManageCall(
906
1378
  swapProofGroups,
@@ -918,13 +1390,33 @@ export class VesuExtendedMultiplierStrategy<
918
1390
  await proofsInfoDeposit.callConstructor({ amount: params.amount })
919
1391
  );
920
1392
  calls.push(callDeposit);
921
- return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
1393
+ return this.createTransactionResult(
1394
+ calls,
1395
+ true,
1396
+ params,
1397
+ "DEPOSIT",
1398
+ params.cycleType
1399
+ );
922
1400
  }
923
- logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
924
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1401
+ logger.error(
1402
+ `Unsupported assets movement: ${params.from} to ${params.to}`
1403
+ );
1404
+ return this.createTransactionResult(
1405
+ [],
1406
+ false,
1407
+ params,
1408
+ "NONE",
1409
+ params.cycleType
1410
+ );
925
1411
  } catch (err) {
926
1412
  logger.error(`error moving assets: ${err}`);
927
- return this.createTransactionResult([], false, params, "NONE", params.cycleType);
1413
+ return this.createTransactionResult(
1414
+ [],
1415
+ false,
1416
+ params,
1417
+ "NONE",
1418
+ params.cycleType
1419
+ );
928
1420
  }
929
1421
  }
930
1422
 
@@ -933,14 +1425,33 @@ export class VesuExtendedMultiplierStrategy<
933
1425
  /**
934
1426
  * Just a demo function, not used in the risk engine
935
1427
  */
936
- return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", CycleType.INVESTMENT);
1428
+ return this.createTransactionResult(
1429
+ [],
1430
+ false,
1431
+ {
1432
+ from: Protocols.VAULT.name,
1433
+ to: Protocols.VAULT.name,
1434
+ amount: new Web3Number(0, 0),
1435
+ },
1436
+ "NONE",
1437
+ CycleType.INVESTMENT
1438
+ );
937
1439
  } catch (err) {
938
1440
  logger.error(`error handling deposit: ${err}`);
939
- return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", CycleType.INVESTMENT);
1441
+ return this.createTransactionResult(
1442
+ [],
1443
+ false,
1444
+ {
1445
+ from: Protocols.VAULT.name,
1446
+ to: Protocols.VAULT.name,
1447
+ amount: new Web3Number(0, 0),
1448
+ },
1449
+ "NONE",
1450
+ CycleType.INVESTMENT
1451
+ );
940
1452
  }
941
1453
  }
942
1454
 
943
-
944
1455
  /**
945
1456
  * Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
946
1457
  * @param extendedAdapter - the extended adapter
@@ -949,13 +1460,18 @@ export class VesuExtendedMultiplierStrategy<
949
1460
  * @param positionType - the position type (open or close)
950
1461
  * @returns true if the price difference is within the acceptable range, false otherwise
951
1462
  */
952
- async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter: ExtendedAdapter, vesuAdapter: VesuMultiplyAdapter, avnuAdapter: AvnuAdapter, positionType: PositionTypeAvnuExtended): Promise<boolean> {
953
- const {
954
- ask, bid
955
- } = await extendedAdapter.fetchOrderBookBTCUSDC();
1463
+ async checkPriceDifferenceBetweenAvnuAndExtended(
1464
+ extendedAdapter: ExtendedAdapter,
1465
+ vesuAdapter: VesuMultiplyAdapter,
1466
+ avnuAdapter: AvnuAdapter,
1467
+ positionType: PositionTypeAvnuExtended
1468
+ ): Promise<boolean> {
1469
+ const { ask, bid } = await extendedAdapter.fetchOrderBookBTCUSDC();
956
1470
  const price = ask.plus(bid).dividedBy(2);
957
1471
  const btcToken = vesuAdapter.config.supportedPositions[0].asset;
958
- const btcPriceAvnu = await avnuAdapter.getPriceOfToken(btcToken.address.toString());
1472
+ const btcPriceAvnu = await avnuAdapter.getPriceOfToken(
1473
+ btcToken.address.toString()
1474
+ );
959
1475
 
960
1476
  if (!btcPriceAvnu) {
961
1477
  logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
@@ -963,19 +1479,34 @@ export class VesuExtendedMultiplierStrategy<
963
1479
  }
964
1480
  logger.info(`price: ${price}`);
965
1481
  logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
966
- const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
1482
+ const priceDifference = new Web3Number(
1483
+ price.minus(btcPriceAvnu).toFixed(2),
1484
+ 0
1485
+ );
967
1486
  logger.info(`priceDifference: ${priceDifference}`);
968
1487
  if (priceDifference.isNegative()) {
969
1488
  return false;
970
1489
  }
971
1490
  if (positionType === PositionTypeAvnuExtended.OPEN) {
972
- logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
973
- const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen); // 500 for now
1491
+ logger.info(
1492
+ `price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${
1493
+ avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen
1494
+ }`
1495
+ );
1496
+ const result = priceDifference.greaterThanOrEqualTo(
1497
+ avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen
1498
+ ); // 500 for now
974
1499
  logger.info(`result: ${result}`);
975
1500
  return result;
976
1501
  } else {
977
- logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
978
- const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing); // 1000 for now
1502
+ logger.info(
1503
+ `price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${
1504
+ avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing
1505
+ }`
1506
+ );
1507
+ const result = priceDifference.lessThanOrEqualTo(
1508
+ avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing
1509
+ ); // 1000 for now
979
1510
  logger.info(`result: ${result}`);
980
1511
  return result;
981
1512
  }
@@ -989,16 +1520,30 @@ export class VesuExtendedMultiplierStrategy<
989
1520
  async handleWithdraw(amount: Web3Number): Promise<TransactionResult[]> {
990
1521
  try {
991
1522
  const usdcBalanceVaultAllocator = await this.getUnusedBalance();
992
- const usdcBalanceDifference = amount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcBalanceVaultAllocator.usdValue);
1523
+ const usdcBalanceDifference = amount
1524
+ .plus(BUFFER_USDC_IN_WITHDRAWAL)
1525
+ .minus(usdcBalanceVaultAllocator.usdValue);
993
1526
  logger.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
994
1527
  let calls: Call[] = [];
995
1528
  let status: boolean = true;
996
1529
  if (usdcBalanceDifference.lessThan(0)) {
997
1530
  const withdrawCall = await this.getBringLiquidityCall({
998
- amount: usdcBalanceVaultAllocator.amount
999
- })
1531
+ amount: usdcBalanceVaultAllocator.amount,
1532
+ });
1000
1533
  calls.push(withdrawCall);
1001
- return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "WITHDRAWAL", CycleType.WITHDRAWAL)];
1534
+ return [
1535
+ this.createTransactionResult(
1536
+ calls,
1537
+ true,
1538
+ {
1539
+ from: Protocols.VAULT.name,
1540
+ to: Protocols.NONE.name,
1541
+ amount: amount,
1542
+ },
1543
+ "WITHDRAWAL",
1544
+ CycleType.WITHDRAWAL
1545
+ ),
1546
+ ];
1002
1547
  }
1003
1548
  const vesuAdapter = await this.getVesuAdapter();
1004
1549
  const extendedAdapter = await this.getExtendedAdapter();
@@ -1007,19 +1552,41 @@ export class VesuExtendedMultiplierStrategy<
1007
1552
  logger.error(
1008
1553
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
1009
1554
  );
1010
- return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "NONE", CycleType.WITHDRAWAL)];
1555
+ return [
1556
+ this.createTransactionResult(
1557
+ calls,
1558
+ status,
1559
+ {
1560
+ from: Protocols.VAULT.name,
1561
+ to: Protocols.NONE.name,
1562
+ amount: amount,
1563
+ },
1564
+ "NONE",
1565
+ CycleType.WITHDRAWAL
1566
+ ),
1567
+ ];
1011
1568
  }
1012
1569
  let transactionResults: TransactionResult[] = [];
1013
1570
  const { collateralTokenAmount } =
1014
1571
  await vesuAdapter.vesuAdapter.getAssetPrices();
1015
- const {
1016
- collateralPrice
1017
- } = await this.getAssetPrices();
1572
+ const { collateralPrice } = await this.getAssetPrices();
1018
1573
  const extendedPositon = await extendedAdapter.getAllOpenPositions();
1019
1574
  if (!extendedPositon) {
1020
1575
  status = false;
1021
1576
  logger.error("error getting extended position", extendedPositon);
1022
- return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "NONE", CycleType.WITHDRAWAL)];
1577
+ return [
1578
+ this.createTransactionResult(
1579
+ calls,
1580
+ status,
1581
+ {
1582
+ from: Protocols.VAULT.name,
1583
+ to: Protocols.NONE.name,
1584
+ amount: amount,
1585
+ },
1586
+ "NONE",
1587
+ CycleType.WITHDRAWAL
1588
+ ),
1589
+ ];
1023
1590
  }
1024
1591
  const amountDistributionForWithdrawal =
1025
1592
  await calculateAmountDistributionForWithdrawal(
@@ -1033,17 +1600,33 @@ export class VesuExtendedMultiplierStrategy<
1033
1600
  logger.error(
1034
1601
  `error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
1035
1602
  );
1036
- return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "NONE", CycleType.WITHDRAWAL)];
1603
+ return [
1604
+ this.createTransactionResult(
1605
+ calls,
1606
+ status,
1607
+ {
1608
+ from: Protocols.VAULT.name,
1609
+ to: Protocols.NONE.name,
1610
+ amount: amount,
1611
+ },
1612
+ "NONE",
1613
+ CycleType.WITHDRAWAL
1614
+ ),
1615
+ ];
1037
1616
  }
1038
1617
  const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
1039
1618
 
1040
1619
  if (status && vesu_amount.greaterThan(0)) {
1041
- const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
1620
+ const {
1621
+ calls: vesuCalls,
1622
+ status: vesuStatus,
1623
+ transactionMetadata: vesuTransactionMetadata,
1624
+ } = await this.moveAssets(
1042
1625
  {
1043
1626
  amount: vesu_amount,
1044
1627
  from: Protocols.VESU.name,
1045
1628
  to: Protocols.VAULT.name,
1046
- cycleType: CycleType.WITHDRAWAL
1629
+ cycleType: CycleType.WITHDRAWAL,
1047
1630
  },
1048
1631
  extendedAdapter,
1049
1632
  vesuAdapter
@@ -1052,16 +1635,20 @@ export class VesuExtendedMultiplierStrategy<
1052
1635
  transactionResults.push({
1053
1636
  status: vesuStatus,
1054
1637
  calls: vesuCalls,
1055
- transactionMetadata: vesuTransactionMetadata
1056
- })
1638
+ transactionMetadata: vesuTransactionMetadata,
1639
+ });
1057
1640
  }
1058
1641
  if (status && extended_amount.greaterThan(0)) {
1059
- const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
1642
+ const {
1643
+ calls: extendedCalls,
1644
+ status: extendedStatus,
1645
+ transactionMetadata: extendedTransactionMetadata,
1646
+ } = await this.moveAssets(
1060
1647
  {
1061
1648
  amount: extended_amount,
1062
1649
  from: Protocols.EXTENDED.name,
1063
1650
  to: Protocols.VAULT.name,
1064
- cycleType: CycleType.WITHDRAWAL
1651
+ cycleType: CycleType.WITHDRAWAL,
1065
1652
  },
1066
1653
  extendedAdapter,
1067
1654
  vesuAdapter
@@ -1071,16 +1658,30 @@ export class VesuExtendedMultiplierStrategy<
1071
1658
  transactionResults.push({
1072
1659
  status: extendedStatus,
1073
1660
  calls: extendedCalls,
1074
- transactionMetadata: extendedTransactionMetadata
1075
- })
1661
+ transactionMetadata: extendedTransactionMetadata,
1662
+ });
1076
1663
  } else {
1077
- logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
1078
- return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "NONE", CycleType.WITHDRAWAL)];
1664
+ logger.error(
1665
+ "error moving assets to vault: extendedStatus: ${extendedStatus}"
1666
+ );
1667
+ return [
1668
+ this.createTransactionResult(
1669
+ [],
1670
+ status,
1671
+ {
1672
+ from: Protocols.VAULT.name,
1673
+ to: Protocols.NONE.name,
1674
+ amount: amount,
1675
+ },
1676
+ "NONE",
1677
+ CycleType.WITHDRAWAL
1678
+ ),
1679
+ ];
1079
1680
  }
1080
1681
  }
1081
1682
  const withdrawCall = await this.getBringLiquidityCall({
1082
- amount: amount
1083
- })
1683
+ amount: amount,
1684
+ });
1084
1685
  logger.info("withdraw call", withdrawCall);
1085
1686
  transactionResults.push({
1086
1687
  status: status,
@@ -1090,18 +1691,34 @@ export class VesuExtendedMultiplierStrategy<
1090
1691
  protocolTo: Protocols.NONE.name,
1091
1692
  transactionType: "WITHDRAWAL",
1092
1693
  usdAmount: amount.toFixed(),
1093
- status: 'PENDING',
1094
- cycleType: CycleType.WITHDRAWAL
1095
- }
1096
- })
1694
+ status: "PENDING",
1695
+ cycleType: CycleType.WITHDRAWAL,
1696
+ },
1697
+ });
1097
1698
  return transactionResults;
1098
1699
  } catch (err) {
1099
1700
  logger.error(`error handling withdrawal: ${err}`);
1100
- return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount: amount }, "NONE", CycleType.WITHDRAWAL)];
1701
+ return [
1702
+ this.createTransactionResult(
1703
+ [],
1704
+ false,
1705
+ {
1706
+ from: Protocols.VAULT.name,
1707
+ to: Protocols.NONE.name,
1708
+ amount: amount,
1709
+ },
1710
+ "NONE",
1711
+ CycleType.WITHDRAWAL
1712
+ ),
1713
+ ];
1101
1714
  }
1102
1715
  }
1103
1716
 
1104
- async getAUM(): Promise<{ net: SingleTokenInfo, prevAum: Web3Number, splits: PositionInfo[] }> {
1717
+ async getAUM(): Promise<{
1718
+ net: SingleTokenInfo;
1719
+ prevAum: Web3Number;
1720
+ splits: PositionInfo[];
1721
+ }> {
1105
1722
  const allPositions: PositionInfo[] = [];
1106
1723
  for (let adapter of this.metadata.additionalInfo.adapters) {
1107
1724
  const positions = await adapter.adapter.getPositions();
@@ -1125,34 +1742,49 @@ export class VesuExtendedMultiplierStrategy<
1125
1742
  usdValue: netAUM.toNumber() * assetPrice.price,
1126
1743
  apy: { apy: netAUM.toNumber() * assetPrice.price, type: APYType.BASE },
1127
1744
  remarks: AUMTypes.FINALISED,
1128
- protocol: Protocols.NONE // just placeholder
1745
+ protocol: Protocols.NONE, // just placeholder
1129
1746
  };
1130
1747
 
1131
1748
  const estimatedAUMDelta: PositionInfo = {
1132
1749
  tokenInfo: this.asset(),
1133
- amount: Web3Number.fromWei('0', this.asset().decimals),
1750
+ amount: Web3Number.fromWei("0", this.asset().decimals),
1134
1751
  usdValue: 0,
1135
1752
  apy: { apy: 0, type: APYType.BASE },
1136
1753
  remarks: AUMTypes.DEFISPRING,
1137
- protocol: Protocols.NONE // just placeholder
1754
+ protocol: Protocols.NONE, // just placeholder
1138
1755
  };
1139
1756
 
1140
1757
  return {
1141
1758
  net: {
1142
1759
  tokenInfo: this.asset(),
1143
1760
  amount: netAUM,
1144
- usdValue: netAUM.toNumber() * assetPrice.price
1145
- }, prevAum: prevAum, splits: [realAUM, estimatedAUMDelta]
1761
+ usdValue: netAUM.toNumber() * assetPrice.price,
1762
+ },
1763
+ prevAum: prevAum,
1764
+ splits: [realAUM, estimatedAUMDelta],
1146
1765
  };
1147
1766
  }
1148
1767
 
1149
- async processTransactionDataFromSDK(txnData: TransactionResult<any>[]): Promise<{ callsToBeExecutedFinal: Call[], txnMetadata: TransactionMetadata[] } | null> {
1768
+ async processTransactionDataFromSDK(
1769
+ txnData: TransactionResult<any>[]
1770
+ ): Promise<{
1771
+ callsToBeExecutedFinal: Call[];
1772
+ txnMetadata: TransactionMetadata[];
1773
+ } | null> {
1150
1774
  try {
1151
- const txnsToBeExecuted = txnData.filter(txn => {
1152
- return txn.transactionMetadata.transactionType !== 'NONE' && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
1153
- })
1154
- const callsToBeExecutedFinal = txnsToBeExecuted.flatMap(txn => txn.calls);
1155
- const txnMetadata = txnsToBeExecuted.map(txn => txn.transactionMetadata);
1775
+ const txnsToBeExecuted = txnData.filter((txn) => {
1776
+ return (
1777
+ txn.transactionMetadata.transactionType !== "NONE" &&
1778
+ txn.transactionMetadata.protocolFrom !== "" &&
1779
+ txn.transactionMetadata.protocolTo !== ""
1780
+ );
1781
+ });
1782
+ const callsToBeExecutedFinal = txnsToBeExecuted.flatMap(
1783
+ (txn) => txn.calls
1784
+ );
1785
+ const txnMetadata = txnsToBeExecuted.map(
1786
+ (txn) => txn.transactionMetadata
1787
+ );
1156
1788
  return { callsToBeExecutedFinal, txnMetadata };
1157
1789
  } catch (err) {
1158
1790
  logger.error(`error processing transaction data from SDK: ${err}`);
@@ -1160,18 +1792,23 @@ export class VesuExtendedMultiplierStrategy<
1160
1792
  }
1161
1793
  }
1162
1794
 
1163
- async processTransactionMetadata(txnMetadata: TransactionMetadata[], extendedIntentFulfilled: boolean): Promise<TransactionMetadata[] | null> {
1795
+ async processTransactionMetadata(
1796
+ txnMetadata: TransactionMetadata[],
1797
+ extendedIntentFulfilled: boolean
1798
+ ): Promise<TransactionMetadata[] | null> {
1164
1799
  try {
1165
- const txnMetadataNew = txnMetadata.map(txn => {
1166
- const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
1800
+ const txnMetadataNew = txnMetadata.map((txn) => {
1801
+ const isExtendedProtocol =
1802
+ txn.protocolFrom === Protocols.EXTENDED.name ||
1803
+ txn.protocolTo === Protocols.EXTENDED.name;
1167
1804
  // Only update status for extended protocol transactions since thsoe only cause delays
1168
1805
  if (isExtendedProtocol) {
1169
- txn.status = extendedIntentFulfilled ? 'COMPLETED' : 'PENDING';
1806
+ txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
1170
1807
  } else {
1171
- txn.status = 'COMPLETED';
1808
+ txn.status = "COMPLETED";
1172
1809
  }
1173
1810
  return txn;
1174
- })
1811
+ });
1175
1812
  return txnMetadataNew;
1176
1813
  } catch (err) {
1177
1814
  logger.error(`error processing transaction data from SDK: ${err}`);
@@ -1185,23 +1822,43 @@ export class VesuExtendedMultiplierStrategy<
1185
1822
  if (!vesuAdapter || !extendedAdapter) {
1186
1823
  return new Web3Number(0, 0);
1187
1824
  }
1188
- const extendedFundingRate = new Web3Number((await extendedAdapter.getNetAPY()).toFixed(4), 0);
1825
+ const extendedFundingRate = new Web3Number(
1826
+ (await extendedAdapter.getNetAPY()).toFixed(4),
1827
+ 0
1828
+ );
1189
1829
  const extendedPositions = await extendedAdapter.getAllOpenPositions();
1190
1830
  if (!extendedPositions || extendedPositions.length === 0) {
1191
1831
  logger.info(`no extended positions found`);
1192
1832
  return new Web3Number(0, 0);
1193
1833
  }
1194
- const extendePositionSizeUSD = new Web3Number(extendedPositions[0].value || 0, 0);
1834
+ const extendePositionSizeUSD = new Web3Number(
1835
+ extendedPositions[0].value || 0,
1836
+ 0
1837
+ );
1195
1838
  const vesuPositions = await vesuAdapter.getPositions();
1196
1839
  const vesuSupplyApy = vesuPositions[0].apy.apy;
1197
- const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
1198
- const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS)
1199
- const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
1840
+ const vesuCollateralSizeUSD = new Web3Number(
1841
+ vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS),
1842
+ USDC_TOKEN_DECIMALS
1843
+ );
1844
+ const vesuDebtSizeUSD = new Web3Number(
1845
+ vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS),
1846
+ USDC_TOKEN_DECIMALS
1847
+ );
1848
+ const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
1200
1849
  const num2 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
1201
- const num3 = vesuDebtSizeUSD.abs()
1850
+ const num3 = vesuDebtSizeUSD.abs();
1202
1851
  const maxBorrowApy = num1.plus(num2).minus(0.1).dividedBy(num3);
1203
- const vesuMaxBorrowableAmount = await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxBorrowApy.toNumber());
1204
- return new Web3Number(vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
1852
+ const vesuMaxBorrowableAmount =
1853
+ await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(
1854
+ this.config,
1855
+ vesuAdapter.config.debt,
1856
+ maxBorrowApy.toNumber()
1857
+ );
1858
+ return new Web3Number(
1859
+ vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS),
1860
+ USDC_TOKEN_DECIMALS
1861
+ );
1205
1862
  }
1206
1863
 
1207
1864
  async getVesuHealthFactors(): Promise<number[]> {
@@ -1211,83 +1868,124 @@ export class VesuExtendedMultiplierStrategy<
1211
1868
  return [0, 0];
1212
1869
  }
1213
1870
  const vesuPositions = await vesuAdapter.getPositions();
1214
- const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
1215
- const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
1871
+ const vesuCollateralSizeUSD = new Web3Number(
1872
+ vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS),
1873
+ 0
1874
+ );
1875
+ const vesuDebtSizeUSD = new Web3Number(
1876
+ vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS),
1877
+ 0
1878
+ );
1216
1879
  const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
1217
1880
  logger.info(`actualLtv: ${actualLtv.toNumber()}`);
1218
- const maxLtv = new Web3Number(await vesuAdapter.vesuAdapter.getLTVConfig(this.config), 4);
1219
- const healthFactor = new Web3Number(maxLtv.dividedBy(actualLtv).toFixed(4), 4);
1881
+ const maxLtv = new Web3Number(
1882
+ await vesuAdapter.vesuAdapter.getLTVConfig(this.config),
1883
+ 4
1884
+ );
1885
+ const healthFactor = new Web3Number(
1886
+ maxLtv.dividedBy(actualLtv).toFixed(4),
1887
+ 4
1888
+ );
1220
1889
  logger.info(`healthFactor: ${healthFactor.toNumber()}`);
1221
1890
  const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
1222
1891
  if (!extendedBalance) {
1223
1892
  return [0, 0];
1224
1893
  }
1225
- const extendedLeverage = new Web3Number((Number(extendedBalance.marginRatio) * 100).toFixed(4), 4);
1894
+ const extendedLeverage = new Web3Number(
1895
+ (Number(extendedBalance.marginRatio) * 100).toFixed(4),
1896
+ 4
1897
+ );
1226
1898
  logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
1227
1899
  return [healthFactor.toNumber(), extendedLeverage.toNumber()];
1228
1900
  }
1229
1901
 
1230
- async netAPY(): Promise<{ net: number; splits: { apy: number; id: string; }[]; }> {
1902
+ async netAPY(): Promise<{
1903
+ net: number;
1904
+ splits: { apy: number; id: string }[];
1905
+ }> {
1231
1906
  const allPositions: PositionInfo[] = [];
1232
1907
  for (let adapter of this.metadata.additionalInfo.adapters) {
1233
- if(adapter.adapter.name !== ExtendedAdapter.name){
1234
- let positions = await adapter.adapter.getPositions();
1235
- if(positions.length > 0){
1236
- allPositions.push(...positions);
1237
- }
1908
+ if (adapter.adapter.name !== ExtendedAdapter.name) {
1909
+ let positions = await adapter.adapter.getPositions();
1910
+ if (positions.length > 0) {
1911
+ allPositions.push(...positions);
1238
1912
  }
1239
1913
  }
1240
- const extendedAdapter =await this.getExtendedAdapter()
1241
- if(!extendedAdapter){
1914
+ }
1915
+ const extendedAdapter = await this.getExtendedAdapter();
1916
+ if (!extendedAdapter) {
1242
1917
  return {
1243
1918
  net: 0,
1244
- splits: []
1245
- }
1919
+ splits: [],
1920
+ };
1246
1921
  }
1247
- let vesuPositions = allPositions.filter((item) => item.protocol === Protocols.VESU);
1248
- vesuPositions.map((item) =>{
1922
+ let vesuPositions = allPositions.filter(
1923
+ (item) => item.protocol === Protocols.VESU
1924
+ );
1925
+ vesuPositions.map((item) => {
1249
1926
  item.apy.apy = item.apy.apy * 0.1;
1250
- })
1927
+ });
1251
1928
  const extendedPositions = await extendedAdapter.getAllOpenPositions();
1252
- const usdcToken = Global.getDefaultTokens().find(token => token.symbol === "USDC");
1253
- if(!extendedPositions || !usdcToken){
1929
+ const usdcToken = Global.getDefaultTokens().find(
1930
+ (token) => token.symbol === "USDC"
1931
+ );
1932
+ if (!extendedPositions || !usdcToken) {
1254
1933
  return {
1255
1934
  net: 0,
1256
- splits: []
1257
- }
1935
+ splits: [],
1936
+ };
1258
1937
  }
1259
1938
  const extendedPosition = extendedPositions[0] || 0;
1260
- const extendedEquity = (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
1939
+ const extendedEquity =
1940
+ (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
1261
1941
  const extendedApy = await extendedAdapter.getNetAPY();
1262
- const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) + Number(extendedEquity);
1263
- console.log(totalHoldingsUSDValue)
1264
- const extendedPositionSizeMultipliedByApy = Number(extendedPosition.value) * extendedApy;
1265
- let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) + extendedPositionSizeMultipliedByApy;
1266
- console.log(weightedAPYs)
1942
+ const totalHoldingsUSDValue =
1943
+ allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) +
1944
+ Number(extendedEquity);
1945
+ console.log(totalHoldingsUSDValue);
1946
+ const extendedPositionSizeMultipliedByApy =
1947
+ Number(extendedPosition.value) * extendedApy;
1948
+ let weightedAPYs =
1949
+ allPositions.reduce(
1950
+ (acc, curr) => acc + curr.apy.apy * curr.usdValue,
1951
+ 0
1952
+ ) + extendedPositionSizeMultipliedByApy;
1953
+ console.log(weightedAPYs);
1267
1954
  const netAPY = weightedAPYs / totalHoldingsUSDValue;
1268
- console.log(netAPY)
1955
+ console.log(netAPY);
1269
1956
  allPositions.push({
1270
1957
  tokenInfo: usdcToken,
1271
1958
  amount: new Web3Number(extendedPosition.size, 0),
1272
1959
  usdValue: Number(extendedEquity),
1273
1960
  apy: { apy: extendedApy, type: APYType.BASE },
1274
1961
  remarks: AUMTypes.FINALISED,
1275
- protocol: Protocols.EXTENDED
1276
- })
1962
+ protocol: Protocols.EXTENDED,
1963
+ });
1277
1964
  return {
1278
1965
  net: netAPY,
1279
- splits: allPositions.map(p => ({apy: p.apy.apy, id: p.remarks ?? ''}))
1966
+ splits: allPositions.map((p) => ({
1967
+ apy: p.apy.apy,
1968
+ id: p.remarks ?? "",
1969
+ })),
1280
1970
  };
1281
1971
  }
1282
1972
 
1283
- async getWalletHoldings(): Promise<{
1284
- tokenInfo: TokenInfo,
1285
- amount: Web3Number,
1286
- usdValue: number
1287
- }[]> {
1288
- const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
1289
- const wbtcToken = Global.getDefaultTokens().find(token => token.symbol === "WBTC");
1290
- const usdcToken = Global.getDefaultTokens().find(token => token.symbol === "USDC");
1973
+ async getWalletHoldings(): Promise<
1974
+ {
1975
+ tokenInfo: TokenInfo;
1976
+ amount: Web3Number;
1977
+ usdValue: number;
1978
+ }[]
1979
+ > {
1980
+ const usdceToken = Global.getDefaultTokens().find(
1981
+ (token) => token.symbol === "USDCe"
1982
+ );
1983
+ const wbtcToken = Global.getDefaultTokens().find(
1984
+ (token) => token.symbol === "WBTC"
1985
+ );
1986
+ const usdcToken = Global.getDefaultTokens().find(
1987
+ (token) => token.symbol === "USDC"
1988
+ );
1291
1989
  if (!usdceToken || !wbtcToken || !usdcToken) {
1292
1990
  return [];
1293
1991
  }
@@ -1309,23 +2007,29 @@ export class VesuExtendedMultiplierStrategy<
1309
2007
  );
1310
2008
  const price = await this.pricer.getPrice(usdceToken.symbol);
1311
2009
  const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
1312
- const usdceUsdValue = Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
1313
- const usdcUsdValue = Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
1314
- const wbtcUsdValue = Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
1315
- return [{
1316
- tokenInfo: usdceToken,
1317
- amount: usdceWalletBalance,
1318
- usdValue: usdceUsdValue
1319
- },
1320
- {
1321
- tokenInfo: usdcToken,
1322
- amount: usdcWalletBalance,
1323
- usdValue: usdcUsdValue
1324
- }, {
1325
- tokenInfo: wbtcToken,
1326
- amount: wbtcWalletBalance,
1327
- usdValue: wbtcUsdValue
1328
- }];
2010
+ const usdceUsdValue =
2011
+ Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
2012
+ const usdcUsdValue =
2013
+ Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
2014
+ const wbtcUsdValue =
2015
+ Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
2016
+ return [
2017
+ {
2018
+ tokenInfo: usdceToken,
2019
+ amount: usdceWalletBalance,
2020
+ usdValue: usdceUsdValue,
2021
+ },
2022
+ {
2023
+ tokenInfo: usdcToken,
2024
+ amount: usdcWalletBalance,
2025
+ usdValue: usdcUsdValue,
2026
+ },
2027
+ {
2028
+ tokenInfo: wbtcToken,
2029
+ amount: wbtcWalletBalance,
2030
+ usdValue: wbtcUsdValue,
2031
+ },
2032
+ ];
1329
2033
  }
1330
2034
  }
1331
2035
 
@@ -1341,7 +2045,7 @@ function getLooperSettings(
1341
2045
  minimumVesuMovementAmount: number,
1342
2046
  minimumExtendedRetriesDelayForOrderStatus: number,
1343
2047
  minimumExtendedPriceDifferenceForSwapOpen: number,
1344
- maximumExtendedPriceDifferenceForSwapClosing: number,
2048
+ maximumExtendedPriceDifferenceForSwapClosing: number
1345
2049
  ) {
1346
2050
  vaultSettings.leafAdapters = [];
1347
2051
 
@@ -1370,15 +2074,15 @@ function getLooperSettings(
1370
2074
  avnuContract: AVNU_MIDDLEWARE,
1371
2075
  slippage: 0.01,
1372
2076
  baseUrl: AVNU_QUOTE_URL,
1373
- minimumExtendedPriceDifferenceForSwapOpen: minimumExtendedPriceDifferenceForSwapOpen,
1374
- maximumExtendedPriceDifferenceForSwapClosing: maximumExtendedPriceDifferenceForSwapClosing,
2077
+ minimumExtendedPriceDifferenceForSwapOpen:
2078
+ minimumExtendedPriceDifferenceForSwapOpen,
2079
+ maximumExtendedPriceDifferenceForSwapClosing:
2080
+ maximumExtendedPriceDifferenceForSwapClosing,
1375
2081
  });
1376
2082
 
1377
2083
  const extendedAdapter = new ExtendedAdapter({
1378
2084
  ...baseAdapterConfig,
1379
- supportedPositions: [
1380
- { asset: usdcToken, isDebt: true },
1381
- ],
2085
+ supportedPositions: [{ asset: usdcToken, isDebt: true }],
1382
2086
  vaultIdExtended: vaultIdExtended,
1383
2087
  extendedContract: EXTENDED_CONTRACT,
1384
2088
  extendedBackendWriteUrl: extendedBackendWriteUrl,
@@ -1441,11 +2145,11 @@ function getLooperSettings(
1441
2145
  });
1442
2146
 
1443
2147
  vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getDepositLeaf());
2148
+ vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getWithdrawLeaf());
2149
+ vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
1444
2150
  vaultSettings.leafAdapters.push(() =>
1445
- vesuMultiplyAdapter.getWithdrawLeaf()
2151
+ extendedAdapter.getSwapFromLegacyLeaf()
1446
2152
  );
1447
- vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
1448
- vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
1449
2153
  vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
1450
2154
  vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
1451
2155
  vaultSettings.leafAdapters.push(
@@ -1466,7 +2170,6 @@ function getLooperSettings(
1466
2170
  return vaultSettings;
1467
2171
  }
1468
2172
 
1469
-
1470
2173
  function getDescription(tokenSymbol: string, underlyingSymbol: string) {
1471
2174
  return VaultDescription(tokenSymbol, underlyingSymbol);
1472
2175
  }
@@ -1486,26 +2189,64 @@ export default function VaultDescription(
1486
2189
 
1487
2190
  return (
1488
2191
  <div style={containerStyle}>
1489
- <h1 style={{ fontSize: "18px", marginBottom: "10px" }}>Liquidation risk managed leverged {lstSymbol} Vault</h1>
2192
+ <h1 style={{ fontSize: "18px", marginBottom: "10px" }}>
2193
+ Liquidation risk managed leverged {lstSymbol} Vault
2194
+ </h1>
1490
2195
  <p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
1491
- This Levered Endur {lstSymbol} vault is a tokenized leveraged Vault, auto-compounding strategy that takes upto 5x leverage on {lstSymbol} by borrow {underlyingSymbol}. Borrowed amount
1492
- is swapped to {lstSymbol} to create leverage. Depositors receive vault shares that
1493
- represent a proportional claim on the underlying assets and accrued yield.
2196
+ This Levered Endur {lstSymbol} vault is a tokenized leveraged Vault,
2197
+ auto-compounding strategy that takes upto 5x leverage on {lstSymbol} by
2198
+ borrow {underlyingSymbol}. Borrowed amount is swapped to {lstSymbol} to
2199
+ create leverage. Depositors receive vault shares that represent a
2200
+ proportional claim on the underlying assets and accrued yield.
1494
2201
  </p>
1495
2202
 
1496
2203
  <p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
1497
- This vault uses Vesu for lending and borrowing. The oracle used by this pool is a {highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }])}
1498
- {" "}which is resilient to liquidity issues and price volatility, hence reducing the risk of liquidation. However, overtime, if left un-monitored, debt can increase enough to trigger a liquidation. But no worries, our continuous monitoring systems look for situations with reduced health factor and balance collateral/debt to bring it back to safe levels. With Troves, you can have a peaceful sleep.
2204
+ This vault uses Vesu for lending and borrowing. The oracle used by this
2205
+ pool is a{" "}
2206
+ {highlightTextWithLinks("conversion rate oracle", [
2207
+ {
2208
+ highlight: "conversion rate oracle",
2209
+ link: "https://docs.pragma.build/starknet/development#conversion-rate",
2210
+ },
2211
+ ])}{" "}
2212
+ which is resilient to liquidity issues and price volatility, hence
2213
+ reducing the risk of liquidation. However, overtime, if left
2214
+ un-monitored, debt can increase enough to trigger a liquidation. But no
2215
+ worries, our continuous monitoring systems look for situations with
2216
+ reduced health factor and balance collateral/debt to bring it back to
2217
+ safe levels. With Troves, you can have a peaceful sleep.
1499
2218
  </p>
1500
2219
 
1501
- <div style={{ backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }}>
2220
+ <div
2221
+ style={{
2222
+ backgroundColor: "#222",
2223
+ padding: "10px",
2224
+ borderRadius: "8px",
2225
+ marginBottom: "20px",
2226
+ border: "1px solid #444",
2227
+ }}
2228
+ >
1502
2229
  <p style={{ fontSize: "13px", color: "#ccc" }}>
1503
- <strong>Withdrawals:</strong> Requests can take up to <strong>1-2 hours</strong> to process as the vault unwinds and settles routing.
2230
+ <strong>Withdrawals:</strong> Requests can take up to{" "}
2231
+ <strong>1-2 hours</strong> to process as the vault unwinds and settles
2232
+ routing.
1504
2233
  </p>
1505
2234
  </div>
1506
- <div style={{ backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }}>
2235
+ <div
2236
+ style={{
2237
+ backgroundColor: "#222",
2238
+ padding: "10px",
2239
+ borderRadius: "8px",
2240
+ marginBottom: "20px",
2241
+ border: "1px solid #444",
2242
+ }}
2243
+ >
1507
2244
  <p style={{ fontSize: "13px", color: "#ccc" }}>
1508
- <strong>Debt limits:</strong> Pools on Vesu have debt caps that are gradually increased over time. Until caps are raised, deposited Tokens remain in the vault, generating a shared net return for all depositors. There is no additional fee taken by Troves on Yield token's APY, its only on added gain.
2245
+ <strong>Debt limits:</strong> Pools on Vesu have debt caps that are
2246
+ gradually increased over time. Until caps are raised, deposited Tokens
2247
+ remain in the vault, generating a shared net return for all
2248
+ depositors. There is no additional fee taken by Troves on Yield
2249
+ token's APY, its only on added gain.
1509
2250
  </p>
1510
2251
  </div>
1511
2252
  {/* <div style={{ backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }}>
@@ -1518,11 +2259,21 @@ export default function VaultDescription(
1518
2259
  }
1519
2260
 
1520
2261
  const re7UsdcPrimeDevansh: VesuExtendedStrategySettings = {
1521
- vaultAddress: ContractAddr.from("0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"),
1522
- manager: ContractAddr.from("0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"),
1523
- vaultAllocator: ContractAddr.from("0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"),
1524
- redeemRequestNFT: ContractAddr.from("0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"),
1525
- aumOracle: ContractAddr.from("0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"),
2262
+ vaultAddress: ContractAddr.from(
2263
+ "0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"
2264
+ ),
2265
+ manager: ContractAddr.from(
2266
+ "0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"
2267
+ ),
2268
+ vaultAllocator: ContractAddr.from(
2269
+ "0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"
2270
+ ),
2271
+ redeemRequestNFT: ContractAddr.from(
2272
+ "0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"
2273
+ ),
2274
+ aumOracle: ContractAddr.from(
2275
+ "0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"
2276
+ ),
1526
2277
  leafAdapters: [],
1527
2278
  adapters: [],
1528
2279
  targetHealthFactor: 1.4,
@@ -1534,34 +2285,88 @@ const re7UsdcPrimeDevansh: VesuExtendedStrategySettings = {
1534
2285
  "0.001",
1535
2286
  Global.getDefaultTokens().find((token) => token.symbol === "WBTC")!.decimals
1536
2287
  ),
1537
- borrowable_assets: [Global.getDefaultTokens().find(token => token.symbol === "WBTC")!],
2288
+ borrowable_assets: [
2289
+ Global.getDefaultTokens().find((token) => token.symbol === "WBTC")!,
2290
+ ],
1538
2291
  minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
1539
2292
  walletAddress: WALLET_ADDRESS,
1540
- }
2293
+ };
1541
2294
 
1542
- export const VesuExtendedTestStrategies = (extendedBackendReadUrl: string, extendedBackendWriteUrl: string, vaultIdExtended: number, minimumExtendedMovementAmount: number, minimumVesuMovementAmount: number, minimumExtendedRetriesDelayForOrderStatus: number, minimumExtendedPriceDifferenceForSwapOpen: number, maximumExtendedPriceDifferenceForSwapClosing: number): IStrategyMetadata<VesuExtendedStrategySettings>[] => {
2295
+ export const VesuExtendedTestStrategies = (
2296
+ extendedBackendReadUrl: string,
2297
+ extendedBackendWriteUrl: string,
2298
+ vaultIdExtended: number,
2299
+ minimumExtendedMovementAmount: number,
2300
+ minimumVesuMovementAmount: number,
2301
+ minimumExtendedRetriesDelayForOrderStatus: number,
2302
+ minimumExtendedPriceDifferenceForSwapOpen: number,
2303
+ maximumExtendedPriceDifferenceForSwapClosing: number
2304
+ ): IStrategyMetadata<VesuExtendedStrategySettings>[] => {
1543
2305
  return [
1544
- getStrategySettingsVesuExtended('WBTC', 'USDC', re7UsdcPrimeDevansh, false, false, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
1545
- ]
1546
- }
1547
-
1548
-
1549
-
1550
- function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: string, addresses: VesuExtendedStrategySettings, isPreview: boolean = false, isLST: boolean, extendedBackendReadUrl: string, extendedBackendWriteUrl: string, vaultIdExtended: number, minimumExtendedMovementAmount: number, minimumVesuMovementAmount: number, minimumExtendedRetriesDelayForOrderStatus: number, minimumExtendedPriceDifferenceForSwapOpen: number, maximumExtendedPriceDifferenceForSwapClosing: number): IStrategyMetadata<VesuExtendedStrategySettings> {
2306
+ getStrategySettingsVesuExtended(
2307
+ "WBTC",
2308
+ "USDC",
2309
+ re7UsdcPrimeDevansh,
2310
+ false,
2311
+ false,
2312
+ extendedBackendReadUrl,
2313
+ extendedBackendWriteUrl,
2314
+ vaultIdExtended,
2315
+ minimumExtendedMovementAmount,
2316
+ minimumVesuMovementAmount,
2317
+ minimumExtendedRetriesDelayForOrderStatus,
2318
+ minimumExtendedPriceDifferenceForSwapOpen,
2319
+ maximumExtendedPriceDifferenceForSwapClosing
2320
+ ),
2321
+ ];
2322
+ };
2323
+
2324
+ function getStrategySettingsVesuExtended(
2325
+ lstSymbol: string,
2326
+ underlyingSymbol: string,
2327
+ addresses: VesuExtendedStrategySettings,
2328
+ isPreview: boolean = false,
2329
+ isLST: boolean,
2330
+ extendedBackendReadUrl: string,
2331
+ extendedBackendWriteUrl: string,
2332
+ vaultIdExtended: number,
2333
+ minimumExtendedMovementAmount: number,
2334
+ minimumVesuMovementAmount: number,
2335
+ minimumExtendedRetriesDelayForOrderStatus: number,
2336
+ minimumExtendedPriceDifferenceForSwapOpen: number,
2337
+ maximumExtendedPriceDifferenceForSwapClosing: number
2338
+ ): IStrategyMetadata<VesuExtendedStrategySettings> {
1551
2339
  return {
1552
2340
  name: `Extended Test ${underlyingSymbol}`,
1553
2341
  description: getDescription(lstSymbol, underlyingSymbol),
1554
2342
  address: addresses.vaultAddress,
1555
2343
  launchBlock: 0,
1556
- type: 'Other',
1557
- depositTokens: [Global.getDefaultTokens().find(token => token.symbol === underlyingSymbol)!],
1558
- additionalInfo: getLooperSettings(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
2344
+ type: "Other",
2345
+ depositTokens: [
2346
+ Global.getDefaultTokens().find(
2347
+ (token) => token.symbol === underlyingSymbol
2348
+ )!,
2349
+ ],
2350
+ additionalInfo: getLooperSettings(
2351
+ lstSymbol,
2352
+ underlyingSymbol,
2353
+ addresses,
2354
+ VesuPools.Re7USDCPrime,
2355
+ extendedBackendReadUrl,
2356
+ extendedBackendWriteUrl,
2357
+ vaultIdExtended,
2358
+ minimumExtendedMovementAmount,
2359
+ minimumVesuMovementAmount,
2360
+ minimumExtendedRetriesDelayForOrderStatus,
2361
+ minimumExtendedPriceDifferenceForSwapOpen,
2362
+ maximumExtendedPriceDifferenceForSwapClosing
2363
+ ),
1559
2364
  risk: {
1560
2365
  riskFactor: _riskFactor,
1561
2366
  netRisk:
1562
2367
  _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
1563
2368
  _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
1564
- notARisks: getNoRiskTags(_riskFactor)
2369
+ notARisks: getNoRiskTags(_riskFactor),
1565
2370
  },
1566
2371
  auditUrl: AUDIT_URL,
1567
2372
  protocols: [Protocols.ENDUR, Protocols.VESU],
@@ -1570,6 +2375,8 @@ function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: st
1570
2375
  faqs: getFAQs(lstSymbol, underlyingSymbol, isLST),
1571
2376
  investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
1572
2377
  isPreview: isPreview,
1573
- apyMethodology: isLST ? 'Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.' : 'Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.'
1574
- }
1575
- }
2378
+ apyMethodology: isLST
2379
+ ? "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown."
2380
+ : "Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.",
2381
+ };
2382
+ }