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

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.
@@ -45,10 +45,13 @@ import {
45
45
  * Use inspectTxn call to obtain the data provided in the scallop contract query module.
46
46
  *
47
47
  * @param query - The Scallop query instance.
48
- * @param rateType - How interest rates are calculated.
48
+ * @param indexer - Whether to use indexer.
49
49
  * @return Market data.
50
50
  */
51
- export const queryMarket = async (query: ScallopQuery) => {
51
+ export const queryMarket = async (
52
+ query: ScallopQuery,
53
+ indexer: boolean = false
54
+ ) => {
52
55
  const packageId = query.address.get('core.packages.query.id');
53
56
  const marketId = query.address.get('core.market');
54
57
  const txBlock = new SuiKitTxBlock();
@@ -56,16 +59,35 @@ export const queryMarket = async (query: ScallopQuery) => {
56
59
  txBlock.moveCall(queryTarget, [marketId]);
57
60
  const queryResult = await query.suiKit.inspectTxn(txBlock);
58
61
  const marketData = queryResult.events[0].parsedJson as MarketQueryInterface;
62
+ const coinPrices = await query.utils.getCoinPrices();
59
63
 
60
64
  const pools: MarketPools = {};
61
65
  const collaterals: MarketCollaterals = {};
62
66
 
67
+ if (indexer) {
68
+ const marketIndexer = await query.indexer.getMarket();
69
+ for (const pool of Object.values(marketIndexer.pools)) {
70
+ pool.coinPrice = coinPrices[pool.coinName] || pool.coinPrice;
71
+ pool.coinWrappedType = query.utils.getCoinWrappedType(pool.coinName);
72
+ }
73
+ for (const collateral of Object.values(marketIndexer.collaterals)) {
74
+ collateral.coinPrice =
75
+ coinPrices[collateral.coinName] || collateral.coinPrice;
76
+ collateral.coinWrappedType = query.utils.getCoinWrappedType(
77
+ collateral.coinName
78
+ );
79
+ }
80
+ return {
81
+ pools: marketIndexer.pools,
82
+ collaterals: marketIndexer.collaterals,
83
+ };
84
+ }
85
+
63
86
  for (const pool of marketData.pools) {
64
87
  const coinType = normalizeStructTag(pool.type.name);
65
88
  const poolCoinName =
66
89
  query.utils.parseCoinNameFromType<SupportPoolCoins>(coinType);
67
- const coinPrice =
68
- (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName] ?? 0;
90
+ const coinPrice = coinPrices[poolCoinName] ?? 0;
69
91
 
70
92
  // Filter pools not yet supported by the SDK.
71
93
  if (!SUPPORT_POOLS.includes(poolCoinName)) {
@@ -122,10 +144,7 @@ export const queryMarket = async (query: ScallopQuery) => {
122
144
  const coinType = normalizeStructTag(collateral.type.name);
123
145
  const collateralCoinName =
124
146
  query.utils.parseCoinNameFromType<SupportCollateralCoins>(coinType);
125
- const coinPrice =
126
- (await query.utils.getCoinPrices([collateralCoinName]))?.[
127
- collateralCoinName
128
- ] ?? 0;
147
+ const coinPrice = coinPrices[collateralCoinName] ?? 0;
129
148
 
130
149
  // Filter collaterals not yet supported by the SDK.
131
150
  if (!SUPPORT_COLLATERALS.includes(collateralCoinName)) {
@@ -182,11 +201,13 @@ export const queryMarket = async (query: ScallopQuery) => {
182
201
  *
183
202
  * @param query - The Scallop query instance.
184
203
  * @param coinNames - Specific an array of support pool coin name.
204
+ * @param indexer - Whether to use indexer.
185
205
  * @return Market pools data.
186
206
  */
187
207
  export const getMarketPools = async (
188
208
  query: ScallopQuery,
189
- poolCoinNames?: SupportPoolCoins[]
209
+ poolCoinNames?: SupportPoolCoins[],
210
+ indexer: boolean = false
190
211
  ) => {
191
212
  poolCoinNames = poolCoinNames || [...SUPPORT_POOLS];
192
213
  const marketId = query.address.get('core.market');
@@ -199,10 +220,27 @@ export const getMarketPools = async (
199
220
  const coinPrices = await query.utils.getCoinPrices(poolCoinNames ?? []);
200
221
 
201
222
  const marketPools: MarketPools = {};
223
+
224
+ if (indexer) {
225
+ const marketPoolsIndexer = await query.indexer.getMarketPools();
226
+ for (const marketPool of Object.values(marketPoolsIndexer)) {
227
+ if (!poolCoinNames.includes(marketPool.coinName)) continue;
228
+ marketPool.coinPrice =
229
+ coinPrices[marketPool.coinName] || marketPool.coinPrice;
230
+ marketPool.coinWrappedType = query.utils.getCoinWrappedType(
231
+ marketPool.coinName
232
+ );
233
+ marketPools[marketPool.coinName] = marketPool;
234
+ }
235
+
236
+ return marketPools;
237
+ }
238
+
202
239
  for (const poolCoinName of poolCoinNames) {
203
240
  const marketPool = await getMarketPool(
204
241
  query,
205
242
  poolCoinName,
243
+ indexer,
206
244
  marketObjectResponse.data,
207
245
  coinPrices?.[poolCoinName]
208
246
  );
@@ -220,6 +258,7 @@ export const getMarketPools = async (
220
258
  *
221
259
  * @param query - The Scallop query instance.
222
260
  * @param poolCoinName - Specific support pool coin name.
261
+ * @param indexer - Whether to use indexer.
223
262
  * @param marketObject - The market object.
224
263
  * @param coinPrice - The coin price.
225
264
  * @returns Market pool data.
@@ -227,6 +266,7 @@ export const getMarketPools = async (
227
266
  export const getMarketPool = async (
228
267
  query: ScallopQuery,
229
268
  poolCoinName: SupportPoolCoins,
269
+ indexer: boolean = false,
230
270
  marketObject?: SuiObjectData | null,
231
271
  coinPrice?: number
232
272
  ) => {
@@ -242,11 +282,26 @@ export const getMarketPool = async (
242
282
  })
243
283
  ).data;
244
284
 
285
+ coinPrice =
286
+ coinPrice ||
287
+ (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName];
288
+
245
289
  let marketPool: MarketPool | undefined;
246
290
  let balanceSheet: BalanceSheet | undefined;
247
291
  let borrowIndex: BorrowIndex | undefined;
248
292
  let interestModel: InterestModel | undefined;
249
293
  let borrowFeeRate: { value: string } | undefined;
294
+
295
+ if (indexer) {
296
+ const marketPoolIndexer = await query.indexer.getMarketPool(poolCoinName);
297
+ marketPoolIndexer.coinPrice = coinPrice || marketPoolIndexer.coinPrice;
298
+ marketPoolIndexer.coinWrappedType = query.utils.getCoinWrappedType(
299
+ marketPoolIndexer.coinName
300
+ );
301
+
302
+ return marketPoolIndexer;
303
+ }
304
+
250
305
  if (marketObject) {
251
306
  if (marketObject.content && 'fields' in marketObject.content) {
252
307
  const fields = marketObject.content.fields as any;
@@ -386,9 +441,6 @@ export const getMarketPool = async (
386
441
  parsedMarketPoolData
387
442
  );
388
443
 
389
- coinPrice =
390
- coinPrice ||
391
- (await query.utils.getCoinPrices([poolCoinName]))?.[poolCoinName];
392
444
  marketPool = {
393
445
  coinName: poolCoinName,
394
446
  symbol: query.utils.parseSymbol(poolCoinName),
@@ -420,11 +472,13 @@ export const getMarketPool = async (
420
472
  *
421
473
  * @param query - The Scallop query instance.
422
474
  * @param collateralCoinNames - Specific an array of support collateral coin name.
475
+ * @param indexer - Whether to use indexer.
423
476
  * @return Market collaterals data.
424
477
  */
425
478
  export const getMarketCollaterals = async (
426
479
  query: ScallopQuery,
427
- collateralCoinNames?: SupportCollateralCoins[]
480
+ collateralCoinNames?: SupportCollateralCoins[],
481
+ indexer: boolean = false
428
482
  ) => {
429
483
  collateralCoinNames = collateralCoinNames || [...SUPPORT_COLLATERALS];
430
484
  const marketId = query.address.get('core.market');
@@ -437,10 +491,26 @@ export const getMarketCollaterals = async (
437
491
  const coinPrices = await query.utils.getCoinPrices(collateralCoinNames ?? []);
438
492
 
439
493
  const marketCollaterals: MarketCollaterals = {};
494
+
495
+ if (indexer) {
496
+ const marketCollateralsIndexer = await query.indexer.getMarketCollaterals();
497
+ for (const marketCollateral of Object.values(marketCollateralsIndexer)) {
498
+ if (!collateralCoinNames.includes(marketCollateral.coinName)) continue;
499
+ marketCollateral.coinPrice =
500
+ coinPrices[marketCollateral.coinName] || marketCollateral.coinPrice;
501
+ marketCollateral.coinWrappedType = query.utils.getCoinWrappedType(
502
+ marketCollateral.coinName
503
+ );
504
+ marketCollaterals[marketCollateral.coinName] = marketCollateral;
505
+ }
506
+ return marketCollaterals;
507
+ }
508
+
440
509
  for (const collateralCoinName of collateralCoinNames) {
441
510
  const marketCollateral = await getMarketCollateral(
442
511
  query,
443
512
  collateralCoinName,
513
+ indexer,
444
514
  marketObjectResponse.data,
445
515
  coinPrices?.[collateralCoinName]
446
516
  );
@@ -458,6 +528,7 @@ export const getMarketCollaterals = async (
458
528
  *
459
529
  * @param query - The Scallop query instance.
460
530
  * @param collateralCoinName - Specific support collateral coin name.
531
+ * @param indexer - Whether to use indexer.
461
532
  * @param marketObject - The market object.
462
533
  * @param coinPrice - The coin price.
463
534
  * @returns Market collateral data.
@@ -465,6 +536,7 @@ export const getMarketCollaterals = async (
465
536
  export const getMarketCollateral = async (
466
537
  query: ScallopQuery,
467
538
  collateralCoinName: SupportCollateralCoins,
539
+ indexer: boolean = false,
468
540
  marketObject?: SuiObjectData | null,
469
541
  coinPrice?: number
470
542
  ) => {
@@ -480,9 +552,28 @@ export const getMarketCollateral = async (
480
552
  })
481
553
  ).data;
482
554
 
555
+ coinPrice =
556
+ coinPrice ||
557
+ (await query.utils.getCoinPrices([collateralCoinName]))?.[
558
+ collateralCoinName
559
+ ];
560
+
483
561
  let marketCollateral: MarketCollateral | undefined;
484
562
  let riskModel: RiskModel | undefined;
485
563
  let collateralStat: CollateralStat | undefined;
564
+
565
+ if (indexer) {
566
+ const marketCollateralIndexer =
567
+ await query.indexer.getMarketCollateral(collateralCoinName);
568
+ marketCollateralIndexer.coinPrice =
569
+ coinPrice || marketCollateralIndexer.coinPrice;
570
+ marketCollateralIndexer.coinWrappedType = query.utils.getCoinWrappedType(
571
+ marketCollateralIndexer.coinName
572
+ );
573
+
574
+ return marketCollateralIndexer;
575
+ }
576
+
486
577
  if (marketObject) {
487
578
  if (marketObject.content && 'fields' in marketObject.content) {
488
579
  const fields = marketObject.content.fields as any;
@@ -558,11 +649,6 @@ export const getMarketCollateral = async (
558
649
  parsedMarketCollateralData
559
650
  );
560
651
 
561
- coinPrice =
562
- coinPrice ||
563
- (await query.utils.getCoinPrices([collateralCoinName]))?.[
564
- collateralCoinName
565
- ];
566
652
  marketCollateral = {
567
653
  coinName: collateralCoinName,
568
654
  symbol: query.utils.parseSymbol(collateralCoinName),
@@ -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,
@@ -28,12 +28,14 @@ import type {
28
28
  * @param query - The ScallopQuery instance.
29
29
  * @param poolCoinNames - Specific an array of support pool coin name.
30
30
  * @param ownerAddress - The owner address.
31
+ * @param indexer - Whether to use indexer.
31
32
  * @return User lending infomation for specific pools.
32
33
  */
33
34
  export const getLendings = async (
34
35
  query: ScallopQuery,
35
36
  poolCoinNames?: SupportPoolCoins[],
36
- ownerAddress?: string
37
+ ownerAddress?: string,
38
+ indexer: boolean = false
37
39
  ) => {
38
40
  poolCoinNames = poolCoinNames || [...SUPPORT_POOLS];
39
41
  const marketCoinNames = poolCoinNames.map((poolCoinName) =>
@@ -43,8 +45,8 @@ export const getLendings = async (
43
45
  (SUPPORT_SPOOLS as readonly SupportMarketCoins[]).includes(marketCoinName)
44
46
  ) as SupportStakeMarketCoins[];
45
47
 
46
- const marketPools = await query.getMarketPools(poolCoinNames);
47
- const spools = await query.getSpools(stakeMarketCoinNames);
48
+ const marketPools = await query.getMarketPools(poolCoinNames, indexer);
49
+ const spools = await query.getSpools(stakeMarketCoinNames, indexer);
48
50
  const coinAmounts = await query.getCoinAmounts(poolCoinNames, ownerAddress);
49
51
  const marketCoinAmounts = await query.getMarketCoinAmounts(
50
52
  marketCoinNames,
@@ -64,6 +66,7 @@ export const getLendings = async (
64
66
  query,
65
67
  poolCoinName,
66
68
  ownerAddress,
69
+ indexer,
67
70
  marketPools?.[poolCoinName],
68
71
  stakeMarketCoinName ? spools[stakeMarketCoinName] : undefined,
69
72
  stakeMarketCoinName ? allStakeAccounts[stakeMarketCoinName] : undefined,
@@ -85,6 +88,7 @@ export const getLendings = async (
85
88
  * @param query - The ScallopQuery instance.
86
89
  * @param poolCoinName - Specific support coin name.
87
90
  * @param ownerAddress - The owner address.
91
+ * @param indexer - Whether to use indexer.
88
92
  * @param marketPool - The market pool data.
89
93
  * @param spool - The spool data.
90
94
  * @param stakeAccounts - The stake accounts data.
@@ -96,6 +100,7 @@ export const getLending = async (
96
100
  query: ScallopQuery,
97
101
  poolCoinName: SupportPoolCoins,
98
102
  ownerAddress?: string,
103
+ indexer: boolean = false,
99
104
  marketPool?: MarketPool,
100
105
  spool?: Spool,
101
106
  stakeAccounts?: StakeAccount[],
@@ -104,11 +109,11 @@ export const getLending = async (
104
109
  coinPrice?: number
105
110
  ) => {
106
111
  const marketCoinName = query.utils.parseMarketCoinName(poolCoinName);
107
- marketPool = marketPool || (await query.getMarketPool(poolCoinName));
112
+ marketPool = marketPool || (await query.getMarketPool(poolCoinName, indexer));
108
113
  spool =
109
114
  spool ||
110
115
  (SUPPORT_SPOOLS as readonly SupportMarketCoins[]).includes(marketCoinName)
111
- ? await query.getSpool(marketCoinName as SupportStakeMarketCoins)
116
+ ? await query.getSpool(marketCoinName as SupportStakeMarketCoins, indexer)
112
117
  : undefined;
113
118
  stakeAccounts =
114
119
  stakeAccounts ||
@@ -170,7 +175,7 @@ export const getLending = async (
170
175
  );
171
176
 
172
177
  const baseIndexRate = 1_000_000_000;
173
- const increasedPointRate = spool?.currentPointIndex
178
+ const increasedPointRate = spool.currentPointIndex
174
179
  ? BigNumber(spool.currentPointIndex - stakeAccount.index).dividedBy(
175
180
  baseIndexRate
176
181
  )
@@ -252,13 +257,15 @@ export const getLending = async (
252
257
  *
253
258
  * @param query - The Scallop query instance.
254
259
  * @param ownerAddress - The owner address.
260
+ * @param indexer - Whether to use indexer.
255
261
  * @return All obligation accounts data.
256
262
  */
257
263
  export const getObligationAccounts = async (
258
264
  query: ScallopQuery,
259
- ownerAddress?: string
265
+ ownerAddress?: string,
266
+ indexer: boolean = false
260
267
  ) => {
261
- const market = await query.queryMarket();
268
+ const market = await query.queryMarket(indexer);
262
269
  const coinPrices = await query.utils.getCoinPrices();
263
270
  const coinAmounts = await query.getCoinAmounts(undefined, ownerAddress);
264
271
  const obligations = await query.getObligations(ownerAddress);
@@ -269,6 +276,7 @@ export const getObligationAccounts = async (
269
276
  query,
270
277
  obligation.id,
271
278
  ownerAddress,
279
+ indexer,
272
280
  market,
273
281
  coinPrices,
274
282
  coinAmounts
@@ -283,17 +291,19 @@ export const getObligationAccounts = async (
283
291
  *
284
292
  * @param query - The Scallop query instance.
285
293
  * @param obligationId - The obligation id.
294
+ * @param indexer - Whether to use indexer.
286
295
  * @return Obligation account data.
287
296
  */
288
297
  export const getObligationAccount = async (
289
298
  query: ScallopQuery,
290
299
  obligationId: string,
291
300
  ownerAddress?: string,
301
+ indexer: boolean = false,
292
302
  market?: Market,
293
303
  coinPrices?: CoinPrices,
294
304
  coinAmounts?: CoinAmounts
295
305
  ) => {
296
- market = market || (await query.queryMarket());
306
+ market = market || (await query.queryMarket(indexer));
297
307
  const assetCoinNames: SupportAssetCoins[] = [
298
308
  ...new Set([
299
309
  ...Object.values(market.pools).map((pool) => pool.coinName),
@@ -303,7 +313,10 @@ export const getObligationAccount = async (
303
313
  ]),
304
314
  ];
305
315
  const obligationQuery = await query.queryObligation(obligationId);
306
- const borrowIncentivePools = await query.getBorrowIncentivePools();
316
+ const borrowIncentivePools = await query.getBorrowIncentivePools(
317
+ undefined,
318
+ indexer
319
+ );
307
320
  const borrowIncentiveAccounts =
308
321
  await query.getBorrowIncentiveAccounts(obligationId);
309
322
  coinPrices = coinPrices || (await query.utils.getCoinPrices(assetCoinNames));
@@ -330,8 +343,8 @@ export const getObligationAccount = async (
330
343
  return assetCoinName === collateralCoinName;
331
344
  });
332
345
 
333
- const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
334
346
  const marketCollateral = market.collaterals[assetCoinName];
347
+ const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
335
348
  const coinPrice = coinPrices?.[assetCoinName];
336
349
  const coinAmount = coinAmounts?.[assetCoinName] ?? 0;
337
350
 
@@ -388,9 +401,10 @@ export const getObligationAccount = async (
388
401
  return assetCoinName === poolCoinName;
389
402
  });
390
403
 
391
- const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
392
404
  const marketPool = market.pools[assetCoinName];
405
+ const coinDecimal = query.utils.getCoinDecimal(assetCoinName);
393
406
  const coinPrice = coinPrices?.[assetCoinName];
407
+ const coinAmount = coinAmounts?.[assetCoinName] ?? 0;
394
408
 
395
409
  if (marketPool && coinPrice) {
396
410
  const increasedRate = debt?.borrowIndex
@@ -398,13 +412,18 @@ export const getObligationAccount = async (
398
412
  : 0;
399
413
  const borrowedAmount = BigNumber(debt?.amount ?? 0);
400
414
  const borrowedCoin = borrowedAmount.shiftedBy(-1 * coinDecimal);
401
- const availableRepayAmount = borrowedAmount.multipliedBy(
415
+
416
+ const requiredRepayAmount = borrowedAmount.multipliedBy(
402
417
  increasedRate + 1
403
418
  );
419
+ const requiredRepayCoin = requiredRepayAmount.shiftedBy(-1 * coinDecimal);
420
+
421
+ const availableRepayAmount = BigNumber(coinAmount);
404
422
  const availableRepayCoin = availableRepayAmount.shiftedBy(
405
423
  -1 * coinDecimal
406
424
  );
407
- const borrowedValue = availableRepayCoin.multipliedBy(coinPrice);
425
+
426
+ const borrowedValue = requiredRepayCoin.multipliedBy(coinPrice);
408
427
  const borrowedValueWithWeight = borrowedValue.multipliedBy(
409
428
  marketPool.borrowWeight
410
429
  );
@@ -429,6 +448,8 @@ export const getObligationAccount = async (
429
448
  borrowedValue: borrowedValue.toNumber(),
430
449
  borrowedValueWithWeight: borrowedValueWithWeight.toNumber(),
431
450
  borrowIndex: Number(debt?.borrowIndex ?? 0),
451
+ requiredRepayAmount: requiredRepayAmount.toNumber(),
452
+ requiredRepayCoin: requiredRepayCoin.toNumber(),
432
453
  availableBorrowAmount: 0,
433
454
  availableBorrowCoin: 0,
434
455
  availableRepayAmount: availableRepayAmount.toNumber(),
@@ -481,16 +502,11 @@ export const getObligationAccount = async (
481
502
  }
482
503
  }
483
504
 
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);
505
+ let riskLevel = totalRequiredCollateralValue.isZero()
506
+ ? BigNumber(0)
507
+ : totalBorrowedValueWithWeight.dividedBy(totalRequiredCollateralValue);
508
+ // Note: 100% represents the safety upper limit. Even if it exceeds 100% before it is liquidated, it will only display 100%.
509
+ riskLevel = riskLevel.isLessThan(1) ? riskLevel : BigNumber(1);
494
510
 
495
511
  const accountBalanceValue = totalDepositedValue
496
512
  .minus(totalBorrowedValue)
@@ -543,24 +559,38 @@ export const getObligationAccount = async (
543
559
  const marketCollateral =
544
560
  market.collaterals[collateralCoinName as SupportCollateralCoins];
545
561
  if (marketCollateral) {
546
- const availableWithdrawAmount =
562
+ let estimatedAvailableWithdrawAmount = BigNumber(
563
+ obligationAccount.totalAvailableCollateralValue
564
+ )
565
+ .dividedBy(marketCollateral.collateralFactor)
566
+ .dividedBy(marketCollateral.coinPrice)
567
+ .shiftedBy(marketCollateral.coinDecimal);
568
+ estimatedAvailableWithdrawAmount =
547
569
  obligationAccount.totalBorrowedValueWithWeight === 0
548
- ? BigNumber(obligationCollateral.depositedAmount)
570
+ ? // Note: when there is no debt record, there is no need to estimate and the deposited amount is directly used as available withdraw.
571
+ BigNumber(obligationCollateral.depositedAmount)
549
572
  : minBigNumber(
550
- BigNumber(obligationAccount.totalAvailableCollateralValue)
551
- .dividedBy(marketCollateral.collateralFactor)
552
- .dividedBy(marketCollateral.coinPrice)
573
+ estimatedAvailableWithdrawAmount
553
574
  // Note: reduced chance of failure when calculations are inaccurate
554
- .multipliedBy(0.99)
575
+ .multipliedBy(
576
+ estimatedFactor(
577
+ BigNumber(obligationAccount.totalAvailableCollateralValue)
578
+ .dividedBy(marketCollateral.collateralFactor)
579
+ .toNumber(),
580
+ 3,
581
+ 'increase'
582
+ )
583
+ )
555
584
  .toNumber(),
556
585
  obligationCollateral.depositedAmount,
557
586
  marketCollateral.depositAmount
558
587
  );
559
588
  obligationCollateral.availableWithdrawAmount =
560
- availableWithdrawAmount.toNumber();
561
- obligationCollateral.availableWithdrawCoin = availableWithdrawAmount
562
- .shiftedBy(-1 * obligationCollateral.coinDecimal)
563
- .toNumber();
589
+ estimatedAvailableWithdrawAmount.toNumber();
590
+ obligationCollateral.availableWithdrawCoin =
591
+ estimatedAvailableWithdrawAmount
592
+ .shiftedBy(-1 * obligationCollateral.coinDecimal)
593
+ .toNumber();
564
594
  }
565
595
  }
566
596
  for (const [poolCoinName, obligationDebt] of Object.entries(
@@ -568,33 +598,49 @@ export const getObligationAccount = async (
568
598
  )) {
569
599
  const marketPool = market.pools[poolCoinName as SupportPoolCoins];
570
600
  if (marketPool) {
571
- const availableRepayAmount = BigNumber(
572
- obligationDebt.availableRepayAmount
601
+ const estimatedRequiredRepayAmount = BigNumber(
602
+ obligationDebt.requiredRepayAmount
573
603
  )
574
- // Note: reduced chance of failure when calculations are inaccurate
575
- .multipliedBy(1.01);
604
+ // Note: reduced chance of not being able to repay in full when calculations are inaccurate,
605
+ // and the contract will not actually take the excess amount.
606
+ .multipliedBy(
607
+ estimatedFactor(obligationDebt.borrowedValue, 3, 'decrease')
608
+ );
576
609
 
577
- const availableBorrowAmount =
610
+ let estimatedAvailableBorrowAmount = BigNumber(
611
+ obligationAccount.totalAvailableCollateralValue
612
+ )
613
+ .dividedBy(marketPool.borrowWeight)
614
+ .shiftedBy(marketPool.coinDecimal)
615
+ .dividedBy(marketPool.coinPrice);
616
+ estimatedAvailableBorrowAmount =
578
617
  obligationAccount.totalAvailableCollateralValue !== 0
579
618
  ? minBigNumber(
580
- BigNumber(obligationAccount.totalAvailableCollateralValue)
581
- .dividedBy(
582
- BigNumber(marketPool.coinPrice).multipliedBy(
583
- marketPool.borrowWeight
619
+ estimatedAvailableBorrowAmount
620
+ // Note: reduced chance of failure when calculations are inaccurate
621
+ .multipliedBy(
622
+ estimatedFactor(
623
+ estimatedAvailableBorrowAmount
624
+ .shiftedBy(-1 * marketPool.coinDecimal)
625
+ .multipliedBy(marketPool.coinPrice)
626
+ .toNumber(),
627
+ 3,
628
+ 'increase'
584
629
  )
585
630
  )
586
- // Note: reduced chance of failure when calculations are inaccurate
587
- .multipliedBy(0.99)
588
631
  .toNumber(),
589
632
  marketPool.supplyAmount
590
633
  )
591
634
  : BigNumber(0);
592
- obligationDebt.availableBorrowAmount = availableBorrowAmount.toNumber();
593
- obligationDebt.availableBorrowCoin = availableBorrowAmount
635
+
636
+ obligationDebt.availableBorrowAmount =
637
+ estimatedAvailableBorrowAmount.toNumber();
638
+ obligationDebt.availableBorrowCoin = estimatedAvailableBorrowAmount
594
639
  .shiftedBy(-1 * obligationDebt.coinDecimal)
595
640
  .toNumber();
596
- obligationDebt.availableRepayAmount = availableRepayAmount.toNumber();
597
- obligationDebt.availableRepayCoin = availableRepayAmount
641
+ obligationDebt.requiredRepayAmount =
642
+ estimatedRequiredRepayAmount.toNumber();
643
+ obligationDebt.requiredRepayCoin = estimatedRequiredRepayAmount
598
644
  .shiftedBy(-1 * obligationDebt.coinDecimal)
599
645
  .toNumber();
600
646
  }
@@ -607,14 +653,27 @@ export const getObligationAccount = async (
607
653
  * Get total value locked data.
608
654
  *
609
655
  * @param query - The Scallop query instance.
656
+ * @param indexer - Whether to use indexer.
610
657
  * @return Total value locked data.
611
658
  */
612
- export const getTotalValueLocked = async (query: ScallopQuery) => {
613
- const market = await query.queryMarket();
659
+ export const getTotalValueLocked = async (
660
+ query: ScallopQuery,
661
+ indexer: boolean = false
662
+ ) => {
663
+ const market = await query.queryMarket(indexer);
614
664
 
615
665
  let supplyValue = BigNumber(0);
616
666
  let borrowValue = BigNumber(0);
617
667
 
668
+ if (indexer) {
669
+ const tvl = await query.indexer.getTotalValueLocked();
670
+ return {
671
+ supplyValue: tvl.supplyValue,
672
+ borrowValue: tvl.borrowValue,
673
+ totalValue: tvl.totalValue,
674
+ };
675
+ }
676
+
618
677
  for (const pool of Object.values(market.pools)) {
619
678
  supplyValue = supplyValue.plus(
620
679
  BigNumber(pool.supplyCoin).multipliedBy(pool.coinPrice)