@scallop-io/sui-scallop-sdk 1.4.14-alpha.1 → 1.4.15-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 (43) hide show
  1. package/dist/constants/poolAddress.d.ts +14 -4
  2. package/dist/constants/queryKeys.d.ts +1 -2
  3. package/dist/constants/tokenBucket.d.ts +1 -1
  4. package/dist/index.js +714 -316
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +669 -271
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/models/scallopQuery.d.ts +20 -17
  9. package/dist/queries/coreQuery.d.ts +18 -19
  10. package/dist/queries/index.d.ts +2 -0
  11. package/dist/queries/isolatedAssetQuery.d.ts +2 -2
  12. package/dist/queries/objectsQuery.d.ts +3 -0
  13. package/dist/queries/poolAddressesQuery.d.ts +15 -0
  14. package/dist/types/query/core.d.ts +22 -5
  15. package/dist/types/utils.d.ts +7 -2
  16. package/dist/utils/core.d.ts +2 -0
  17. package/dist/utils/index.d.ts +1 -0
  18. package/dist/utils/util.d.ts +1 -0
  19. package/package.json +1 -1
  20. package/src/constants/enum.ts +6 -14
  21. package/src/constants/poolAddress.ts +290 -29
  22. package/src/constants/queryKeys.ts +5 -5
  23. package/src/constants/tokenBucket.ts +1 -1
  24. package/src/models/scallopCache.ts +34 -7
  25. package/src/models/scallopQuery.ts +24 -12
  26. package/src/queries/borrowIncentiveQuery.ts +1 -1
  27. package/src/queries/borrowLimitQuery.ts +2 -2
  28. package/src/queries/coreQuery.ts +378 -248
  29. package/src/queries/index.ts +2 -0
  30. package/src/queries/isolatedAssetQuery.ts +39 -33
  31. package/src/queries/objectsQuery.ts +20 -0
  32. package/src/queries/poolAddressesQuery.ts +134 -0
  33. package/src/queries/portfolioQuery.ts +14 -7
  34. package/src/queries/priceQuery.ts +3 -1
  35. package/src/queries/spoolQuery.ts +3 -1
  36. package/src/queries/supplyLimitQuery.ts +2 -2
  37. package/src/types/query/core.ts +21 -5
  38. package/src/types/utils.ts +8 -3
  39. package/src/utils/core.ts +11 -0
  40. package/src/utils/index.ts +1 -0
  41. package/src/utils/query.ts +16 -2
  42. package/src/utils/tokenBucket.ts +1 -1
  43. package/src/utils/util.ts +8 -0
@@ -3,14 +3,15 @@ import {
3
3
  SUPPORT_POOLS,
4
4
  PROTOCOL_OBJECT_ID,
5
5
  SUPPORT_COLLATERALS,
6
- BORROW_FEE_PROTOCOL_ID,
7
6
  FlashLoanFeeObjectMap,
7
+ POOL_ADDRESSES,
8
8
  } from '../constants';
9
9
  import {
10
10
  parseOriginMarketPoolData,
11
11
  calculateMarketPoolData,
12
12
  parseOriginMarketCollateralData,
13
13
  calculateMarketCollateralData,
14
+ parseObjectAs,
14
15
  } from '../utils';
15
16
  import type { SuiObjectResponse, SuiObjectData } from '@mysten/sui/client';
16
17
  import type { SuiObjectArg } from '@scallop-io/sui-kit';
@@ -28,22 +29,28 @@ import {
28
29
  ObligationQueryInterface,
29
30
  Obligation,
30
31
  InterestModel,
31
- BorrowIndex,
32
32
  BalanceSheet,
33
33
  RiskModel,
34
34
  CollateralStat,
35
35
  SupportMarketCoins,
36
36
  OptionalKeys,
37
37
  CoinPrices,
38
+ OriginMarketPoolData,
39
+ BorrowFee,
40
+ BorrowDynamic,
41
+ OriginMarketCollateralData,
38
42
  } from '../types';
39
43
  import BigNumber from 'bignumber.js';
40
44
  import { getSupplyLimit } from './supplyLimitQuery';
41
45
  import { isIsolatedAsset } from './isolatedAssetQuery';
42
46
  import { getBorrowLimit } from './borrowLimitQuery';
47
+ import { queryMultipleObjects } from './objectsQuery';
43
48
 
44
49
  /**
45
50
  * Query market data.
46
51
  *
52
+ * @deprecated Use query market pools
53
+ *
47
54
  * @description
48
55
  * Use inspectTxn call to obtain the data provided in the scallop contract query module.
49
56
  *
@@ -126,6 +133,9 @@ export const queryMarket = async (
126
133
  highKink: pool.highKink,
127
134
  midKink: pool.midKink,
128
135
  minBorrowAmount: pool.minBorrowAmount,
136
+ isIsolated: await isIsolatedAsset(query.utils, poolCoinName),
137
+ supplyLimit: (await getSupplyLimit(query.utils, poolCoinName)) ?? '0',
138
+ borrowLimit: (await getBorrowLimit(query.utils, poolCoinName)) ?? '0',
129
139
  });
130
140
 
131
141
  const calculatedMarketPoolData = calculateMarketPoolData(
@@ -133,19 +143,6 @@ export const queryMarket = async (
133
143
  parsedMarketPoolData
134
144
  );
135
145
 
136
- const coinDecimal = query.utils.getCoinDecimal(poolCoinName);
137
- const maxSupplyCoin = BigNumber(
138
- (await getSupplyLimit(query.utils, poolCoinName)) ?? '0'
139
- )
140
- .shiftedBy(-coinDecimal)
141
- .toNumber();
142
-
143
- const maxBorrowCoin = BigNumber(
144
- (await getBorrowLimit(query.utils, poolCoinName)) ?? '0'
145
- )
146
- .shiftedBy(-coinDecimal)
147
- .toNumber();
148
-
149
146
  pools[poolCoinName] = {
150
147
  coinName: poolCoinName,
151
148
  symbol: query.utils.parseSymbol(poolCoinName),
@@ -155,7 +152,6 @@ export const queryMarket = async (
155
152
  query.utils.parseMarketCoinName(poolCoinName)
156
153
  ),
157
154
  coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
158
- coinDecimal,
159
155
  coinPrice: coinPrice,
160
156
  highKink: parsedMarketPoolData.highKink,
161
157
  midKink: parsedMarketPoolData.midKink,
@@ -164,10 +160,6 @@ export const queryMarket = async (
164
160
  borrowFee: parsedMarketPoolData.borrowFee,
165
161
  marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
166
162
  minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
167
- isIsolated: await isIsolatedAsset(query.utils, poolCoinName),
168
- // isIsolated: false,
169
- maxSupplyCoin,
170
- maxBorrowCoin,
171
163
  ...calculatedMarketPoolData,
172
164
  };
173
165
  }
@@ -188,10 +180,11 @@ export const queryMarket = async (
188
180
  collateralFactor: collateral.collateralFactor,
189
181
  liquidationFactor: collateral.liquidationFactor,
190
182
  liquidationDiscount: collateral.liquidationDiscount,
191
- liquidationPanelty: collateral.liquidationPanelty,
183
+ liquidationPenalty: collateral.liquidationPanelty,
192
184
  liquidationReserveFactor: collateral.liquidationReserveFactor,
193
185
  maxCollateralAmount: collateral.maxCollateralAmount,
194
186
  totalCollateralAmount: collateral.totalCollateralAmount,
187
+ isIsolated: await isIsolatedAsset(query.utils, collateralCoinName),
195
188
  });
196
189
 
197
190
  const calculatedMarketCollateralData = calculateMarketCollateralData(
@@ -205,15 +198,14 @@ export const queryMarket = async (
205
198
  coinType: coinType,
206
199
  marketCoinType: query.utils.parseMarketCoinType(collateralCoinName),
207
200
  coinWrappedType: query.utils.getCoinWrappedType(collateralCoinName),
208
- coinDecimal: query.utils.getCoinDecimal(collateralCoinName),
209
201
  coinPrice: coinPrice,
210
202
  collateralFactor: parsedMarketCollateralData.collateralFactor,
211
203
  liquidationFactor: parsedMarketCollateralData.liquidationFactor,
212
204
  liquidationDiscount: parsedMarketCollateralData.liquidationDiscount,
213
- liquidationPanelty: parsedMarketCollateralData.liquidationPanelty,
205
+ liquidationPenalty: parsedMarketCollateralData.liquidationPenalty,
214
206
  liquidationReserveFactor:
215
207
  parsedMarketCollateralData.liquidationReserveFactor,
216
- isIsolated: await isIsolatedAsset(query.utils, collateralCoinName),
208
+
217
209
  ...calculatedMarketCollateralData,
218
210
  };
219
211
  }
@@ -225,6 +217,135 @@ export const queryMarket = async (
225
217
  } as Market;
226
218
  };
227
219
 
220
+ const queryRequiredMarketObjects = async (
221
+ query: ScallopQuery,
222
+ poolCoinNames: SupportPoolCoins[]
223
+ ) => {
224
+ // Prepare all tasks for querying each object type
225
+ const tasks = poolCoinNames.map((t) => ({
226
+ poolCoinName: t,
227
+ balanceSheet: POOL_ADDRESSES[t]?.lendingPoolAddress,
228
+ collateralStat: POOL_ADDRESSES[t]?.collateralPoolAddress,
229
+ borrowDynamic: POOL_ADDRESSES[t]?.borrowDynamic,
230
+ interestModel: POOL_ADDRESSES[t]?.interestModel,
231
+ riskModel: POOL_ADDRESSES[t]?.riskModel,
232
+ borrowFeeKey: POOL_ADDRESSES[t]?.borrowFeeKey,
233
+ supplyLimitKey: POOL_ADDRESSES[t]?.supplyLimitKey,
234
+ borrowLimitKey: POOL_ADDRESSES[t]?.borrowLimitKey,
235
+ isolatedAssetKey: POOL_ADDRESSES[t]?.isolatedAssetKey,
236
+ }));
237
+
238
+ // Query all objects for each key in parallel
239
+ const [
240
+ balanceSheetObjects,
241
+ collateralStatObjects,
242
+ borrowDynamicObjects,
243
+ interestModelObjects,
244
+ riskModelObjects,
245
+ borrowFeeObjects,
246
+ supplyLimitObjects,
247
+ borrowLimitObjects,
248
+ isolatedAssetObjects,
249
+ ] = await Promise.all([
250
+ queryMultipleObjects(
251
+ query.cache,
252
+ tasks.map((task) => task.balanceSheet).filter((t): t is string => !!t)
253
+ ),
254
+ queryMultipleObjects(
255
+ query.cache,
256
+ tasks.map((task) => task.collateralStat).filter((t): t is string => !!t)
257
+ ),
258
+ queryMultipleObjects(
259
+ query.cache,
260
+ tasks.map((task) => task.borrowDynamic).filter((t): t is string => !!t)
261
+ ),
262
+ queryMultipleObjects(
263
+ query.cache,
264
+ tasks.map((task) => task.interestModel).filter((t): t is string => !!t)
265
+ ),
266
+ queryMultipleObjects(
267
+ query.cache,
268
+ tasks.map((task) => task.riskModel).filter((t): t is string => !!t)
269
+ ),
270
+ queryMultipleObjects(
271
+ query.cache,
272
+ tasks.map((task) => task.borrowFeeKey).filter((t): t is string => !!t)
273
+ ),
274
+ queryMultipleObjects(
275
+ query.cache,
276
+ tasks.map((task) => task.supplyLimitKey).filter((t): t is string => !!t)
277
+ ),
278
+ queryMultipleObjects(
279
+ query.cache,
280
+ tasks.map((task) => task.borrowLimitKey).filter((t): t is string => !!t)
281
+ ),
282
+ queryMultipleObjects(
283
+ query.cache,
284
+ tasks.map((task) => task.isolatedAssetKey).filter((t): t is string => !!t)
285
+ ),
286
+ ]);
287
+
288
+ // Map the results back to poolCoinNames
289
+ const mapObjects = (
290
+ tasks: { poolCoinName: string; [key: string]: string | undefined }[],
291
+ fetchedObjects: SuiObjectData[]
292
+ ) => {
293
+ const resultMap: Record<string, SuiObjectData> = {};
294
+ let fetchedIndex = 0;
295
+
296
+ for (const task of tasks) {
297
+ const key = task[Object.keys(task)[1]]; // current object key being queried
298
+ if (key) {
299
+ resultMap[task.poolCoinName] = fetchedObjects[fetchedIndex];
300
+ fetchedIndex++;
301
+ }
302
+ }
303
+ return resultMap;
304
+ };
305
+
306
+ const balanceSheetMap = mapObjects(tasks, balanceSheetObjects);
307
+ const collateralStatMap = mapObjects(tasks, collateralStatObjects);
308
+ const borrowDynamicMap = mapObjects(tasks, borrowDynamicObjects);
309
+ const interestModelMap = mapObjects(tasks, interestModelObjects);
310
+ const riskModelMap = mapObjects(tasks, riskModelObjects);
311
+ const borrowFeeMap = mapObjects(tasks, borrowFeeObjects);
312
+ const supplyLimitMap = mapObjects(tasks, supplyLimitObjects);
313
+ const borrowLimitMap = mapObjects(tasks, borrowLimitObjects);
314
+ const isolatedAssetMap = mapObjects(tasks, isolatedAssetObjects);
315
+
316
+ // Construct the final requiredObjects result
317
+ return poolCoinNames.reduce(
318
+ (acc, name) => {
319
+ acc[name] = {
320
+ balanceSheet: balanceSheetMap[name],
321
+ collateralStat: collateralStatMap[name],
322
+ borrowDynamic: borrowDynamicMap[name],
323
+ interestModel: interestModelMap[name],
324
+ riskModel: riskModelMap[name],
325
+ borrowFeeKey: borrowFeeMap[name],
326
+ supplyLimitKey: supplyLimitMap[name],
327
+ borrowLimitKey: borrowLimitMap[name],
328
+ isolatedAssetKey: isolatedAssetMap[name],
329
+ };
330
+ return acc;
331
+ },
332
+ {} as Record<
333
+ SupportPoolCoins,
334
+ {
335
+ balanceSheet: SuiObjectData;
336
+ collateralStat?: SuiObjectData;
337
+ riskModel?: SuiObjectData;
338
+ borrowDynamic: SuiObjectData;
339
+ interestModel: SuiObjectData;
340
+ borrowFeeKey: SuiObjectData;
341
+ supplyLimitKey: SuiObjectData;
342
+ borrowLimitKey: SuiObjectData;
343
+ isolatedAssetKey: SuiObjectData;
344
+ }
345
+ >
346
+ );
347
+ };
348
+
228
349
  /**
229
350
  * Get coin market pools data.
230
351
  *
@@ -239,53 +360,172 @@ export const queryMarket = async (
239
360
  */
240
361
  export const getMarketPools = async (
241
362
  query: ScallopQuery,
242
- poolCoinNames: SupportPoolCoins[] = [...SUPPORT_POOLS],
363
+ poolCoinNames: SupportPoolCoins[],
243
364
  indexer: boolean = false,
244
365
  coinPrices?: CoinPrices
245
- ) => {
246
- const marketId = query.address.get('core.market');
247
- const marketObjectResponse = await query.cache.queryGetObject(marketId, {
248
- showContent: true,
249
- });
366
+ ): Promise<{
367
+ pools: MarketPools;
368
+ collaterals: MarketCollaterals;
369
+ }> => {
250
370
  coinPrices = coinPrices ?? (await query.utils.getCoinPrices());
251
371
 
252
- const marketPools: MarketPools = {};
372
+ const pools: MarketPools = {};
373
+ const collaterals: MarketCollaterals = {};
253
374
 
254
375
  if (indexer) {
255
- const marketPoolsIndexer = await query.indexer.getMarketPools();
256
-
257
- const updateMarketPool = (marketPool: MarketPool) => {
258
- if (!poolCoinNames.includes(marketPool.coinName)) return;
259
- marketPool.coinPrice =
260
- coinPrices[marketPool.coinName] ?? marketPool.coinPrice;
261
- marketPool.coinWrappedType = query.utils.getCoinWrappedType(
262
- marketPool.coinName
263
- );
264
- marketPools[marketPool.coinName] = marketPool;
376
+ // const marketPoolsIndexer = await query.indexer.getMarketPools();
377
+
378
+ // const updateMarketPool = (marketPool: MarketPool) => {
379
+ // if (!poolCoinNames.includes(marketPool.coinName)) return;
380
+ // marketPool.coinPrice =
381
+ // coinPrices[marketPool.coinName] ?? marketPool.coinPrice;
382
+ // marketPool.coinWrappedType = query.utils.getCoinWrappedType(
383
+ // marketPool.coinName
384
+ // );
385
+ // pools[marketPool.coinName] = marketPool;
386
+ // };
387
+
388
+ // Object.values(marketPoolsIndexer).forEach(updateMarketPool);
389
+
390
+ // return pools;
391
+ const marketIndexer = await query.indexer.getMarket();
392
+
393
+ const updatePools = (item: MarketPool) => {
394
+ item.coinPrice = coinPrices[item.coinName] ?? item.coinPrice;
395
+ item.coinWrappedType = query.utils.getCoinWrappedType(item.coinName);
396
+ pools[item.coinName] = item;
265
397
  };
266
398
 
267
- Object.values(marketPoolsIndexer).forEach(updateMarketPool);
399
+ const updateCollaterals = (item: MarketCollateral) => {
400
+ item.coinPrice = coinPrices[item.coinName] ?? item.coinPrice;
401
+ item.coinWrappedType = query.utils.getCoinWrappedType(item.coinName);
402
+ collaterals[item.coinName] = item;
403
+ };
404
+
405
+ Object.values(marketIndexer.pools).forEach(updatePools);
406
+ Object.values(marketIndexer.collaterals).forEach(updateCollaterals);
268
407
 
269
- return marketPools;
408
+ return {
409
+ pools,
410
+ collaterals,
411
+ };
270
412
  }
271
413
 
414
+ const requiredObjects = await queryRequiredMarketObjects(
415
+ query,
416
+ poolCoinNames
417
+ );
418
+
272
419
  await Promise.allSettled(
273
420
  poolCoinNames.map(async (poolCoinName) => {
274
- const marketPool = await getMarketPool(
275
- query,
276
- poolCoinName,
277
- indexer,
278
- marketObjectResponse?.data,
279
- coinPrices?.[poolCoinName]
280
- );
281
-
282
- if (marketPool) {
283
- marketPools[poolCoinName] = marketPool;
421
+ try {
422
+ const result = await getMarketPool(
423
+ query,
424
+ poolCoinName,
425
+ indexer,
426
+ coinPrices?.[poolCoinName] ?? 0,
427
+ requiredObjects[poolCoinName]
428
+ );
429
+ if (result?.marketPool) {
430
+ pools[poolCoinName] = result?.marketPool;
431
+ }
432
+ if (result?.collateral) {
433
+ collaterals[poolCoinName as SupportCollateralCoins] =
434
+ result.collateral;
435
+ }
436
+ } catch (e) {
437
+ console.error(e);
284
438
  }
285
439
  })
286
440
  );
287
441
 
288
- return marketPools;
442
+ return {
443
+ pools,
444
+ collaterals,
445
+ };
446
+ };
447
+
448
+ const parseMarketPoolObjects = ({
449
+ balanceSheet,
450
+ borrowDynamic,
451
+ collateralStat,
452
+ interestModel,
453
+ riskModel,
454
+ borrowFeeKey,
455
+ supplyLimitKey,
456
+ borrowLimitKey,
457
+ isolatedAssetKey,
458
+ }: {
459
+ balanceSheet: SuiObjectData;
460
+ borrowDynamic: SuiObjectData;
461
+ collateralStat?: SuiObjectData;
462
+ interestModel: SuiObjectData;
463
+ riskModel?: SuiObjectData;
464
+ borrowFeeKey: SuiObjectData;
465
+ supplyLimitKey?: SuiObjectData;
466
+ borrowLimitKey?: SuiObjectData;
467
+ isolatedAssetKey: SuiObjectData;
468
+ }): OriginMarketPoolData & {
469
+ parsedOriginMarketCollateral?: OriginMarketCollateralData;
470
+ } => {
471
+ const _balanceSheet = parseObjectAs<BalanceSheet>(balanceSheet);
472
+ const _interestModel = parseObjectAs<InterestModel>(interestModel);
473
+ const _borrowDynamic = parseObjectAs<BorrowDynamic>(borrowDynamic);
474
+ const _borrowFee = parseObjectAs<BorrowFee>(borrowFeeKey);
475
+ const _supplyLimit = supplyLimitKey
476
+ ? parseObjectAs<string>(supplyLimitKey)
477
+ : '0';
478
+ const _borrowLimit = borrowLimitKey
479
+ ? parseObjectAs<string>(borrowLimitKey)
480
+ : '0';
481
+ const _riskModel = riskModel
482
+ ? parseObjectAs<RiskModel>(riskModel)
483
+ : undefined;
484
+ const _collateralStat = collateralStat
485
+ ? parseObjectAs<CollateralStat>(collateralStat)
486
+ : undefined;
487
+
488
+ const parsedOriginMarketCollateral =
489
+ _riskModel && _collateralStat
490
+ ? {
491
+ type: _interestModel.type.fields,
492
+ isIsolated: !!isolatedAssetKey,
493
+ collateralFactor: _riskModel.collateral_factor.fields,
494
+ liquidationFactor: _riskModel.liquidation_factor.fields,
495
+ liquidationPenalty: _riskModel.liquidation_penalty.fields,
496
+ liquidationDiscount: _riskModel.liquidation_discount.fields,
497
+ liquidationReserveFactor:
498
+ _riskModel.liquidation_revenue_factor.fields,
499
+ maxCollateralAmount: _riskModel.max_collateral_amount,
500
+ totalCollateralAmount: _collateralStat.amount,
501
+ }
502
+ : undefined;
503
+
504
+ return {
505
+ type: _interestModel.type.fields,
506
+ maxBorrowRate: _interestModel.max_borrow_rate.fields,
507
+ interestRate: _borrowDynamic.interest_rate.fields,
508
+ interestRateScale: _borrowDynamic.interest_rate_scale,
509
+ borrowIndex: _borrowDynamic.borrow_index,
510
+ lastUpdated: _borrowDynamic.last_updated,
511
+ cash: _balanceSheet.cash,
512
+ debt: _balanceSheet.debt,
513
+ marketCoinSupply: _balanceSheet.market_coin_supply,
514
+ reserve: _balanceSheet.revenue,
515
+ reserveFactor: _interestModel.revenue_factor.fields,
516
+ borrowWeight: _interestModel.borrow_weight.fields,
517
+ borrowFeeRate: _borrowFee,
518
+ baseBorrowRatePerSec: _interestModel.base_borrow_rate_per_sec.fields,
519
+ borrowRateOnHighKink: _interestModel.borrow_rate_on_high_kink.fields,
520
+ borrowRateOnMidKink: _interestModel.borrow_rate_on_mid_kink.fields,
521
+ highKink: _interestModel.high_kink.fields,
522
+ midKink: _interestModel.mid_kink.fields,
523
+ minBorrowAmount: _interestModel.min_borrow_amount,
524
+ isIsolated: !!isolatedAssetKey,
525
+ supplyLimit: _supplyLimit,
526
+ borrowLimit: _borrowLimit,
527
+ parsedOriginMarketCollateral,
528
+ };
289
529
  };
290
530
 
291
531
  /**
@@ -302,9 +542,19 @@ export const getMarketPool = async (
302
542
  query: ScallopQuery,
303
543
  poolCoinName: SupportPoolCoins,
304
544
  indexer: boolean = false,
305
- marketObject?: SuiObjectData | null,
306
- coinPrice?: number
307
- ): Promise<MarketPool | undefined> => {
545
+ coinPrice: number,
546
+ requiredObjects?: {
547
+ balanceSheet: SuiObjectData;
548
+ borrowDynamic: SuiObjectData;
549
+ interestModel: SuiObjectData;
550
+ borrowFeeKey: SuiObjectData;
551
+ supplyLimitKey: SuiObjectData;
552
+ borrowLimitKey: SuiObjectData;
553
+ isolatedAssetKey: SuiObjectData;
554
+ }
555
+ ): Promise<
556
+ { marketPool: MarketPool; collateral?: MarketCollateral } | undefined
557
+ > => {
308
558
  coinPrice = coinPrice ?? (await query.utils.getCoinPrices())?.[poolCoinName];
309
559
 
310
560
  if (indexer) {
@@ -317,202 +567,83 @@ export const getMarketPool = async (
317
567
  marketPoolIndexer.coinName
318
568
  );
319
569
 
320
- return marketPoolIndexer;
321
- }
322
-
323
- const marketId = query.address.get('core.market');
324
- marketObject =
325
- marketObject ||
326
- (
327
- await query.cache.queryGetObject(marketId, {
328
- showContent: true,
329
- })
330
- )?.data;
331
-
332
- if (!(marketObject && marketObject.content?.dataType === 'moveObject'))
333
- throw new Error(`Failed to fetch marketObject`);
334
-
335
- const fields = marketObject.content.fields as any;
336
- const coinType = query.utils.parseCoinType(poolCoinName);
337
- // Get balance sheet.
338
- const balanceSheetParentId =
339
- fields.vault.fields.balance_sheets.fields.table.fields.id.id;
340
- const balanceSheetDynamicFieldObjectResponse =
341
- await query.cache.queryGetDynamicFieldObject({
342
- parentId: balanceSheetParentId,
343
- name: {
344
- type: '0x1::type_name::TypeName',
345
- value: {
346
- name: coinType.substring(2),
347
- },
348
- },
349
- });
350
-
351
- const balanceSheetDynamicFieldObject =
352
- balanceSheetDynamicFieldObjectResponse?.data;
353
-
354
- if (
355
- !(
356
- balanceSheetDynamicFieldObject &&
357
- balanceSheetDynamicFieldObject.content &&
358
- 'fields' in balanceSheetDynamicFieldObject.content
359
- )
360
- )
361
- throw new Error(
362
- `Failed to fetch balanceSheetDynamicFieldObject for ${poolCoinName}: ${balanceSheetDynamicFieldObjectResponse?.error?.code.toString()}`
363
- );
364
- const balanceSheet: BalanceSheet = (
365
- balanceSheetDynamicFieldObject.content.fields as any
366
- ).value.fields;
367
-
368
- // Get borrow index.
369
- const borrowIndexParentId = fields.borrow_dynamics.fields.table.fields.id.id;
370
- const borrowIndexDynamicFieldObjectResponse =
371
- await query.cache.queryGetDynamicFieldObject({
372
- parentId: borrowIndexParentId,
373
- name: {
374
- type: '0x1::type_name::TypeName',
375
- value: {
376
- name: coinType.substring(2),
377
- },
378
- },
379
- });
380
-
381
- const borrowIndexDynamicFieldObject =
382
- borrowIndexDynamicFieldObjectResponse?.data;
383
- if (
384
- !(
385
- borrowIndexDynamicFieldObject &&
386
- borrowIndexDynamicFieldObject.content &&
387
- 'fields' in borrowIndexDynamicFieldObject.content
388
- )
389
- )
390
- throw new Error(
391
- `Failed to fetch borrowIndexDynamicFieldObject for ${poolCoinName}`
392
- );
393
- const borrowIndex: BorrowIndex = (
394
- borrowIndexDynamicFieldObject.content.fields as any
395
- ).value.fields;
396
-
397
- // Get interest models.
398
- const interestModelParentId =
399
- fields.interest_models.fields.table.fields.id.id;
400
- const interestModelDynamicFieldObjectResponse =
401
- await query.cache.queryGetDynamicFieldObject({
402
- parentId: interestModelParentId,
403
- name: {
404
- type: '0x1::type_name::TypeName',
405
- value: {
406
- name: coinType.substring(2),
407
- },
408
- },
409
- });
410
-
411
- const interestModelDynamicFieldObject =
412
- interestModelDynamicFieldObjectResponse?.data;
413
- if (
414
- !(
415
- interestModelDynamicFieldObject &&
416
- interestModelDynamicFieldObject.content &&
417
- 'fields' in interestModelDynamicFieldObject.content
418
- )
419
- )
420
- throw new Error(
421
- `Failed to fetch interestModelDynamicFieldObject for ${poolCoinName}: ${interestModelDynamicFieldObject}`
422
- );
423
- const interestModel: InterestModel = (
424
- interestModelDynamicFieldObject.content.fields as any
425
- ).value.fields;
426
-
427
- // Get borrow fee.
428
- const getBorrowFee = async () => {
429
- const borrowFeeDynamicFieldObjectResponse =
430
- await query.cache.queryGetDynamicFieldObject({
431
- parentId: marketId,
432
- name: {
433
- type: `${BORROW_FEE_PROTOCOL_ID}::market_dynamic_keys::BorrowFeeKey`,
434
- value: {
435
- type: {
436
- name: coinType.substring(2),
437
- },
438
- },
439
- },
440
- });
570
+ let marketCollateralIndexer: MarketCollateral | undefined = undefined;
571
+ if (SUPPORT_COLLATERALS.includes(poolCoinName as SupportCollateralCoins)) {
572
+ marketCollateralIndexer = await query.indexer.getMarketCollateral(
573
+ poolCoinName as SupportCollateralCoins
574
+ );
575
+ marketCollateralIndexer.coinPrice =
576
+ coinPrice ?? marketCollateralIndexer.coinPrice;
577
+ marketCollateralIndexer.coinWrappedType = query.utils.getCoinWrappedType(
578
+ marketCollateralIndexer.coinName
579
+ );
580
+ }
441
581
 
442
- const borrowFeeDynamicFieldObject =
443
- borrowFeeDynamicFieldObjectResponse?.data;
444
- if (
445
- !(
446
- borrowFeeDynamicFieldObject &&
447
- borrowFeeDynamicFieldObject.content &&
448
- 'fields' in borrowFeeDynamicFieldObject.content
449
- )
450
- )
451
- return { value: '0' };
452
- return (borrowFeeDynamicFieldObject.content.fields as any).value.fields;
453
- };
582
+ return {
583
+ marketPool: marketPoolIndexer,
584
+ collateral: marketCollateralIndexer,
585
+ };
586
+ }
454
587
 
455
- const parsedMarketPoolData = parseOriginMarketPoolData({
456
- type: interestModel.type.fields,
457
- maxBorrowRate: interestModel.max_borrow_rate.fields,
458
- interestRate: borrowIndex.interest_rate.fields,
459
- interestRateScale: borrowIndex.interest_rate_scale,
460
- borrowIndex: borrowIndex.borrow_index,
461
- lastUpdated: borrowIndex.last_updated,
462
- cash: balanceSheet.cash,
463
- debt: balanceSheet.debt,
464
- marketCoinSupply: balanceSheet.market_coin_supply,
465
- reserve: balanceSheet.revenue,
466
- reserveFactor: interestModel.revenue_factor.fields,
467
- borrowWeight: interestModel.borrow_weight.fields,
468
- borrowFeeRate: await getBorrowFee(),
469
- baseBorrowRatePerSec: interestModel.base_borrow_rate_per_sec.fields,
470
- borrowRateOnHighKink: interestModel.borrow_rate_on_high_kink.fields,
471
- borrowRateOnMidKink: interestModel.borrow_rate_on_mid_kink.fields,
472
- highKink: interestModel.high_kink.fields,
473
- midKink: interestModel.mid_kink.fields,
474
- minBorrowAmount: interestModel.min_borrow_amount,
475
- });
588
+ requiredObjects ??= (await queryRequiredMarketObjects(query, [poolCoinName]))[
589
+ poolCoinName
590
+ ];
476
591
 
592
+ const parsedMarketPoolObjects = parseMarketPoolObjects(requiredObjects);
593
+ const parsedMarketPoolData = parseOriginMarketPoolData(
594
+ parsedMarketPoolObjects
595
+ );
477
596
  const calculatedMarketPoolData = calculateMarketPoolData(
478
597
  query.utils,
479
598
  parsedMarketPoolData
480
599
  );
481
-
482
- const coinDecimal = query.utils.getCoinDecimal(poolCoinName);
483
- const maxSupplyCoin = BigNumber(
484
- (await getSupplyLimit(query.utils, poolCoinName)) ?? '0'
485
- )
486
- .shiftedBy(-coinDecimal)
487
- .toNumber();
488
- const maxBorrowCoin = BigNumber(
489
- (await getBorrowLimit(query.utils, poolCoinName)) ?? '0'
490
- )
491
- .shiftedBy(-coinDecimal)
492
- .toNumber();
493
-
494
- return {
495
- coinName: poolCoinName,
600
+ const parsedMarketCollateralData =
601
+ parsedMarketPoolObjects.parsedOriginMarketCollateral
602
+ ? parseOriginMarketCollateralData(
603
+ parsedMarketPoolObjects.parsedOriginMarketCollateral
604
+ )
605
+ : undefined;
606
+
607
+ const basePoolData = <T extends SupportPoolCoins = SupportPoolCoins>() => ({
608
+ coinName: poolCoinName as T,
496
609
  symbol: query.utils.parseSymbol(poolCoinName),
497
- coinType: query.utils.parseCoinType(poolCoinName),
498
610
  marketCoinType: query.utils.parseMarketCoinType(poolCoinName),
499
- sCoinType: query.utils.parseSCoinType(
500
- query.utils.parseMarketCoinName(poolCoinName)
501
- ),
502
- coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
503
- coinDecimal,
504
- coinPrice: coinPrice ?? 0,
505
- highKink: parsedMarketPoolData.highKink,
506
- midKink: parsedMarketPoolData.midKink,
507
- reserveFactor: parsedMarketPoolData.reserveFactor,
508
- borrowWeight: parsedMarketPoolData.borrowWeight,
509
- borrowFee: parsedMarketPoolData.borrowFee,
510
- marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
511
- minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
512
- maxSupplyCoin,
513
- maxBorrowCoin,
514
- isIsolated: await isIsolatedAsset(query.utils, poolCoinName),
515
- ...calculatedMarketPoolData,
611
+ coinType: query.utils.parseCoinType(poolCoinName),
612
+ });
613
+ return {
614
+ marketPool: {
615
+ ...basePoolData(),
616
+ sCoinType: query.utils.parseSCoinType(
617
+ query.utils.parseMarketCoinName(poolCoinName)
618
+ ),
619
+ coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
620
+ coinPrice: coinPrice ?? 0,
621
+ highKink: parsedMarketPoolData.highKink,
622
+ midKink: parsedMarketPoolData.midKink,
623
+ reserveFactor: parsedMarketPoolData.reserveFactor,
624
+ borrowWeight: parsedMarketPoolData.borrowWeight,
625
+ borrowFee: parsedMarketPoolData.borrowFee,
626
+ marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
627
+ minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
628
+ ...calculatedMarketPoolData,
629
+ },
630
+ collateral: parsedMarketCollateralData
631
+ ? {
632
+ ...basePoolData<SupportCollateralCoins>(),
633
+ coinWrappedType: query.utils.getCoinWrappedType(poolCoinName),
634
+ coinPrice: coinPrice,
635
+ collateralFactor: parsedMarketCollateralData.collateralFactor,
636
+ liquidationFactor: parsedMarketCollateralData.liquidationFactor,
637
+ liquidationDiscount: parsedMarketCollateralData.liquidationDiscount,
638
+ liquidationPenalty: parsedMarketCollateralData.liquidationPenalty,
639
+ liquidationReserveFactor:
640
+ parsedMarketCollateralData.liquidationReserveFactor,
641
+ ...calculateMarketCollateralData(
642
+ query.utils,
643
+ parsedMarketCollateralData
644
+ ),
645
+ }
646
+ : undefined,
516
647
  };
517
648
  };
518
649
 
@@ -691,10 +822,11 @@ export const getMarketCollateral = async (
691
822
  collateralFactor: riskModel.collateral_factor.fields,
692
823
  liquidationFactor: riskModel.liquidation_factor.fields,
693
824
  liquidationDiscount: riskModel.liquidation_discount.fields,
694
- liquidationPanelty: riskModel.liquidation_penalty.fields,
825
+ liquidationPenalty: riskModel.liquidation_penalty.fields,
695
826
  liquidationReserveFactor: riskModel.liquidation_revenue_factor.fields,
696
827
  maxCollateralAmount: riskModel.max_collateral_amount,
697
828
  totalCollateralAmount: collateralStat.amount,
829
+ isIsolated: await isIsolatedAsset(query.utils, collateralCoinName),
698
830
  });
699
831
 
700
832
  const calculatedMarketCollateralData = calculateMarketCollateralData(
@@ -708,15 +840,13 @@ export const getMarketCollateral = async (
708
840
  coinType: query.utils.parseCoinType(collateralCoinName),
709
841
  marketCoinType: query.utils.parseMarketCoinType(collateralCoinName),
710
842
  coinWrappedType: query.utils.getCoinWrappedType(collateralCoinName),
711
- coinDecimal: query.utils.getCoinDecimal(collateralCoinName),
712
843
  coinPrice: coinPrice ?? 0,
713
844
  collateralFactor: parsedMarketCollateralData.collateralFactor,
714
845
  liquidationFactor: parsedMarketCollateralData.liquidationFactor,
715
846
  liquidationDiscount: parsedMarketCollateralData.liquidationDiscount,
716
- liquidationPanelty: parsedMarketCollateralData.liquidationPanelty,
847
+ liquidationPenalty: parsedMarketCollateralData.liquidationPenalty,
717
848
  liquidationReserveFactor:
718
849
  parsedMarketCollateralData.liquidationReserveFactor,
719
- isIsolated: await isIsolatedAsset(query.utils, collateralCoinName),
720
850
  ...calculatedMarketCollateralData,
721
851
  };
722
852
  };