@scallop-io/sui-scallop-sdk 0.44.6 → 0.44.7

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.
@@ -192,7 +192,7 @@ export declare class ScallopClient {
192
192
  * @param walletAddress - The wallet address of the owner.
193
193
  * @return Transaction block response or transaction block.
194
194
  */
195
- repay<S extends boolean>(poolCoinName: SupportPoolCoins, amount: number, sign: S | undefined, obligationId: string, walletAddress?: string): Promise<ScallopClientFnReturnType<S>>;
195
+ repay<S extends boolean>(poolCoinName: SupportPoolCoins, amount: number, sign: S | undefined, obligationId: string, obligationKey: string, walletAddress?: string): Promise<ScallopClientFnReturnType<S>>;
196
196
  /**
197
197
  * FlashLoan asset from the specific pool.
198
198
  *
@@ -262,6 +262,7 @@ export declare class ScallopQuery {
262
262
  */
263
263
  getBorrowIncentivePools(coinNames?: SupportBorrowIncentiveCoins[]): Promise<{
264
264
  usdc?: import("../types").BorrowIncentivePool | undefined;
265
+ usdt?: import("../types").BorrowIncentivePool | undefined;
265
266
  sui?: import("../types").BorrowIncentivePool | undefined;
266
267
  }>;
267
268
  /**
@@ -273,6 +274,7 @@ export declare class ScallopQuery {
273
274
  */
274
275
  getBorrowIncentiveAccounts(obligationId: string, coinNames?: SupportBorrowIncentiveCoins[]): Promise<{
275
276
  usdc?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
277
+ usdt?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
276
278
  sui?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
277
279
  }>;
278
280
  /**
@@ -9,6 +9,7 @@ import type { SupportBorrowIncentiveCoins } from '../types';
9
9
  */
10
10
  export declare const queryBorrowIncentivePools: (query: ScallopQuery, borrowIncentiveCoinNames?: SupportBorrowIncentiveCoins[]) => Promise<{
11
11
  usdc?: import("../types").BorrowIncentivePool | undefined;
12
+ usdt?: import("../types").BorrowIncentivePool | undefined;
12
13
  sui?: import("../types").BorrowIncentivePool | undefined;
13
14
  }>;
14
15
  /**
@@ -20,5 +21,6 @@ export declare const queryBorrowIncentivePools: (query: ScallopQuery, borrowInce
20
21
  */
21
22
  export declare const queryBorrowIncentiveAccounts: (query: ScallopQuery, obligationId: string, borrowIncentiveCoinNames?: SupportBorrowIncentiveCoins[]) => Promise<{
22
23
  usdc?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
24
+ usdt?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
23
25
  sui?: import("../types").ParsedBorrowIncentiveAccountData | undefined;
24
26
  }>;
@@ -77,6 +77,8 @@ export type ObligationDebt = {
77
77
  borrowedValue: number;
78
78
  borrowedValueWithWeight: number;
79
79
  borrowIndex: number;
80
+ requiredRepayAmount: number;
81
+ requiredRepayCoin: number;
80
82
  availableBorrowAmount: number;
81
83
  availableBorrowCoin: number;
82
84
  availableRepayAmount: number;
@@ -58,3 +58,11 @@ export declare const calculateBorrowIncentiveRewardPoolData: (parsedBorrowIncent
58
58
  export declare const parseOriginBorrowIncentiveAccountData: (originBorrowIncentiveAccountData: OriginBorrowIncentiveAccountData) => ParsedBorrowIncentiveAccountData;
59
59
  export declare const minBigNumber: (...args: BigNumber.Value[]) => BigNumber;
60
60
  export declare const maxBigNumber: (...args: BigNumber.Value[]) => BigNumber;
61
+ /**
62
+ * Dynamically adjust the decrease or increase ratio according to the amout
63
+ * @param amount - The amount required to calculate factor.
64
+ * @param scaleStep - The scale step required to determine the factor..
65
+ * @param type - The type of the calculation.
66
+ * @return The estimated factor
67
+ * */
68
+ export declare const estimatedFactor: (amount: number, scaleStep: number, type: 'increase' | 'decrease') => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "0.44.6",
3
+ "version": "0.44.7",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -40,7 +40,7 @@ export const SUPPORT_SPOOLS = ['ssui', 'susdc', 'susdt'] as const;
40
40
 
41
41
  export const SUPPORT_SPOOLS_REWARDS = ['sui'] as const;
42
42
 
43
- export const SUPPORT_BORROW_INCENTIVE_POOLS = ['sui', 'usdc'] as const;
43
+ export const SUPPORT_BORROW_INCENTIVE_POOLS = ['sui', 'usdc', 'usdt'] as const;
44
44
 
45
45
  export const SUPPORT_BORROW_INCENTIVE_REWARDS = ['sui'] as const;
46
46
  export const SUPPORT_ORACLES = ['supra', 'switchboard', 'pyth'] as const;
@@ -78,6 +78,7 @@ export const spoolRewardCoins: StakeRewardCoins = {
78
78
  export const borrowIncentiveRewardCoins: BorrowIncentiveRewardCoins = {
79
79
  sui: 'sui',
80
80
  usdc: 'sui',
81
+ usdt: 'sui',
81
82
  };
82
83
 
83
84
  export const coinIds: AssetCoinIds = {
@@ -1,6 +1,6 @@
1
1
  import { normalizeSuiAddress } from '@mysten/sui.js/utils';
2
2
  import { SuiKit } from '@scallop-io/sui-kit';
3
- import { ADDRESSES_ID } from '../constants';
3
+ import { ADDRESSES_ID, SUPPORT_BORROW_INCENTIVE_POOLS } from '../constants';
4
4
  import { ScallopAddress } from './scallopAddress';
5
5
  import { ScallopUtils } from './scallopUtils';
6
6
  import { ScallopBuilder } from './scallopBuilder';
@@ -481,6 +481,16 @@ export class ScallopClient {
481
481
  const sender = walletAddress || this.walletAddress;
482
482
  txBlock.setSender(sender);
483
483
 
484
+ const availableStake = (
485
+ SUPPORT_BORROW_INCENTIVE_POOLS as readonly SupportPoolCoins[]
486
+ ).includes(poolCoinName);
487
+ if (sign && availableStake) {
488
+ await txBlock.unstakeObligationQuick(
489
+ poolCoinName as SupportBorrowIncentiveCoins,
490
+ obligationId,
491
+ obligationKey
492
+ );
493
+ }
484
494
  const coin = await txBlock.borrowQuick(
485
495
  amount,
486
496
  poolCoinName,
@@ -488,6 +498,13 @@ export class ScallopClient {
488
498
  obligationKey
489
499
  );
490
500
  txBlock.transferObjects([coin], sender);
501
+ if (sign && availableStake) {
502
+ await txBlock.stakeObligationQuick(
503
+ poolCoinName as SupportBorrowIncentiveCoins,
504
+ obligationId,
505
+ obligationKey
506
+ );
507
+ }
491
508
 
492
509
  if (sign) {
493
510
  return (await this.suiKit.signAndSendTxn(
@@ -513,13 +530,31 @@ export class ScallopClient {
513
530
  amount: number,
514
531
  sign: S = true as S,
515
532
  obligationId: string,
533
+ obligationKey: string,
516
534
  walletAddress?: string
517
535
  ): Promise<ScallopClientFnReturnType<S>> {
518
536
  const txBlock = this.builder.createTxBlock();
519
537
  const sender = walletAddress || this.walletAddress;
520
538
  txBlock.setSender(sender);
521
539
 
540
+ const availableStake = (
541
+ SUPPORT_BORROW_INCENTIVE_POOLS as readonly SupportPoolCoins[]
542
+ ).includes(poolCoinName);
543
+ if (sign && availableStake) {
544
+ await txBlock.unstakeObligationQuick(
545
+ poolCoinName as SupportBorrowIncentiveCoins,
546
+ obligationId,
547
+ obligationKey
548
+ );
549
+ }
522
550
  await txBlock.repayQuick(amount, poolCoinName, obligationId);
551
+ if (sign && availableStake) {
552
+ await txBlock.stakeObligationQuick(
553
+ poolCoinName as SupportBorrowIncentiveCoins,
554
+ obligationId,
555
+ obligationKey
556
+ );
557
+ }
523
558
 
524
559
  if (sign) {
525
560
  return (await this.suiKit.signAndSendTxn(
@@ -1,6 +1,6 @@
1
1
  import BigNumber from 'bignumber.js';
2
2
  import { SUPPORT_POOLS, SUPPORT_SPOOLS } from '../constants';
3
- import { minBigNumber } from 'src/utils';
3
+ import { minBigNumber, estimatedFactor } from 'src/utils';
4
4
  import type { ScallopQuery } from '../models';
5
5
  import type {
6
6
  Market,
@@ -330,8 +330,8 @@ export const getObligationAccount = async (
330
330
  return assetCoinName === collateralCoinName;
331
331
  });
332
332
 
333
- const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
334
333
  const marketCollateral = market.collaterals[assetCoinName];
334
+ const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
335
335
  const coinPrice = coinPrices?.[assetCoinName];
336
336
  const coinAmount = coinAmounts?.[assetCoinName] ?? 0;
337
337
 
@@ -388,9 +388,10 @@ export const getObligationAccount = async (
388
388
  return assetCoinName === poolCoinName;
389
389
  });
390
390
 
391
- const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
392
391
  const marketPool = market.pools[assetCoinName];
392
+ const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
393
393
  const coinPrice = coinPrices?.[assetCoinName];
394
+ const coinAmount = coinAmounts?.[assetCoinName] ?? 0;
394
395
 
395
396
  if (marketPool && coinPrice) {
396
397
  const increasedRate = debt?.borrowIndex
@@ -398,13 +399,18 @@ export const getObligationAccount = async (
398
399
  : 0;
399
400
  const borrowedAmount = BigNumber(debt?.amount ?? 0);
400
401
  const borrowedCoin = borrowedAmount.shiftedBy(-1 * coinDecimal);
401
- const availableRepayAmount = borrowedAmount.multipliedBy(
402
+
403
+ const requiredRepayAmount = borrowedAmount.multipliedBy(
402
404
  increasedRate + 1
403
405
  );
406
+ const requiredRepayCoin = requiredRepayAmount.shiftedBy(-1 * coinDecimal);
407
+
408
+ const availableRepayAmount = BigNumber(coinAmount);
404
409
  const availableRepayCoin = availableRepayAmount.shiftedBy(
405
410
  -1 * coinDecimal
406
411
  );
407
- const borrowedValue = availableRepayCoin.multipliedBy(coinPrice);
412
+
413
+ const borrowedValue = requiredRepayCoin.multipliedBy(coinPrice);
408
414
  const borrowedValueWithWeight = borrowedValue.multipliedBy(
409
415
  marketPool.borrowWeight
410
416
  );
@@ -429,6 +435,8 @@ export const getObligationAccount = async (
429
435
  borrowedValue: borrowedValue.toNumber(),
430
436
  borrowedValueWithWeight: borrowedValueWithWeight.toNumber(),
431
437
  borrowIndex: Number(debt?.borrowIndex ?? 0),
438
+ requiredRepayAmount: requiredRepayAmount.toNumber(),
439
+ requiredRepayCoin: requiredRepayCoin.toNumber(),
432
440
  availableBorrowAmount: 0,
433
441
  availableBorrowCoin: 0,
434
442
  availableRepayAmount: availableRepayAmount.toNumber(),
@@ -481,16 +489,11 @@ export const getObligationAccount = async (
481
489
  }
482
490
  }
483
491
 
484
- let riskLevel =
485
- totalRequiredCollateralValue.isZero() &&
486
- totalBorrowedValueWithWeight.isZero()
487
- ? BigNumber(0)
488
- : totalBorrowedValueWithWeight.dividedBy(totalRequiredCollateralValue);
489
- riskLevel = riskLevel.isFinite()
490
- ? riskLevel.isLessThan(1)
491
- ? riskLevel
492
- : BigNumber(1)
493
- : BigNumber(1);
492
+ let riskLevel = totalRequiredCollateralValue.isZero()
493
+ ? BigNumber(0)
494
+ : totalBorrowedValueWithWeight.dividedBy(totalRequiredCollateralValue);
495
+ // Note: 100% represents the safety upper limit. Even if it exceeds 100% before it is liquidated, it will only display 100%.
496
+ riskLevel = riskLevel.isLessThan(1) ? riskLevel : BigNumber(1);
494
497
 
495
498
  const accountBalanceValue = totalDepositedValue
496
499
  .minus(totalBorrowedValue)
@@ -543,24 +546,38 @@ export const getObligationAccount = async (
543
546
  const marketCollateral =
544
547
  market.collaterals[collateralCoinName as SupportCollateralCoins];
545
548
  if (marketCollateral) {
546
- const availableWithdrawAmount =
549
+ let estimatedAvailableWithdrawAmount = BigNumber(
550
+ obligationAccount.totalAvailableCollateralValue
551
+ )
552
+ .dividedBy(marketCollateral.collateralFactor)
553
+ .dividedBy(marketCollateral.coinPrice)
554
+ .shiftedBy(marketCollateral.coinDecimal);
555
+ estimatedAvailableWithdrawAmount =
547
556
  obligationAccount.totalBorrowedValueWithWeight === 0
548
- ? BigNumber(obligationCollateral.depositedAmount)
557
+ ? // Note: when there is no debt record, there is no need to estimate and the deposited amount is directly used as available withdraw.
558
+ BigNumber(obligationCollateral.depositedAmount)
549
559
  : minBigNumber(
550
- BigNumber(obligationAccount.totalAvailableCollateralValue)
551
- .dividedBy(marketCollateral.collateralFactor)
552
- .dividedBy(marketCollateral.coinPrice)
560
+ estimatedAvailableWithdrawAmount
553
561
  // Note: reduced chance of failure when calculations are inaccurate
554
- .multipliedBy(0.99)
562
+ .multipliedBy(
563
+ estimatedFactor(
564
+ BigNumber(obligationAccount.totalAvailableCollateralValue)
565
+ .dividedBy(marketCollateral.collateralFactor)
566
+ .toNumber(),
567
+ 3,
568
+ 'increase'
569
+ )
570
+ )
555
571
  .toNumber(),
556
572
  obligationCollateral.depositedAmount,
557
573
  marketCollateral.depositAmount
558
574
  );
559
575
  obligationCollateral.availableWithdrawAmount =
560
- availableWithdrawAmount.toNumber();
561
- obligationCollateral.availableWithdrawCoin = availableWithdrawAmount
562
- .shiftedBy(-1 * obligationCollateral.coinDecimal)
563
- .toNumber();
576
+ estimatedAvailableWithdrawAmount.toNumber();
577
+ obligationCollateral.availableWithdrawCoin =
578
+ estimatedAvailableWithdrawAmount
579
+ .shiftedBy(-1 * obligationCollateral.coinDecimal)
580
+ .toNumber();
564
581
  }
565
582
  }
566
583
  for (const [poolCoinName, obligationDebt] of Object.entries(
@@ -568,33 +585,49 @@ export const getObligationAccount = async (
568
585
  )) {
569
586
  const marketPool = market.pools[poolCoinName as SupportPoolCoins];
570
587
  if (marketPool) {
571
- const availableRepayAmount = BigNumber(
572
- obligationDebt.availableRepayAmount
588
+ const estimatedRequiredRepayAmount = BigNumber(
589
+ obligationDebt.requiredRepayAmount
573
590
  )
574
- // Note: reduced chance of failure when calculations are inaccurate
575
- .multipliedBy(1.01);
591
+ // Note: reduced chance of not being able to repay in full when calculations are inaccurate,
592
+ // and the contract will not actually take the excess amount.
593
+ .multipliedBy(
594
+ estimatedFactor(obligationDebt.borrowedValue, 3, 'decrease')
595
+ );
576
596
 
577
- const availableBorrowAmount =
597
+ let estimatedAvailableBorrowAmount = BigNumber(
598
+ obligationAccount.totalAvailableCollateralValue
599
+ )
600
+ .dividedBy(marketPool.borrowWeight)
601
+ .shiftedBy(marketPool.coinDecimal)
602
+ .dividedBy(marketPool.coinPrice);
603
+ estimatedAvailableBorrowAmount =
578
604
  obligationAccount.totalAvailableCollateralValue !== 0
579
605
  ? minBigNumber(
580
- BigNumber(obligationAccount.totalAvailableCollateralValue)
581
- .dividedBy(
582
- BigNumber(marketPool.coinPrice).multipliedBy(
583
- marketPool.borrowWeight
606
+ estimatedAvailableBorrowAmount
607
+ // Note: reduced chance of failure when calculations are inaccurate
608
+ .multipliedBy(
609
+ estimatedFactor(
610
+ estimatedAvailableBorrowAmount
611
+ .shiftedBy(-1 * marketPool.coinDecimal)
612
+ .multipliedBy(marketPool.coinPrice)
613
+ .toNumber(),
614
+ 3,
615
+ 'increase'
584
616
  )
585
617
  )
586
- // Note: reduced chance of failure when calculations are inaccurate
587
- .multipliedBy(0.99)
588
618
  .toNumber(),
589
619
  marketPool.supplyAmount
590
620
  )
591
621
  : BigNumber(0);
592
- obligationDebt.availableBorrowAmount = availableBorrowAmount.toNumber();
593
- obligationDebt.availableBorrowCoin = availableBorrowAmount
622
+
623
+ obligationDebt.availableBorrowAmount =
624
+ estimatedAvailableBorrowAmount.toNumber();
625
+ obligationDebt.availableBorrowCoin = estimatedAvailableBorrowAmount
594
626
  .shiftedBy(-1 * obligationDebt.coinDecimal)
595
627
  .toNumber();
596
- obligationDebt.availableRepayAmount = availableRepayAmount.toNumber();
597
- obligationDebt.availableRepayCoin = availableRepayAmount
628
+ obligationDebt.requiredRepayAmount =
629
+ estimatedRequiredRepayAmount.toNumber();
630
+ obligationDebt.requiredRepayCoin = estimatedRequiredRepayAmount
598
631
  .shiftedBy(-1 * obligationDebt.coinDecimal)
599
632
  .toNumber();
600
633
  }
@@ -99,6 +99,8 @@ export type ObligationDebt = {
99
99
  borrowedValue: number;
100
100
  borrowedValueWithWeight: number;
101
101
  borrowIndex: number;
102
+ requiredRepayAmount: number;
103
+ requiredRepayCoin: number;
102
104
  availableBorrowAmount: number;
103
105
  availableBorrowCoin: number;
104
106
  availableRepayAmount: number;
@@ -612,3 +612,29 @@ export const maxBigNumber = (...args: BigNumber.Value[]) => {
612
612
  )
613
613
  );
614
614
  };
615
+
616
+ /**
617
+ * Dynamically adjust the decrease or increase ratio according to the amout
618
+ * @param amount - The amount required to calculate factor.
619
+ * @param scaleStep - The scale step required to determine the factor..
620
+ * @param type - The type of the calculation.
621
+ * @return The estimated factor
622
+ * */
623
+ export const estimatedFactor = (
624
+ amount: number,
625
+ scaleStep: number,
626
+ type: 'increase' | 'decrease'
627
+ ) => {
628
+ const amountOfDigits = Math.max(
629
+ 1,
630
+ Math.floor(Math.log10(Math.abs(amount)) + 1)
631
+ );
632
+
633
+ const adjustScale =
634
+ Math.max(Math.floor((amountOfDigits - 1) / scaleStep), 1) + 1;
635
+
636
+ let adjustFactor = Math.pow(10, -adjustScale);
637
+ adjustFactor = type === 'increase' ? 1 - adjustFactor : 1 + adjustFactor;
638
+
639
+ return adjustFactor;
640
+ };