@scallop-io/sui-scallop-sdk 0.44.3 → 0.44.5

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.
@@ -4,6 +4,7 @@ export interface AddressesInterface {
4
4
  core: {
5
5
  version: string;
6
6
  versionCap: string;
7
+ object: string;
7
8
  market: string;
8
9
  adminCap: string;
9
10
  coinDecimalsRegistry: string;
@@ -46,6 +47,7 @@ export interface AddressesInterface {
46
47
  spool: {
47
48
  id: string;
48
49
  adminCap: string;
50
+ object: string;
49
51
  pools: Partial<Record<SupportStakeMarketCoins, {
50
52
  id: string;
51
53
  rewardPoolId: string;
@@ -54,6 +56,7 @@ export interface AddressesInterface {
54
56
  borrowIncentive: {
55
57
  id: string;
56
58
  adminCap: string;
59
+ object: string;
57
60
  query: string;
58
61
  incentivePools: string;
59
62
  incentiveAccounts: string;
@@ -59,6 +59,8 @@ export type OriginBorrowIncentiveRewardPoolData = {
59
59
  claimed_rewards: string;
60
60
  exchange_rate_denominator: string;
61
61
  exchange_rate_numerator: string;
62
+ rewards_fee_rate_denominator: string;
63
+ rewards_fee_rate_numerator: string;
62
64
  remaining_reward: string;
63
65
  reward_type: {
64
66
  name: string;
@@ -67,8 +69,10 @@ export type OriginBorrowIncentiveRewardPoolData = {
67
69
  export type ParsedBorrowIncentiveRewardPoolData = {
68
70
  rewardType: string;
69
71
  claimedRewards: number;
70
- exchangeRateNumerator: number;
71
72
  exchangeRateDenominator: number;
73
+ exchangeRateNumerator: number;
74
+ rewardsFeeRateDenominator: number;
75
+ rewardsFeeRateNumerator: number;
72
76
  remainingRewards: number;
73
77
  };
74
78
  export type CalculatedBorrowIncentiveRewardPoolData = {
@@ -83,6 +87,7 @@ export type CalculatedBorrowIncentiveRewardPoolData = {
83
87
  claimedRewardCoin: number;
84
88
  claimedRewardValue: number;
85
89
  rewardPerSec: number;
90
+ rewardFee: number;
86
91
  };
87
92
  export type BorrowIncentiveAccounts = OptionalKeys<Record<SupportBorrowIncentiveCoins, ParsedBorrowIncentiveAccountData>>;
88
93
  export type OriginBorrowIncentiveAccountData = {
@@ -43,6 +43,11 @@ export type InterestModel = {
43
43
  value: string;
44
44
  };
45
45
  };
46
+ borrow_fee_rate: {
47
+ fields: {
48
+ value: string;
49
+ };
50
+ };
46
51
  high_kink: {
47
52
  fields: {
48
53
  value: string;
@@ -115,7 +120,7 @@ export type MarketPool = {
115
120
  coinWrappedType: CoinWrappedType;
116
121
  coinDecimal: number;
117
122
  coinPrice: number;
118
- } & Required<Pick<ParsedMarketPoolData, 'highKink' | 'midKink' | 'reserveFactor' | 'borrowWeight' | 'marketCoinSupplyAmount' | 'minBorrowAmount'>> & CalculatedMarketPoolData;
123
+ } & Required<Pick<ParsedMarketPoolData, 'highKink' | 'midKink' | 'reserveFactor' | 'borrowWeight' | 'borrowFee' | 'marketCoinSupplyAmount' | 'minBorrowAmount'>> & CalculatedMarketPoolData;
119
124
  export type MarketCollateral = {
120
125
  coinName: SupportCollateralCoins;
121
126
  symbol: string;
@@ -148,6 +153,9 @@ export type OriginMarketPoolData = {
148
153
  borrowWeight: {
149
154
  value: string;
150
155
  };
156
+ borrowFeeRate: {
157
+ value: string;
158
+ };
151
159
  baseBorrowRatePerSec: {
152
160
  value: string;
153
161
  };
@@ -178,6 +186,7 @@ export type ParsedMarketPoolData = {
178
186
  reserveAmount: number;
179
187
  reserveFactor: number;
180
188
  borrowWeight: number;
189
+ borrowFee: number;
181
190
  baseBorrowRate: number;
182
191
  borrowRateOnHighKink: number;
183
192
  borrowRateOnMidKink: number;
@@ -319,6 +328,9 @@ export interface MarketQueryInterface {
319
328
  borrowWeight: {
320
329
  value: string;
321
330
  };
331
+ borrowFeeRate: {
332
+ value: string;
333
+ };
322
334
  type: {
323
335
  name: string;
324
336
  };
@@ -48,6 +48,7 @@ export type ObligationAccount = {
48
48
  totalBorrowedPools: number;
49
49
  collaterals: OptionalKeys<Record<SupportCollateralCoins, ObligationCollateral>>;
50
50
  debts: OptionalKeys<Record<SupportPoolCoins, ObligationDebt>>;
51
+ borrowIncentives: OptionalKeys<Record<SupportPoolCoins, ObligationBorrowIncentive>>;
51
52
  };
52
53
  export type ObligationCollateral = {
53
54
  coinName: SupportCollateralCoins;
@@ -81,6 +82,18 @@ export type ObligationDebt = {
81
82
  availableRepayAmount: number;
82
83
  availableRepayCoin: number;
83
84
  };
85
+ export type ObligationBorrowIncentive = {
86
+ coinName: SupportPoolCoins;
87
+ coinType: string;
88
+ rewardCoinType: string;
89
+ symbol: string;
90
+ coinDecimal: number;
91
+ rewardCoinDecimal: number;
92
+ coinPrice: number;
93
+ rewardCoinPrice: number;
94
+ availableClaimAmount: number;
95
+ availableClaimCoin: number;
96
+ };
84
97
  export type TotalValueLocked = {
85
98
  supplyValue: number;
86
99
  borrowValue: number;
@@ -59,13 +59,17 @@ export type OriginSpoolRewardPoolData = {
59
59
  claimed_rewards: string;
60
60
  exchange_rate_denominator: string;
61
61
  exchange_rate_numerator: string;
62
+ fee_rate_denominator: string;
63
+ fee_rate_numerator: string;
62
64
  rewards: string;
63
65
  spool_id: string;
64
66
  };
65
67
  export type ParsedSpoolRewardPoolData = {
66
68
  claimedRewards: number;
67
- exchangeRateNumerator: number;
68
69
  exchangeRateDenominator: number;
70
+ exchangeRateNumerator: number;
71
+ feeRateDenominator: number;
72
+ feeRateNumerator: number;
69
73
  rewards: number;
70
74
  spoolId: string;
71
75
  };
@@ -81,6 +85,7 @@ export type CalculatedSpoolRewardPoolData = {
81
85
  claimedRewardCoin: number;
82
86
  claimedRewardValue: number;
83
87
  rewardPerSec: number;
88
+ rewardFee: number;
84
89
  };
85
90
  export type StakePools = OptionalKeys<Record<SupportStakeMarketCoins, StakePool>>;
86
91
  export type StakeRewardPools = OptionalKeys<Record<SupportStakeMarketCoins, StakeRewardPool>>;
@@ -113,8 +118,10 @@ export interface StakeRewardPool {
113
118
  id: string;
114
119
  type: string;
115
120
  stakePoolId: string;
116
- ratioNumerator: number;
117
121
  ratioDenominator: number;
122
+ ratioNumerator: number;
123
+ feeRateDenominator: number;
124
+ feeRateNumerator: number;
118
125
  rewards: number;
119
126
  claimedRewards: number;
120
127
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-scallop-sdk",
3
- "version": "0.44.3",
3
+ "version": "0.44.5",
4
4
  "description": "Typescript sdk for interacting with Scallop contract on SUI",
5
5
  "keywords": [
6
6
  "sui",
@@ -5,6 +5,9 @@ export const ADDRESSES_ID = '6462a088a7ace142bb6d7e9b';
5
5
  export const PROTOCOL_OBJECT_ID =
6
6
  '0xefe8b36d5b2e43728cc323298626b83177803521d195cfb11e15b910e892fddf';
7
7
 
8
+ export const BORROW_FEE_PROTOCOL_ID =
9
+ '0xc38f849e81cfe46d4e4320f508ea7dda42934a329d5a6571bb4c3cb6ea63f5da';
10
+
8
11
  export const SUPPORT_POOLS = [
9
12
  'eth',
10
13
  'btc',
@@ -11,6 +11,7 @@ const EMPTY_ADDRESSES: AddressesInterface = {
11
11
  core: {
12
12
  version: '',
13
13
  versionCap: '',
14
+ object: '',
14
15
  market: '',
15
16
  adminCap: '',
16
17
  coinDecimalsRegistry: '',
@@ -188,6 +189,7 @@ const EMPTY_ADDRESSES: AddressesInterface = {
188
189
  spool: {
189
190
  id: '',
190
191
  adminCap: '',
192
+ object: '',
191
193
  pools: {
192
194
  ssui: {
193
195
  id: '',
@@ -202,6 +204,7 @@ const EMPTY_ADDRESSES: AddressesInterface = {
202
204
  borrowIncentive: {
203
205
  id: '',
204
206
  adminCap: '',
207
+ object: '',
205
208
  query: '',
206
209
  incentivePools: '',
207
210
  incentiveAccounts: '',
@@ -159,8 +159,10 @@ export class ScallopUtils {
159
159
  * @return Market coin type.
160
160
  */
161
161
  public parseMarketCoinType(coinName: SupportCoins) {
162
+ const protocolObjectId =
163
+ this._address.get('core.object') || PROTOCOL_OBJECT_ID;
162
164
  const coinType = this.parseCoinType(coinName);
163
- return `${PROTOCOL_OBJECT_ID}::reserve::MarketCoin<${coinType}>`;
165
+ return `${protocolObjectId}::reserve::MarketCoin<${coinType}>`;
164
166
  }
165
167
 
166
168
  /**
@@ -1,3 +1,4 @@
1
+ import { normalizeStructTag } from '@mysten/sui.js/utils';
1
2
  import { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
2
3
  import { SUPPORT_BORROW_INCENTIVE_POOLS } from '../constants';
3
4
  import {
@@ -49,7 +50,7 @@ export const queryBorrowIncentivePools = async (
49
50
 
50
51
  const borrowIncentivePools: BorrowIncentivePools = {};
51
52
  for (const pool of borrowIncentivePoolsQueryData.incentive_pools) {
52
- const coinType = '0x' + pool.pool_type.name;
53
+ const coinType = normalizeStructTag(pool.pool_type.name);
53
54
  const coinName =
54
55
  query.utils.parseCoinNameFromType<SupportBorrowIncentiveCoins>(coinType);
55
56
  const rewardCoinName =
@@ -1,9 +1,11 @@
1
+ import { normalizeStructTag } from '@mysten/sui.js/utils';
1
2
  import { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
2
3
  import BigNumber from 'bignumber.js';
3
4
  import {
4
5
  SUPPORT_POOLS,
5
6
  PROTOCOL_OBJECT_ID,
6
7
  SUPPORT_COLLATERALS,
8
+ BORROW_FEE_PROTOCOL_ID,
7
9
  } from '../constants';
8
10
  import {
9
11
  parseOriginMarketPoolData,
@@ -59,7 +61,7 @@ export const queryMarket = async (query: ScallopQuery) => {
59
61
  const collaterals: MarketCollaterals = {};
60
62
 
61
63
  for (const pool of marketData.pools) {
62
- const coinType = '0x' + pool.type.name;
64
+ const coinType = normalizeStructTag(pool.type.name);
63
65
  const poolCoinName =
64
66
  query.utils.parseCoinNameFromType<SupportPoolCoins>(coinType);
65
67
  const coinPrice =
@@ -83,6 +85,7 @@ export const queryMarket = async (query: ScallopQuery) => {
83
85
  reserve: pool.reserve,
84
86
  reserveFactor: pool.reserveFactor,
85
87
  borrowWeight: pool.borrowWeight,
88
+ borrowFeeRate: pool.borrowFeeRate,
86
89
  baseBorrowRatePerSec: pool.baseBorrowRatePerSec,
87
90
  borrowRateOnHighKink: pool.borrowRateOnHighKink,
88
91
  borrowRateOnMidKink: pool.borrowRateOnMidKink,
@@ -108,6 +111,7 @@ export const queryMarket = async (query: ScallopQuery) => {
108
111
  midKink: parsedMarketPoolData.midKink,
109
112
  reserveFactor: parsedMarketPoolData.reserveFactor,
110
113
  borrowWeight: parsedMarketPoolData.borrowWeight,
114
+ borrowFee: parsedMarketPoolData.borrowFee,
111
115
  marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
112
116
  minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
113
117
  ...calculatedMarketPoolData,
@@ -115,7 +119,7 @@ export const queryMarket = async (query: ScallopQuery) => {
115
119
  }
116
120
 
117
121
  for (const collateral of marketData.collaterals) {
118
- const coinType = '0x' + collateral.type.name;
122
+ const coinType = normalizeStructTag(collateral.type.name);
119
123
  const collateralCoinName =
120
124
  query.utils.parseCoinNameFromType<SupportCollateralCoins>(coinType);
121
125
  const coinPrice =
@@ -242,6 +246,7 @@ export const getMarketPool = async (
242
246
  let balanceSheet: BalanceSheet | undefined;
243
247
  let borrowIndex: BorrowIndex | undefined;
244
248
  let interestModel: InterestModel | undefined;
249
+ let borrowFeeRate: { value: string } | undefined;
245
250
  if (marketObject) {
246
251
  if (marketObject.content && 'fields' in marketObject.content) {
247
252
  const fields = marketObject.content.fields as any;
@@ -324,10 +329,36 @@ export const getMarketPool = async (
324
329
  .fields as any;
325
330
  interestModel = dynamicFields.value.fields;
326
331
  }
332
+
333
+ // Get borrow fee.
334
+ const borrowFeeDynamicFieldObjectResponse = await query.suiKit
335
+ .client()
336
+ .getDynamicFieldObject({
337
+ parentId: marketId,
338
+ name: {
339
+ type: `${BORROW_FEE_PROTOCOL_ID}::market_dynamic_keys::BorrowFeeKey`,
340
+ value: {
341
+ type: {
342
+ name: coinType.substring(2),
343
+ },
344
+ },
345
+ },
346
+ });
347
+
348
+ const borrowFeeDynamicFieldObject =
349
+ borrowFeeDynamicFieldObjectResponse.data;
350
+ if (
351
+ borrowFeeDynamicFieldObject &&
352
+ borrowFeeDynamicFieldObject.content &&
353
+ 'fields' in borrowFeeDynamicFieldObject.content
354
+ ) {
355
+ const dynamicFields = borrowFeeDynamicFieldObject.content.fields as any;
356
+ borrowFeeRate = dynamicFields.value.fields;
357
+ }
327
358
  }
328
359
  }
329
360
 
330
- if (balanceSheet && borrowIndex && interestModel) {
361
+ if (balanceSheet && borrowIndex && interestModel && borrowFeeRate) {
331
362
  const parsedMarketPoolData = parseOriginMarketPoolData({
332
363
  type: interestModel.type.fields,
333
364
  maxBorrowRate: interestModel.max_borrow_rate.fields,
@@ -341,6 +372,7 @@ export const getMarketPool = async (
341
372
  reserve: balanceSheet.revenue,
342
373
  reserveFactor: interestModel.revenue_factor.fields,
343
374
  borrowWeight: interestModel.borrow_weight.fields,
375
+ borrowFeeRate: borrowFeeRate,
344
376
  baseBorrowRatePerSec: interestModel.base_borrow_rate_per_sec.fields,
345
377
  borrowRateOnHighKink: interestModel.borrow_rate_on_high_kink.fields,
346
378
  borrowRateOnMidKink: interestModel.borrow_rate_on_mid_kink.fields,
@@ -369,6 +401,7 @@ export const getMarketPool = async (
369
401
  midKink: parsedMarketPoolData.midKink,
370
402
  reserveFactor: parsedMarketPoolData.reserveFactor,
371
403
  borrowWeight: parsedMarketPoolData.borrowWeight,
404
+ borrowFee: parsedMarketPoolData.borrowFee,
372
405
  marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
373
406
  minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
374
407
  ...calculatedMarketPoolData,
@@ -563,6 +596,8 @@ export const getObligations = async (
563
596
  ownerAddress?: string
564
597
  ) => {
565
598
  const owner = ownerAddress || query.suiKit.currentAddress();
599
+ const protocolObjectId =
600
+ query.address.get('core.object') || PROTOCOL_OBJECT_ID;
566
601
  const keyObjectsResponse: SuiObjectResponse[] = [];
567
602
  let hasNextPage = false;
568
603
  let nextCursor: string | null = null;
@@ -572,7 +607,7 @@ export const getObligations = async (
572
607
  .getOwnedObjects({
573
608
  owner,
574
609
  filter: {
575
- StructType: `${PROTOCOL_OBJECT_ID}::obligation::ObligationKey`,
610
+ StructType: `${protocolObjectId}::obligation::ObligationKey`,
576
611
  },
577
612
  cursor: nextCursor,
578
613
  });
@@ -19,6 +19,7 @@ import type {
19
19
  CoinPrices,
20
20
  SupportMarketCoins,
21
21
  TotalValueLocked,
22
+ SupportBorrowIncentiveCoins,
22
23
  } from '../types';
23
24
 
24
25
  /**
@@ -164,7 +165,9 @@ export const getLending = async (
164
165
  availableUnstakeAmount = availableUnstakeAmount.plus(
165
166
  accountStakedMarketCoinAmount
166
167
  );
167
- availableUnstakeCoin = availableUnstakeAmount.shiftedBy(-1 * coinDecimal);
168
+ availableUnstakeCoin = availableUnstakeAmount.shiftedBy(
169
+ -1 * spool.coinDecimal
170
+ );
168
171
 
169
172
  const baseIndexRate = 1_000_000_000;
170
173
  const increasedPointRate = spool?.currentPointIndex
@@ -173,13 +176,15 @@ export const getLending = async (
173
176
  )
174
177
  : 1;
175
178
  availableClaimAmount = availableClaimAmount.plus(
176
- BigNumber(stakeAccount.staked)
179
+ accountStakedMarketCoinAmount
177
180
  .multipliedBy(increasedPointRate)
178
181
  .plus(stakeAccount.points)
179
182
  .multipliedBy(spool.exchangeRateNumerator)
180
183
  .dividedBy(spool.exchangeRateDenominator)
181
184
  );
182
- availableClaimCoin = availableClaimAmount.shiftedBy(-1 * coinDecimal);
185
+ availableClaimCoin = availableClaimAmount.shiftedBy(
186
+ -1 * spool.rewardCoinDecimal
187
+ );
183
188
  }
184
189
  }
185
190
 
@@ -298,12 +303,16 @@ export const getObligationAccount = async (
298
303
  ]),
299
304
  ];
300
305
  const obligationQuery = await query.queryObligation(obligationId);
306
+ const borrowIncentivePools = await query.getBorrowIncentivePools();
307
+ const borrowIncentiveAccounts =
308
+ await query.getBorrowIncentiveAccounts(obligationId);
301
309
  coinPrices = coinPrices || (await query.utils.getCoinPrices(assetCoinNames));
302
310
  coinAmounts =
303
311
  coinAmounts || (await query.getCoinAmounts(assetCoinNames, ownerAddress));
304
312
 
305
313
  const collaterals: ObligationAccount['collaterals'] = {};
306
314
  const debts: ObligationAccount['debts'] = {};
315
+ const borrowIncentives: ObligationAccount['borrowIncentives'] = {};
307
316
  let totalDepositedPools = 0;
308
317
  let totalDepositedValue = BigNumber(0);
309
318
  let totalBorrowCapacityValue = BigNumber(0);
@@ -419,6 +428,50 @@ export const getObligationAccount = async (
419
428
  }
420
429
  }
421
430
 
431
+ for (const [poolCoinName, borrowIncentiveAccount] of Object.entries(
432
+ borrowIncentiveAccounts
433
+ )) {
434
+ const coinName = poolCoinName as SupportBorrowIncentiveCoins;
435
+ const borrowIncentivePool = borrowIncentivePools[coinName];
436
+
437
+ let availableClaimAmount = BigNumber(0);
438
+ let availableClaimCoin = BigNumber(0);
439
+ if (borrowIncentivePool) {
440
+ const accountBorrowedAmount = BigNumber(borrowIncentiveAccount.amount);
441
+ const baseIndexRate = 1_000_000_000;
442
+ const increasedPointRate = borrowIncentivePool.currentPointIndex
443
+ ? BigNumber(
444
+ borrowIncentivePool.currentPointIndex - borrowIncentiveAccount.index
445
+ ).dividedBy(baseIndexRate)
446
+ : 1;
447
+ availableClaimAmount = availableClaimAmount.plus(
448
+ accountBorrowedAmount
449
+ .multipliedBy(increasedPointRate)
450
+ .plus(borrowIncentiveAccount.points)
451
+ .multipliedBy(borrowIncentivePool.exchangeRateNumerator)
452
+ .dividedBy(borrowIncentivePool.exchangeRateDenominator)
453
+ );
454
+ availableClaimCoin = availableClaimAmount.shiftedBy(
455
+ -1 * borrowIncentivePool.rewardCoinDecimal
456
+ );
457
+
458
+ if (availableClaimAmount.isGreaterThan(0)) {
459
+ borrowIncentives[coinName] = {
460
+ coinName: borrowIncentivePool.coinName,
461
+ coinType: borrowIncentivePool.coinType,
462
+ rewardCoinType: borrowIncentivePool.rewardCoinType,
463
+ symbol: borrowIncentivePool.symbol,
464
+ coinDecimal: borrowIncentivePool.coinDecimal,
465
+ rewardCoinDecimal: borrowIncentivePool.rewardCoinDecimal,
466
+ coinPrice: borrowIncentivePool.coinPrice,
467
+ rewardCoinPrice: borrowIncentivePool.rewardCoinPrice,
468
+ availableClaimAmount: availableClaimAmount.toNumber(),
469
+ availableClaimCoin: availableClaimCoin.toNumber(),
470
+ };
471
+ }
472
+ }
473
+ }
474
+
422
475
  let riskLevel =
423
476
  totalRequiredCollateralValue.isZero() &&
424
477
  totalBorrowedValueWithWeight.isZero()
@@ -472,6 +525,7 @@ export const getObligationAccount = async (
472
525
  totalBorrowedPools,
473
526
  collaterals,
474
527
  debts,
528
+ borrowIncentives,
475
529
  };
476
530
 
477
531
  for (const [collateralCoinName, obligationCollateral] of Object.entries(
@@ -500,10 +554,10 @@ export const getObligationAccount = async (
500
554
  .toNumber();
501
555
  }
502
556
  }
503
- for (const [assetCoinName, obligationDebt] of Object.entries(
557
+ for (const [poolCoinName, obligationDebt] of Object.entries(
504
558
  obligationAccount.debts
505
559
  )) {
506
- const marketPool = market.pools[assetCoinName as SupportPoolCoins];
560
+ const marketPool = market.pools[poolCoinName as SupportPoolCoins];
507
561
  if (marketPool) {
508
562
  const availableRepayAmount = BigNumber(
509
563
  obligationDebt.availableRepayAmount