@scallop-io/sui-scallop-sdk 1.4.1-alpha.1 → 1.4.2-rc.1

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.
Files changed (88) hide show
  1. package/dist/constants/common.d.ts +4 -4
  2. package/dist/constants/enum.d.ts +2 -2
  3. package/dist/constants/poolAddress.d.ts +16 -4
  4. package/dist/constants/queryKeys.d.ts +2 -2
  5. package/dist/constants/tokenBucket.d.ts +2 -2
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1314 -653
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +1269 -609
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/models/scallopBuilder.d.ts +2 -1
  12. package/dist/models/scallopCache.d.ts +2 -0
  13. package/dist/models/scallopQuery.d.ts +46 -20
  14. package/dist/models/scallopUtils.d.ts +5 -3
  15. package/dist/queries/borrowIncentiveQuery.d.ts +12 -0
  16. package/dist/queries/coreQuery.d.ts +18 -17
  17. package/dist/queries/index.d.ts +2 -0
  18. package/dist/queries/isolatedAssetQuery.d.ts +2 -2
  19. package/dist/queries/objectsQuery.d.ts +3 -0
  20. package/dist/queries/poolAddressesQuery.d.ts +18 -0
  21. package/dist/queries/portfolioQuery.d.ts +2 -0
  22. package/dist/queries/priceQuery.d.ts +4 -0
  23. package/dist/queries/sCoinQuery.d.ts +1 -1
  24. package/dist/queries/spoolQuery.d.ts +6 -2
  25. package/dist/test.d.ts +1 -0
  26. package/dist/types/builder/borrowIncentive.d.ts +5 -5
  27. package/dist/types/builder/core.d.ts +20 -16
  28. package/dist/types/builder/loyaltyProgram.d.ts +1 -1
  29. package/dist/types/builder/referral.d.ts +4 -4
  30. package/dist/types/builder/sCoin.d.ts +2 -2
  31. package/dist/types/builder/spool.d.ts +4 -4
  32. package/dist/types/builder/vesca.d.ts +6 -6
  33. package/dist/types/query/core.d.ts +22 -5
  34. package/dist/types/query/spool.d.ts +20 -0
  35. package/dist/types/utils.d.ts +7 -2
  36. package/dist/utils/core.d.ts +2 -0
  37. package/dist/utils/index.d.ts +2 -0
  38. package/dist/utils/query.d.ts +1 -1
  39. package/dist/utils/util.d.ts +1 -0
  40. package/package.json +7 -7
  41. package/src/builders/borrowIncentiveBuilder.ts +28 -15
  42. package/src/builders/coreBuilder.ts +76 -49
  43. package/src/builders/loyaltyProgramBuilder.ts +4 -3
  44. package/src/builders/referralBuilder.ts +23 -10
  45. package/src/builders/sCoinBuilder.ts +8 -6
  46. package/src/builders/spoolBuilder.ts +21 -14
  47. package/src/builders/vescaBuilder.ts +23 -13
  48. package/src/constants/coinGecko.ts +2 -3
  49. package/src/constants/common.ts +5 -19
  50. package/src/constants/enum.ts +20 -35
  51. package/src/constants/poolAddress.ts +344 -19
  52. package/src/constants/pyth.ts +2 -3
  53. package/src/constants/queryKeys.ts +9 -5
  54. package/src/constants/testAddress.ts +42 -0
  55. package/src/constants/tokenBucket.ts +2 -2
  56. package/src/index.ts +1 -0
  57. package/src/models/scallopBuilder.ts +59 -2
  58. package/src/models/scallopCache.ts +171 -19
  59. package/src/models/scallopClient.ts +16 -10
  60. package/src/models/scallopQuery.ts +36 -28
  61. package/src/models/scallopUtils.ts +11 -4
  62. package/src/queries/borrowIncentiveQuery.ts +6 -8
  63. package/src/queries/borrowLimitQuery.ts +3 -3
  64. package/src/queries/coreQuery.ts +408 -258
  65. package/src/queries/index.ts +2 -0
  66. package/src/queries/isolatedAssetQuery.ts +39 -34
  67. package/src/queries/objectsQuery.ts +20 -0
  68. package/src/queries/poolAddressesQuery.ts +146 -0
  69. package/src/queries/portfolioQuery.ts +31 -13
  70. package/src/queries/priceQuery.ts +3 -1
  71. package/src/queries/spoolQuery.ts +189 -122
  72. package/src/queries/supplyLimitQuery.ts +2 -3
  73. package/src/test.ts +14 -17
  74. package/src/types/builder/borrowIncentive.ts +8 -5
  75. package/src/types/builder/core.ts +23 -17
  76. package/src/types/builder/loyaltyProgram.ts +1 -1
  77. package/src/types/builder/referral.ts +6 -4
  78. package/src/types/builder/sCoin.ts +2 -2
  79. package/src/types/builder/spool.ts +4 -4
  80. package/src/types/builder/vesca.ts +9 -6
  81. package/src/types/query/core.ts +21 -5
  82. package/src/types/query/spool.ts +21 -0
  83. package/src/types/utils.ts +8 -3
  84. package/src/utils/core.ts +18 -0
  85. package/src/utils/index.ts +2 -0
  86. package/src/utils/query.ts +21 -5
  87. package/src/utils/tokenBucket.ts +9 -29
  88. package/src/utils/util.ts +8 -0
@@ -10,3 +10,5 @@ export * from './spoolQuery';
10
10
  export * from './supplyLimitQuery';
11
11
  export * from './vescaQuery';
12
12
  export * from './borrowLimitQuery';
13
+ export * from './poolAddressesQuery';
14
+ export * from './objectsQuery';
@@ -1,7 +1,8 @@
1
1
  import { DynamicFieldInfo, DynamicFieldName } from '@mysten/sui/client';
2
- import { ScallopAddress, ScallopUtils } from '../models';
2
+ import { ScallopQuery, ScallopUtils } from '../models';
3
3
  import { SupportPoolCoins } from '../types';
4
4
  import { z as zod } from 'zod';
5
+ import { POOL_ADDRESSES, SUPPORT_POOLS } from 'src/constants';
5
6
 
6
7
  const isolatedAssetZod = zod.object({
7
8
  dataType: zod.string(),
@@ -18,9 +19,8 @@ const isolatedAssetZod = zod.object({
18
19
  }),
19
20
  });
20
21
 
21
- // TODO: enable for production
22
- // const isolatedAssetKeyType = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da26c7221b220f01af6::market_dynamic_keys::IsolatedAssetKey`; // prod
23
- const isolatedAssetKeyType = `0x6c23585e940a989588432509107e98bae06dbca4e333f26d0635d401b3c7c76d::market_dynamic_keys::IsolatedAssetKey`;
22
+ const isolatedAssetKeyType = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da26c7221b220f01af6::market_dynamic_keys::IsolatedAssetKey`; // prod
23
+ // const isolatedAssetKeyType = `0x6c23585e940a989588432509107e98bae06dbca4e333f26d0635d401b3c7c76d::market_dynamic_keys::IsolatedAssetKey`;
24
24
 
25
25
  /**
26
26
  * Return list of isolated assets coin types
@@ -28,10 +28,16 @@ const isolatedAssetKeyType = `0x6c23585e940a989588432509107e98bae06dbca4e333f26d
28
28
  * @returns list of isolated assets coin types
29
29
  */
30
30
  export const getIsolatedAssets = async (
31
- address: ScallopAddress
31
+ query: ScallopQuery
32
32
  ): Promise<string[]> => {
33
+ if (SUPPORT_POOLS.every((t) => !!POOL_ADDRESSES[t])) {
34
+ return SUPPORT_POOLS.filter(
35
+ (t): t is typeof t & { coinType: string; isolatedAssetKey: string } =>
36
+ !!POOL_ADDRESSES[t]?.isolatedAssetKey && !!POOL_ADDRESSES[t]?.coinType
37
+ ).map((t) => POOL_ADDRESSES[t as SupportPoolCoins]?.coinType!);
38
+ }
33
39
  try {
34
- const marketObject = address.get('core.market');
40
+ const marketObject = query.address.get('core.market');
35
41
  const isolatedAssets: string[] = [];
36
42
  if (!marketObject) return isolatedAssets;
37
43
 
@@ -47,7 +53,7 @@ export const getIsolatedAssets = async (
47
53
  };
48
54
 
49
55
  do {
50
- const response = await address.cache.queryGetDynamicFields({
56
+ const response = await query.cache.queryGetDynamicFields({
51
57
  parentId: marketObject,
52
58
  cursor: nextCursor,
53
59
  limit: 10,
@@ -82,34 +88,33 @@ export const isIsolatedAsset = async (
82
88
  utils: ScallopUtils,
83
89
  coinName: SupportPoolCoins
84
90
  ): Promise<boolean> => {
85
- try {
86
- const marketObject = utils.address.get('core.market');
87
- // check if the coin type is in the list
88
- const cachedData = utils.address.cache.queryClient.getQueryData<string[]>([
89
- 'getDynamicFields',
90
- marketObject,
91
- ]);
92
- if (cachedData) {
93
- const coinType = utils.parseCoinType(coinName);
94
- return cachedData.includes(coinType);
95
- }
91
+ if (POOL_ADDRESSES[coinName]) {
92
+ return !!POOL_ADDRESSES[coinName].isolatedAssetKey;
93
+ }
94
+
95
+ const marketObject = utils.address.get('core.market');
96
+ // check if the coin type is in the list
97
+ const cachedData = utils.address.cache.queryClient.getQueryData<string[]>([
98
+ 'getDynamicFields',
99
+ marketObject,
100
+ ]);
101
+ if (cachedData) {
102
+ const coinType = utils.parseCoinType(coinName);
103
+ return cachedData.includes(coinType);
104
+ }
96
105
 
97
- // fetch dynamic field object
98
- const coinType = utils.parseCoinType(coinName).slice(2);
106
+ // fetch dynamic field object
107
+ const coinType = utils.parseCoinType(coinName).slice(2);
99
108
 
100
- const object = await utils.cache.queryGetDynamicFieldObject({
101
- parentId: marketObject,
102
- name: {
103
- type: isolatedAssetKeyType,
104
- value: coinType,
105
- },
106
- });
109
+ const object = await utils.cache.queryGetDynamicFieldObject({
110
+ parentId: marketObject,
111
+ name: {
112
+ type: isolatedAssetKeyType,
113
+ value: coinType,
114
+ },
115
+ });
107
116
 
108
- const parsedData = isolatedAssetZod.safeParse(object?.data?.content);
109
- if (!parsedData.success) return false;
110
- return parsedData.data.fields.value;
111
- } catch (e) {
112
- console.error(e);
113
- return false;
114
- }
117
+ const parsedData = isolatedAssetZod.safeParse(object?.data?.content);
118
+ if (!parsedData.success) return false;
119
+ return parsedData.data.fields.value;
115
120
  };
@@ -0,0 +1,20 @@
1
+ import { SuiObjectDataOptions } from '@mysten/sui/dist/cjs/client';
2
+ import { ScallopCache } from 'src/models/scallopCache';
3
+ import { partitionArray } from 'src/utils';
4
+
5
+ export const queryMultipleObjects = async (
6
+ cache: ScallopCache,
7
+ objectIds: string[],
8
+ options?: SuiObjectDataOptions,
9
+ partitionSize = 50
10
+ ) => {
11
+ const objectIdsPartition = partitionArray(objectIds, partitionSize);
12
+
13
+ const objects = [];
14
+ for (const objectIds of objectIdsPartition) {
15
+ const result = await cache.queryGetObjects(objectIds, options);
16
+ objects.push(...result);
17
+ }
18
+
19
+ return objects;
20
+ };
@@ -0,0 +1,146 @@
1
+ import { SUPPORT_POOLS } from 'src/constants';
2
+ import { ScallopQuery } from 'src/models';
3
+ import { OptionalKeys, SupportPoolCoins } from 'src/types';
4
+
5
+ export const getAllAddresses = async (query: ScallopQuery) => {
6
+ const results: OptionalKeys<
7
+ Record<
8
+ SupportPoolCoins,
9
+ {
10
+ lendingPoolAddress?: string;
11
+ collateralPoolAddress?: string; // not all pool has collateral
12
+ borrowDynamic?: string;
13
+ spoolReward?: string;
14
+ spool?: string;
15
+ sCoinTreasury?: string;
16
+ interestModel?: string;
17
+ riskModel?: string;
18
+ borrowFeeKey?: string;
19
+ supplyLimitKey?: string;
20
+ borrowLimitKey?: string;
21
+ isolatedAssetKey?: string;
22
+ coinDecimalId?: string;
23
+ borrowIncentivePoolId?: string;
24
+ }
25
+ >
26
+ > = {};
27
+
28
+ const marketId = query.address.get('core.market');
29
+ const marketObject = (
30
+ await query.cache.queryGetObject(marketId, {
31
+ showContent: true,
32
+ })
33
+ )?.data;
34
+
35
+ if (!(marketObject && marketObject.content?.dataType === 'moveObject'))
36
+ throw new Error(`Failed to fetch marketObject`);
37
+
38
+ const fields = marketObject.content.fields as any;
39
+
40
+ const coinTypesPairs = SUPPORT_POOLS.reduce(
41
+ (acc, pool) => {
42
+ acc.push([pool, query.utils.parseCoinType(pool).substring(2)]);
43
+ return acc;
44
+ },
45
+ [] as [SupportPoolCoins, string][]
46
+ );
47
+ const balanceSheetParentId =
48
+ fields.vault.fields.balance_sheets.fields.table.fields.id.id;
49
+
50
+ const collateralStatsParentId =
51
+ fields.collateral_stats.fields.table.fields.id.id;
52
+
53
+ const borrowDynamicsParentid =
54
+ fields.borrow_dynamics.fields.table.fields.id.id;
55
+
56
+ const interestModelParentId =
57
+ fields.interest_models.fields.table.fields.id.id;
58
+
59
+ const riskModelParentId = fields.risk_models.fields.table.fields.id.id;
60
+
61
+ const ADDRESS_TYPE = `0x1::type_name::TypeName`;
62
+ const BORROW_FEE_TYPE = `0xc38f849e81cfe46d4e4320f508ea7dda42934a329d5a6571bb4c3cb6ea63f5da::market_dynamic_keys::BorrowFeeKey`;
63
+ const SUPPLY_LIMIT_TYPE = `0x6e641f0dca8aedab3101d047e96439178f16301bf0b57fe8745086ff1195eb3e::market_dynamic_keys::SupplyLimitKey`;
64
+ const BORROW_LIMIT_TYPE = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da26c7221b220f01af6::market_dynamic_keys::BorrowLimitKey`; // prod
65
+ const ISOLATED_ASSET_KEY = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da26c7221b220f01af6::market_dynamic_keys::IsolatedAssetKey`;
66
+ const fetchDynamicObject = async (
67
+ parentId: string,
68
+ type: string,
69
+ value: any
70
+ ) => {
71
+ try {
72
+ return (
73
+ await query.cache.queryGetDynamicFieldObject({
74
+ parentId,
75
+ name: {
76
+ type,
77
+ value,
78
+ },
79
+ })
80
+ )?.data?.objectId;
81
+ } catch (_e) {
82
+ return undefined;
83
+ }
84
+ };
85
+
86
+ await Promise.all(
87
+ coinTypesPairs.map(async ([coinName, coinType]) => {
88
+ const addresses = await Promise.all([
89
+ fetchDynamicObject(balanceSheetParentId, ADDRESS_TYPE, {
90
+ name: coinType,
91
+ }),
92
+ fetchDynamicObject(collateralStatsParentId, ADDRESS_TYPE, {
93
+ name: coinType,
94
+ }),
95
+ fetchDynamicObject(borrowDynamicsParentid, ADDRESS_TYPE, {
96
+ name: coinType,
97
+ }),
98
+ fetchDynamicObject(interestModelParentId, ADDRESS_TYPE, {
99
+ name: coinType,
100
+ }),
101
+ fetchDynamicObject(riskModelParentId, ADDRESS_TYPE, {
102
+ name: coinType,
103
+ }),
104
+ fetchDynamicObject(marketId, BORROW_FEE_TYPE, coinType),
105
+ fetchDynamicObject(marketId, SUPPLY_LIMIT_TYPE, coinType),
106
+ fetchDynamicObject(marketId, BORROW_LIMIT_TYPE, coinType),
107
+ fetchDynamicObject(marketId, ISOLATED_ASSET_KEY, coinType),
108
+ ]);
109
+
110
+ const spool = query.address.get(
111
+ // @ts-ignore
112
+ `spool.pools.s${coinName}.id`
113
+ );
114
+ const rewardPool = query.address.get(
115
+ // @ts-ignore
116
+ `spool.pools.s${coinName}.rewardPoolId`
117
+ );
118
+ const sCoinTreasury = query.address.get(
119
+ // @ts-ignore
120
+ `scoin.coins.s${coinName}.treasury`
121
+ );
122
+ const coinDecimalId = query.address.get(
123
+ `core.coins.${coinName}.metaData`
124
+ );
125
+ results[coinName as SupportPoolCoins] = {
126
+ lendingPoolAddress: addresses[0],
127
+ collateralPoolAddress: addresses[1],
128
+ borrowDynamic: addresses[2],
129
+ interestModel: addresses[3],
130
+ riskModel: addresses[4],
131
+ borrowFeeKey: addresses[5],
132
+ supplyLimitKey: addresses[6],
133
+ borrowLimitKey: addresses[7],
134
+ isolatedAssetKey: addresses[8],
135
+ spool,
136
+ spoolReward: rewardPool,
137
+ sCoinTreasury,
138
+ coinDecimalId,
139
+ };
140
+
141
+ await new Promise((resolve) => setTimeout(resolve, 200));
142
+ })
143
+ );
144
+
145
+ return results;
146
+ };
@@ -25,6 +25,7 @@ import type {
25
25
  SupportBorrowIncentiveCoins,
26
26
  ObligationBorrowIcentiveReward,
27
27
  SupportBorrowIncentiveRewardCoins,
28
+ SupportAssetCoins,
28
29
  } from '../types';
29
30
 
30
31
  /**
@@ -50,10 +51,13 @@ export const getLendings = async (
50
51
  ) as SupportStakeMarketCoins[];
51
52
 
52
53
  const coinPrices = await query.utils.getCoinPrices();
53
- const marketPools = await query.getMarketPools(poolCoinNames, {
54
- indexer,
55
- coinPrices,
56
- });
54
+ const marketPools = (
55
+ await query.getMarketPools(poolCoinNames, {
56
+ indexer,
57
+ coinPrices,
58
+ })
59
+ ).pools;
60
+
57
61
  const spools = await query.getSpools(stakeMarketCoinNames, {
58
62
  indexer,
59
63
  marketPools,
@@ -307,8 +311,10 @@ export const getObligationAccounts = async (
307
311
  ownerAddress?: string,
308
312
  indexer: boolean = false
309
313
  ) => {
310
- const coinPrices = await query.utils.getCoinPrices();
311
- const market = await query.queryMarket({ indexer, coinPrices });
314
+ const market = await query.queryMarket({ indexer });
315
+ const coinPrices = await query.getAllCoinPrices({
316
+ marketPools: market.pools,
317
+ });
312
318
  const [coinAmounts, obligations] = await Promise.all([
313
319
  query.getCoinAmounts(undefined, ownerAddress),
314
320
  query.getObligations(ownerAddress),
@@ -349,15 +355,19 @@ export const getObligationAccount = async (
349
355
  coinPrices?: CoinPrices,
350
356
  coinAmounts?: CoinAmounts
351
357
  ) => {
352
- const collateralAssetCoinNames: SupportCollateralCoins[] = [
358
+ const coinNames: SupportAssetCoins[] = Array.from(
359
+ new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
360
+ );
361
+ const collateralAssetCoinNames = [
353
362
  ...SUPPORT_COLLATERALS,
354
- ];
355
- market = market ?? (await query.queryMarket({ indexer }));
363
+ ] as SupportCollateralCoins[];
364
+
365
+ // market = market ?? (await query.queryMarket({ indexer }));
366
+ market = market ?? (await query.getMarketPools(undefined, { indexer }));
356
367
  coinPrices =
357
368
  coinPrices ?? (await query.getAllCoinPrices({ marketPools: market.pools }));
358
369
  coinAmounts =
359
- coinAmounts ||
360
- (await query.getCoinAmounts(collateralAssetCoinNames, ownerAddress));
370
+ coinAmounts ?? (await query.getCoinAmounts(coinNames, ownerAddress));
361
371
 
362
372
  const [obligationQuery, borrowIncentivePools, borrowIncentiveAccounts] =
363
373
  await Promise.all([
@@ -365,6 +375,7 @@ export const getObligationAccount = async (
365
375
  query.getBorrowIncentivePools(undefined, {
366
376
  coinPrices,
367
377
  indexer,
378
+ marketPools: market.pools,
368
379
  }),
369
380
  query.getBorrowIncentiveAccounts(obligationId),
370
381
  ]);
@@ -527,7 +538,7 @@ export const getObligationAccount = async (
527
538
  ([key, accountPoint]) => {
528
539
  const poolPoint =
529
540
  borrowIncentivePool.points[
530
- key as SupportBorrowIncentiveRewardCoins
541
+ query.utils.parseSCoinTypeNameToMarketCoinName(key)
531
542
  ];
532
543
 
533
544
  if (accountPoint && poolPoint) {
@@ -572,6 +583,11 @@ export const getObligationAccount = async (
572
583
  .toNumber()
573
584
  : 1;
574
585
 
586
+ // console.log({
587
+ // availableClaimAmount: availableClaimAmount.toString(),
588
+ // coinName: poolPoint.coinName,
589
+ // coinType: poolPoint.coinType,
590
+ // });
575
591
  if (availableClaimAmount.isGreaterThanOrEqualTo(0)) {
576
592
  rewards.push({
577
593
  coinName: poolPoint.coinName,
@@ -774,7 +790,8 @@ export const getTotalValueLocked = async (
774
790
  query: ScallopQuery,
775
791
  indexer: boolean = false
776
792
  ) => {
777
- const market = await query.queryMarket({ indexer });
793
+ // const market = await query.queryMarket({ indexer });
794
+ const market = await query.getMarketPools(undefined, { indexer });
778
795
 
779
796
  let supplyValue = BigNumber(0);
780
797
  let borrowValue = BigNumber(0);
@@ -801,6 +818,7 @@ export const getTotalValueLocked = async (
801
818
  );
802
819
  }
803
820
 
821
+ // console.dir(market.collaterals, { depth: null });
804
822
  for (const collateral of Object.values(market.collaterals)) {
805
823
  supplyValue = supplyValue.plus(
806
824
  BigNumber(collateral.depositCoin).multipliedBy(collateral.coinPrice)
@@ -142,7 +142,9 @@ export const getAllCoinPrices = async (
142
142
  ) => {
143
143
  coinPrices = coinPrices ?? (await query.utils.getCoinPrices());
144
144
  marketPools =
145
- marketPools ?? (await query.getMarketPools(undefined, { coinPrices }));
145
+ marketPools ??
146
+ (await query.getMarketPools(undefined, { coinPrices })).pools;
147
+
146
148
  if (!marketPools) {
147
149
  throw new Error(`Failed to fetch market pool for getAllCoinPrices`);
148
150
  }