@strkfarm/sdk 2.0.0-dev.1 → 2.0.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,7 @@ 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 { EXTENDED_QTY_PRECISION, LIMIT_BALANCE, MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED, MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED, MINIMUM_EXTENDED_POSITION_SIZE, USDC_TOKEN_DECIMALS, WBTC_TOKEN_DECIMALS } from "./utils/constants";
16
+ import { BUFFER_USDC_IN_WITHDRAWAL, EXTENDED_QTY_PRECISION, LIMIT_BALANCE, MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED, MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED, MINIMUM_EXTENDED_POSITION_SIZE, USDC_TOKEN_DECIMALS, WALLET_ADDRESS, WBTC_TOKEN_DECIMALS } from "./utils/constants";
17
17
  import { PricerBase } from "@/modules/pricerBase";
18
18
  import { ContractAddr, Web3Number } from "@/dataTypes";
19
19
  import { Global } from "@/global";
@@ -108,6 +108,26 @@ export class VesuExtendedMultiplierStrategy<
108
108
  debtPrice,
109
109
  };
110
110
  }
111
+
112
+ async getUnusedBalanceUSDCE(): Promise<SingleTokenInfo> {
113
+ const usdceToken = Global.getDefaultTokens().find(
114
+ (token) => token.symbol === "USDCe"
115
+ )!;
116
+ const balance = await new ERC20(this.config).balanceOf(
117
+ usdceToken.address,
118
+ WALLET_ADDRESS,
119
+ usdceToken.decimals
120
+ );
121
+ const price = await this.pricer.getPrice(usdceToken.symbol);
122
+ const usdValue =
123
+ Number(balance.toFixed(usdceToken.decimals)) * price.price;
124
+ return {
125
+ tokenInfo: usdceToken,
126
+ amount: balance,
127
+ usdValue,
128
+ };
129
+ }
130
+
111
131
 
112
132
  async getUnusedBalanceWBTC(): Promise<SingleTokenInfo> {
113
133
  const collateralToken = this.metadata.additionalInfo.borrowable_assets[0]!;
@@ -159,23 +179,31 @@ export class VesuExtendedMultiplierStrategy<
159
179
  return extendedAdapter.adapter as ExtendedAdapter;
160
180
  }
161
181
 
162
- async moveAssetsToVaultAllocator(amount: Web3Number): Promise<Call[]> {
163
- try{
164
- const usdcToken = Global.getDefaultTokens().find(
165
- (token) => token.symbol === "USDC"
182
+ async moveAssetsToVaultAllocator(amount: Web3Number, extendedAdapter: ExtendedAdapter): Promise<Call[]> {
183
+ try {
184
+ const usdceToken = Global.getDefaultTokens().find(
185
+ (token) => token.symbol === "USDCe"
166
186
  )!;
167
187
  const approveCall = new ERC20(this.config).approve(
168
- usdcToken.address,
188
+ usdceToken.address,
169
189
  this.metadata.additionalInfo.vaultAllocator,
170
190
  amount
171
191
  );
172
192
  const transferCall = new ERC20(this.config).transfer(
173
- usdcToken.address,
193
+ usdceToken.address,
174
194
  this.metadata.additionalInfo.vaultAllocator,
175
195
  amount
176
196
  );
177
- return [approveCall, transferCall];
178
- }catch(err){
197
+ const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
198
+ this.getMerkleTree()
199
+ );
200
+ const proofGroups = proofsInfo.proofs;
201
+ const call = this.getManageCall(
202
+ proofGroups,
203
+ await proofsInfo.callConstructor({ amount: amount })
204
+ );
205
+ return [approveCall, transferCall, call];
206
+ } catch (err) {
179
207
  logger.error(`error moving assets to vault allocator: ${err}`);
180
208
  return [];
181
209
  }
@@ -307,11 +335,9 @@ export class VesuExtendedMultiplierStrategy<
307
335
  );
308
336
  return calls;
309
337
  }
310
- console.log("extendedAmount", extendedAmount);
311
- console.log("vesuAmount", vesuAmount);
312
338
  if (extendedAmount.lessThan(0)) {
313
339
  try {
314
- const extendedCalls = await this.moveAssets(
340
+ const {calls: extendedCalls, status: extendedStatus} = await this.moveAssets(
315
341
  {
316
342
  to: Protocols.VAULT.name,
317
343
  from: Protocols.EXTENDED.name,
@@ -320,7 +346,12 @@ export class VesuExtendedMultiplierStrategy<
320
346
  extendedAdapter,
321
347
  vesuAdapter
322
348
  );
349
+ //If withdrawal succesfull, then do further
350
+ if(extendedStatus){
323
351
  calls.push(...extendedCalls);
352
+ }else{
353
+ return [];
354
+ }
324
355
  } catch (err) {
325
356
  logger.error(`Failed moving assets to vault: ${err}`);
326
357
  }
@@ -328,7 +359,7 @@ export class VesuExtendedMultiplierStrategy<
328
359
 
329
360
  if (vesuAmount.lessThan(0)) {
330
361
  try {
331
- const vesuCalls = await this.moveAssets(
362
+ const {calls: vesuCalls, status: vesuStatus} = await this.moveAssets(
332
363
  {
333
364
  to: Protocols.EXTENDED.name,
334
365
  from: Protocols.VESU.name,
@@ -338,6 +369,9 @@ export class VesuExtendedMultiplierStrategy<
338
369
  vesuAdapter
339
370
  );
340
371
  calls.push(...vesuCalls);
372
+ if(!vesuStatus){
373
+ return [];
374
+ }
341
375
  } catch (err) {
342
376
  logger.error(`Failed moving assets to vault: ${err}`);
343
377
  }
@@ -355,7 +389,7 @@ export class VesuExtendedMultiplierStrategy<
355
389
  if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
356
390
  //move assets to extended
357
391
  try {
358
- const extendedCalls = await this.moveAssets(
392
+ const {calls: extendedCalls} = await this.moveAssets(
359
393
  {
360
394
  to: Protocols.EXTENDED.name,
361
395
  from: Protocols.VAULT.name,
@@ -372,15 +406,18 @@ export class VesuExtendedMultiplierStrategy<
372
406
  if (vesuAmount.minus(usdcAmountInWallet).greaterThan(0)) {
373
407
  //move assets to vesu
374
408
  try {
375
- const vesuCalls = await this.moveAssets(
409
+ const {calls: vesuCalls, status: vesuStatus} = await this.moveAssets(
376
410
  {
377
- to: Protocols.VESU.name,
411
+ to: Protocols.VAULT.name,
378
412
  from: Protocols.EXTENDED.name,
379
413
  amount: vesuAmount.minus(usdcAmountInWallet),
380
414
  },
381
415
  extendedAdapter,
382
416
  vesuAdapter
383
417
  );
418
+ if(!vesuStatus){
419
+ return [];
420
+ }
384
421
  calls.push(...vesuCalls);
385
422
  } catch (err) {
386
423
  logger.error(`Failed moving assets to vault: ${err}`);
@@ -401,18 +438,25 @@ export class VesuExtendedMultiplierStrategy<
401
438
  },
402
439
  extendedAdapter: ExtendedAdapter,
403
440
  vesuAdapter: VesuMultiplyAdapter
404
- ): Promise<Call[]> {
441
+ ): Promise<{
442
+ calls: Call[];
443
+ status: boolean;
444
+ }> {
405
445
  try {
406
446
  const avnuAdapter = await this.getAvnuAdapter();
407
447
  if (!avnuAdapter) {
408
448
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
409
- return [];
449
+ return {
450
+ calls: [],
451
+ status: false
452
+ };
410
453
  }
411
- logger.info("moveAssets params", params);
454
+ logger.info(`moveAssets params, ${JSON.stringify(params)}`);
412
455
  const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
413
456
  const {
414
457
  collateralPrice,
415
458
  } = await this.getAssetPrices();
459
+
416
460
  if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VAULT.name) {
417
461
  const proofsInfo = extendedAdapter.getProofs(
418
462
  true,
@@ -425,22 +469,63 @@ export class VesuExtendedMultiplierStrategy<
425
469
  await proofsInfo.callConstructor({ amount: params.amount })
426
470
  );
427
471
  calls.push(call);
428
- return calls;
472
+ return {
473
+ calls: [call],
474
+ status: true
475
+ };
429
476
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
477
+ const extendedLeverage = calculateExtendedLevergae();
478
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
479
+ if (!extendedHoldings) {
480
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
481
+ return {
482
+ calls: [],
483
+ status: false
484
+ };
485
+ }
486
+ const extendedHoldingAmount = new Web3Number(
487
+ extendedHoldings.availableForWithdrawal,
488
+ USDC_TOKEN_DECIMALS
489
+ );
490
+
491
+ const leftAmountAfterWithdrawalAmountInAccount = params.amount.minus(extendedHoldingAmount);
492
+ const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
493
+ const openLongPosition = await extendedAdapter.createOrder(
494
+ extendedLeverage.toString(),
495
+ btcAmount.toNumber(),
496
+ OrderSide.BUY
497
+ )
498
+ if (!openLongPosition) {
499
+ logger.error(`error opening long position: ${openLongPosition}`);
500
+ return {
501
+ calls: [],
502
+ status: false
503
+ };
504
+ }
505
+ await new Promise(resolve => setTimeout(resolve, 5000));
430
506
  const withdrawalFromExtended =
431
507
  await extendedAdapter.withdrawFromExtended(params.amount);
432
508
  if (withdrawalFromExtended) {
433
- /**
434
- * We need to move assets from my wallet back to vault contract
435
- */
436
- const calls = await this.moveAssetsToVaultAllocator(params.amount);
509
+ /**
510
+ * We need to move assets from my wallet back to vault contract
511
+ */
512
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
513
+ logger.info(`extendedHoldings after withdrawal ${extendedHoldings}`);
514
+ await new Promise(resolve => setTimeout(resolve, 10000));
515
+ const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
437
516
  if (calls.length > 0) {
438
- return calls;
517
+ return {
518
+ calls: calls,
519
+ status: true
520
+ };
439
521
  }
440
522
  } else {
441
523
  logger.error("withdrawal from extended failed");
524
+ return {
525
+ calls: [],
526
+ status: false
527
+ };
442
528
  }
443
- return [];
444
529
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
445
530
  //withdraw from vesu
446
531
  const vesuAmountInBTC = new Web3Number(
@@ -462,7 +547,10 @@ export class VesuExtendedMultiplierStrategy<
462
547
  await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
463
548
  );
464
549
  calls.push(swapCall);
465
- return calls;
550
+ return {
551
+ calls: calls,
552
+ status: true
553
+ };
466
554
  } else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
467
555
  const vesuAmountInBTC = new Web3Number(
468
556
  params.amount.dividedBy(collateralPrice.price).toNumber(),
@@ -494,19 +582,28 @@ export class VesuExtendedMultiplierStrategy<
494
582
  await proofsInfoDeposit.callConstructor({ amount: params.amount })
495
583
  );
496
584
  calls.push(callDeposit);
497
- return calls;
585
+ return {
586
+ calls: calls,
587
+ status: true
588
+ };
498
589
  }
499
- console.warn("moveAssets received unsupported route:", params);
500
- return [];
590
+ return {
591
+ calls: [],
592
+ status: false
593
+ };
501
594
  } catch (err) {
502
595
  logger.error(`error moving assets: ${err}`);
503
- return [];
596
+ return {
597
+ calls: [],
598
+ status: false
599
+ };
504
600
  }
505
601
  }
506
602
 
507
603
  async handleDeposit(): Promise<{
508
- extendedAmountInBTC : Web3Number,
509
- calls:Call[]}> {
604
+ extendedAmountInBTC: Web3Number,
605
+ calls: Call[]
606
+ }> {
510
607
  try {
511
608
  const vesuAdapter = await this.getVesuAdapter();
512
609
  const extendedAdapter = await this.getExtendedAdapter();
@@ -567,10 +664,10 @@ export class VesuExtendedMultiplierStrategy<
567
664
  collateralTokenAmount,
568
665
  collateralPrice.price
569
666
  );
570
- console.log("vesuAmountInBTC", vesuAmountInBTC);
571
- console.log("extendedAmountInBTC", extendedAmountInBTC);
667
+ logger.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
668
+
572
669
  let calls: Call[] = [];
573
- if(vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)){
670
+ if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
574
671
  const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
575
672
  const proofGroups = proofsInfo.proofs;
576
673
  const call = this.getManageCall(
@@ -581,7 +678,7 @@ export class VesuExtendedMultiplierStrategy<
581
678
  );
582
679
  const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
583
680
  if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
584
- console.log("error wbtc amount in vault allocator is less than vesu amount in btc", wbtcAmountInVaultAllocator, vesuAmountInBTC);
681
+ logger.info(`WBTC amount in vault allocator is less than vesu amount required in WBTC thus swapping, wbtcAmountInVaultAllocator: ${wbtcAmountInVaultAllocator}, vesuAmountInBTC: ${vesuAmountInBTC}`);
585
682
  const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
586
683
  const swapProofGroups = swapProofsInfo.proofs;
587
684
  const swapCall = this.getManageCall(
@@ -620,44 +717,54 @@ export class VesuExtendedMultiplierStrategy<
620
717
  }
621
718
  }
622
719
 
623
- async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter:ExtendedAdapter, vesuAdapter:VesuMultiplyAdapter, avnuAdapter:AvnuAdapter): Promise<boolean> {
720
+ async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter: ExtendedAdapter, vesuAdapter: VesuMultiplyAdapter, avnuAdapter: AvnuAdapter): Promise<boolean> {
624
721
  const {
625
722
  ask, bid
626
- }= await extendedAdapter.fetchOrderBookBTCUSDC();
723
+ } = await extendedAdapter.fetchOrderBookBTCUSDC();
627
724
  const price = ask.plus(bid).dividedBy(2);
628
- const btcToken = vesuAdapter.config.supportedPositions[1].asset;
725
+ const btcToken = vesuAdapter.config.supportedPositions[0].asset;
629
726
  const btcPriceAvnu = await avnuAdapter.getPriceOfToken(btcToken.address.toString());
630
727
  if (!btcPriceAvnu) {
631
728
  logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
632
729
  return false;
633
730
  }
634
731
  const priceDifference = price.minus(btcPriceAvnu).toNumber();
635
- if(priceDifference < MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED && priceDifference > MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED){
732
+ if (priceDifference < MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED && priceDifference > MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED) {
636
733
  return true;
637
734
  }
638
735
  logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
639
736
  return false;
640
737
  }
641
738
 
642
- async handleWithdraw(amount: Web3Number): Promise<Call[]> {
739
+ async handleWithdraw(amount: Web3Number): Promise<{calls: Call[], status: boolean}> {
643
740
  try {
644
741
  const usdcBalanceVaultAllocator = await this.getUnusedBalance()
645
- const usdcBalanceDifference = amount.minus(usdcBalanceVaultAllocator.usdValue);
742
+ const usdcBalanceDifference = amount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcBalanceVaultAllocator.usdValue);
646
743
  logger.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
744
+ let calls: Call[] = [];
745
+ let status: boolean = true;
647
746
  if (usdcBalanceDifference.lessThan(0)) {
648
747
  const withdrawCall = await this.getBringLiquidityCall({
649
- amount: amount
748
+ amount: usdcBalanceVaultAllocator.amount
650
749
  })
651
750
  logger.info("withdraw call", withdrawCall);
652
- return [withdrawCall];
751
+ calls.push(withdrawCall);
752
+ return {
753
+ calls:calls,
754
+ status:true
755
+ };
653
756
  }
654
757
  const vesuAdapter = await this.getVesuAdapter();
655
758
  const extendedAdapter = await this.getExtendedAdapter();
656
759
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
760
+ status = false;
657
761
  logger.error(
658
762
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
659
763
  );
660
- return [];
764
+ return {
765
+ calls:calls,
766
+ status:status
767
+ };
661
768
  }
662
769
  const { collateralTokenAmount } =
663
770
  await vesuAdapter.vesuAdapter.getAssetPrices();
@@ -665,22 +772,35 @@ export class VesuExtendedMultiplierStrategy<
665
772
  collateralPrice
666
773
  } = await this.getAssetPrices();
667
774
  const extendedPositon = await extendedAdapter.getAllOpenPositions();
775
+ if(!extendedPositon) {
776
+ status = false;
777
+ logger.error("error getting extended position", extendedPositon);
778
+ return {
779
+ calls:calls,
780
+ status:status
781
+ }
782
+ }
668
783
  const amountDistributionForWithdrawal =
669
784
  await calculateAmountDistributionForWithdrawal(
670
- amount,
785
+ usdcBalanceDifference,
671
786
  collateralPrice.price,
672
787
  collateralTokenAmount,
673
788
  extendedPositon
674
789
  );
675
790
  if (!amountDistributionForWithdrawal) {
791
+ status = false;
676
792
  logger.error(
677
793
  `error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
678
794
  );
679
- return [];
795
+ return {
796
+ calls:calls,
797
+ status:status
798
+ };
680
799
  }
681
800
  const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
682
- if (vesu_amount.greaterThan(0)) {
683
- const result = await this.moveAssets(
801
+
802
+ if (status && vesu_amount.greaterThan(0)) {
803
+ const {calls: vesuCalls, status: vesuStatus} = await this.moveAssets(
684
804
  {
685
805
  amount: vesu_amount,
686
806
  from: Protocols.VESU.name,
@@ -689,10 +809,11 @@ export class VesuExtendedMultiplierStrategy<
689
809
  extendedAdapter,
690
810
  vesuAdapter
691
811
  );
692
- return result;
812
+ status = vesuStatus;
813
+ calls.push(...vesuCalls);
693
814
  }
694
- if (extended_amount.greaterThan(0)) {
695
- const result = await this.moveAssets(
815
+ if (status && extended_amount.greaterThan(0)) {
816
+ const {calls: extendedCalls, status: extendedStatus} = await this.moveAssets(
696
817
  {
697
818
  amount: extended_amount,
698
819
  from: Protocols.EXTENDED.name,
@@ -701,12 +822,32 @@ export class VesuExtendedMultiplierStrategy<
701
822
  extendedAdapter,
702
823
  vesuAdapter
703
824
  );
704
- return result;
825
+ status = extendedStatus;
826
+ if(status) {
827
+ calls.push(...extendedCalls);
828
+ }else{
829
+ logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
830
+ return {
831
+ calls: [],
832
+ status: status
833
+ };
834
+ }
705
835
  }
706
- return [];
836
+ const withdrawCall = await this.getBringLiquidityCall({
837
+ amount: amount
838
+ })
839
+ logger.info("withdraw call", withdrawCall);
840
+ calls.push(withdrawCall);
841
+ return {
842
+ calls: calls,
843
+ status: status
844
+ };
707
845
  } catch (err) {
708
846
  logger.error(`error handling withdrawal: ${err}`);
709
- return [];
847
+ return {
848
+ calls: [],
849
+ status: false
850
+ };
710
851
  }
711
852
  }
712
853
 
@@ -714,7 +855,7 @@ export class VesuExtendedMultiplierStrategy<
714
855
  const allPositions: PositionInfo[] = [];
715
856
  for (let adapter of this.metadata.additionalInfo.adapters) {
716
857
  const positions = await adapter.adapter.getPositions();
717
- allPositions.push(...positions);
858
+ allPositions.push(...positions);
718
859
  }
719
860
 
720
861
  const assetPrice = await this.pricer.getPrice(this.asset().symbol);
@@ -863,6 +1004,7 @@ function getLooperSettings(
863
1004
  vesuMultiplyAdapter.getWithdrawLeaf()
864
1005
  );
865
1006
  vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
1007
+ vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
866
1008
  vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
867
1009
  vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
868
1010
  // Doubt here, should this be usdcToken.address, or wbtcToken.address?