@scallop-io/sui-scallop-sdk 1.5.3 → 2.0.0-alpha.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 (59) hide show
  1. package/dist/index.d.mts +446 -599
  2. package/dist/index.d.ts +446 -599
  3. package/dist/index.js +29 -60
  4. package/dist/index.mjs +6 -6
  5. package/package.json +1 -1
  6. package/src/builders/loyaltyProgramBuilder.ts +5 -3
  7. package/src/builders/oracle.ts +10 -24
  8. package/src/builders/referralBuilder.ts +5 -9
  9. package/src/builders/sCoinBuilder.ts +9 -8
  10. package/src/builders/spoolBuilder.ts +4 -6
  11. package/src/constants/common.ts +114 -126
  12. package/src/constants/index.ts +0 -5
  13. package/src/constants/pyth.ts +25 -34
  14. package/src/constants/queryKeys.ts +2 -0
  15. package/src/models/index.ts +1 -0
  16. package/src/models/scallop.ts +23 -19
  17. package/src/models/scallopAddress.ts +7 -4
  18. package/src/models/scallopBuilder.ts +32 -35
  19. package/src/models/scallopCache.ts +1 -1
  20. package/src/models/scallopClient.ts +87 -89
  21. package/src/models/scallopConstants.ts +341 -0
  22. package/src/models/scallopIndexer.ts +11 -24
  23. package/src/models/scallopQuery.ts +65 -70
  24. package/src/models/scallopUtils.ts +114 -244
  25. package/src/queries/borrowIncentiveQuery.ts +21 -56
  26. package/src/queries/borrowLimitQuery.ts +3 -6
  27. package/src/queries/coreQuery.ts +94 -112
  28. package/src/queries/flashloanFeeQuery.ts +86 -0
  29. package/src/queries/isolatedAssetQuery.ts +12 -11
  30. package/src/queries/poolAddressesQuery.ts +187 -112
  31. package/src/queries/portfolioQuery.ts +65 -67
  32. package/src/queries/priceQuery.ts +16 -22
  33. package/src/queries/sCoinQuery.ts +15 -16
  34. package/src/queries/spoolQuery.ts +49 -59
  35. package/src/queries/supplyLimitQuery.ts +2 -6
  36. package/src/queries/xOracleQuery.ts +4 -15
  37. package/src/types/address.ts +12 -18
  38. package/src/types/builder/borrowIncentive.ts +2 -3
  39. package/src/types/builder/core.ts +20 -27
  40. package/src/types/builder/index.ts +1 -2
  41. package/src/types/builder/referral.ts +4 -8
  42. package/src/types/builder/sCoin.ts +4 -8
  43. package/src/types/builder/spool.ts +7 -10
  44. package/src/types/constant/common.ts +43 -49
  45. package/src/types/constant/enum.ts +15 -27
  46. package/src/types/constant/xOracle.ts +3 -5
  47. package/src/types/model.ts +47 -28
  48. package/src/types/query/borrowIncentive.ts +7 -24
  49. package/src/types/query/core.ts +8 -18
  50. package/src/types/query/portfolio.ts +8 -17
  51. package/src/types/query/spool.ts +5 -11
  52. package/src/types/utils.ts +1 -21
  53. package/src/utils/core.ts +1 -1
  54. package/src/utils/query.ts +13 -20
  55. package/src/utils/util.ts +6 -84
  56. package/src/constants/coinGecko.ts +0 -34
  57. package/src/constants/enum.ts +0 -268
  58. package/src/constants/flashloan.ts +0 -18
  59. package/src/constants/poolAddress.ts +0 -898
@@ -1,59 +1,118 @@
1
- import { PYTH_FEED_IDS } from 'src/constants';
2
- import { ScallopQuery } from 'src/models';
3
- import { OptionalKeys, SupportPoolCoins } from 'src/types';
1
+ import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
2
+ import { AddressesInterface, OptionalKeys, PoolAddress } from 'src/types';
4
3
 
5
- export const getAllAddresses = async (
6
- query: ScallopQuery,
7
- pools: SupportPoolCoins[]
4
+ const RPC_PROVIDERS = [
5
+ getFullnodeUrl('mainnet'),
6
+ 'https://sui-mainnet.public.blastapi.io',
7
+ 'https://sui-mainnet-ca-2.cosmostation.io',
8
+ 'https://sui-mainnet-eu-4.cosmostation.io',
9
+ 'https://sui-mainnet-endpoint.blockvision.org',
10
+ 'https://sui-rpc.publicnode.com',
11
+ 'https://sui-mainnet-rpc.allthatnode.com',
12
+ 'https://mainnet.suiet.app',
13
+ 'https://mainnet.sui.rpcpool.com',
14
+ 'https://sui1mainnet-rpc.chainode.tech',
15
+ 'https://fullnode.mainnet.apis.scallop.io',
16
+ 'https://sui-mainnet-us-2.cosmostation.io',
17
+ ];
18
+
19
+ const tryRequest = async <T>(fn: (client: SuiClient) => T) => {
20
+ for (const rpc of RPC_PROVIDERS) {
21
+ try {
22
+ const res = await fn(new SuiClient({ url: rpc }));
23
+ return res;
24
+ } catch (e: any) {
25
+ if (e.status !== 429) {
26
+ throw e;
27
+ }
28
+ await new Promise((resolve) => setTimeout(resolve, 500));
29
+ }
30
+ }
31
+ throw new Error('Failed to fetch data');
32
+ };
33
+
34
+ const queryFlashloanFeeObjectIds = async (
35
+ client: SuiClient,
36
+ coinTypeMap: Set<string>, // set of coin types
37
+ flashloanFeeTableId: string = '0x00481a93b819d744a7d79ecdc6c62c74f2f7cb4779316c4df640415817ac61bb'
8
38
  ) => {
9
- const results: OptionalKeys<
10
- Record<
11
- SupportPoolCoins,
12
- {
13
- coinName: string;
14
- symbol: string;
15
- lendingPoolAddress?: string;
16
- collateralPoolAddress?: string; // not all pool has collateral
17
- borrowDynamic?: string;
18
- spoolReward?: string;
19
- spool?: string;
20
- sCoinType?: string;
21
- sCoinName?: string;
22
- sCoinSymbol?: string;
23
- sCoinTreasury?: string;
24
- interestModel?: string;
25
- riskModel?: string;
26
- borrowFeeKey?: string;
27
- supplyLimitKey?: string;
28
- borrowLimitKey?: string;
29
- isolatedAssetKey?: string;
30
- coinMetadataId?: string;
31
- borrowIncentivePoolId?: string;
32
- coinType?: string;
33
- sCoinMetadataId?: string;
34
- spoolName?: string;
35
- decimals: number;
36
- pythFeed?: string;
37
- pythFeedObjectId?: string;
39
+ let cursor: string | null | undefined = null;
40
+ let nextPage: boolean = false;
41
+ const flashloanFeeObjectIds: Record<string, string> = {}; // <coinType, flashloanFeeObjectId>
42
+
43
+ do {
44
+ const resp = await client.getDynamicFields({
45
+ parentId: flashloanFeeTableId,
46
+ limit: 10,
47
+ cursor,
48
+ });
49
+ if (!resp) break;
50
+ const { data, hasNextPage, nextCursor } = resp;
51
+ // get the dynamic object ids
52
+ data.forEach((field) => {
53
+ const assetType = `0x${(field.name.value as any).name as string}`;
54
+ if (coinTypeMap.has(assetType)) {
55
+ flashloanFeeObjectIds[assetType] = field.objectId;
38
56
  }
39
- >
40
- > = {};
57
+ });
58
+ nextPage = hasNextPage;
59
+ cursor = nextCursor;
60
+ } while (nextPage);
61
+
62
+ return flashloanFeeObjectIds;
63
+ };
41
64
 
42
- const marketId = query.address.get('core.market');
43
- const marketObject = (await query.cache.queryGetObject(marketId))?.data;
65
+ export const getPoolAddresses = async (
66
+ addressId: string,
67
+ poolNames: string[] = []
68
+ ) => {
69
+ const poolNameSet = new Set(poolNames);
70
+ const results: OptionalKeys<Record<string, PoolAddress>> = {};
44
71
 
45
- if (!(marketObject && marketObject.content?.dataType === 'moveObject'))
46
- throw new Error(`Failed to fetch marketObject`);
72
+ // fetch the Address API
73
+ const URL = 'https://sui.apis.scallop.io';
74
+ const addressApiResponse = (
75
+ await fetch(`${URL}/addresses/${addressId}`).then((res) => res.json())
76
+ ).mainnet as unknown as AddressesInterface;
47
77
 
48
- const fields = marketObject.content.fields as any;
78
+ if (!addressApiResponse) throw new Error('Failed to fetch addresses');
79
+
80
+ // Compose pools based on addresses
81
+ const pools = Object.keys(addressApiResponse.core.coins);
82
+ if (pools.length === 0) throw new Error('Pools empty');
49
83
 
50
84
  const coinTypesPairs = pools.reduce(
51
- (acc, pool) => {
52
- acc.push([pool, query.utils.parseCoinType(pool).substring(2)]);
85
+ (acc, poolName) => {
86
+ if (poolNameSet.size > 0 && !poolNameSet.has(poolName)) return acc;
87
+ const value =
88
+ addressApiResponse.core.coins[
89
+ poolName as keyof typeof addressApiResponse.core.coins
90
+ ];
91
+ if (value && value.coinType) {
92
+ acc.push([poolName, value.coinType]);
93
+ }
53
94
  return acc;
54
95
  },
55
- [] as [SupportPoolCoins, string][]
96
+ [] as [string, string][]
56
97
  );
98
+ if (coinTypesPairs.length === 0) throw new Error('No coinTypesPairs');
99
+
100
+ const marketId = addressApiResponse.core.market;
101
+ const marketObject = (
102
+ await tryRequest(async (client) => {
103
+ return await client.getObject({
104
+ id: marketId,
105
+ options: {
106
+ showContent: true,
107
+ },
108
+ });
109
+ })
110
+ ).data;
111
+
112
+ if (!(marketObject && marketObject.content?.dataType === 'moveObject'))
113
+ throw new Error(`Failed to fetch marketObject`);
114
+
115
+ const fields = marketObject.content.fields as any;
57
116
 
58
117
  const balanceSheetParentId =
59
118
  fields.vault.fields.balance_sheets.fields.table.fields.id.id;
@@ -79,111 +138,127 @@ export const getAllAddresses = async (
79
138
  type: string,
80
139
  value: any
81
140
  ) => {
82
- try {
83
- return (
84
- await query.cache.queryGetDynamicFieldObject({
141
+ return (
142
+ await tryRequest(async (client) => {
143
+ return await client.getDynamicFieldObject({
85
144
  parentId,
86
145
  name: {
87
146
  type,
88
147
  value,
89
148
  },
90
- })
91
- )?.data?.objectId;
92
- } catch (e: any) {
93
- console.error(e.message);
94
- return undefined;
95
- }
149
+ });
150
+ })
151
+ ).data?.objectId;
96
152
  };
97
153
 
154
+ // query flashloan fee objects first
155
+ const flashloanFeeObjectIds = await tryRequest(async (client) => {
156
+ return await queryFlashloanFeeObjectIds(
157
+ client,
158
+ new Set(coinTypesPairs.map(([, coinType]) => coinType))
159
+ );
160
+ });
161
+
98
162
  await Promise.all(
99
163
  coinTypesPairs.map(async ([coinName, coinType]) => {
164
+ const coinTypeKey = coinType.slice(2);
100
165
  const addresses = await Promise.all([
101
166
  fetchDynamicObject(balanceSheetParentId, ADDRESS_TYPE, {
102
- name: coinType,
167
+ name: coinTypeKey,
103
168
  }),
104
169
  fetchDynamicObject(collateralStatsParentId, ADDRESS_TYPE, {
105
- name: coinType,
170
+ name: coinTypeKey,
106
171
  }),
107
172
  fetchDynamicObject(borrowDynamicsParentid, ADDRESS_TYPE, {
108
- name: coinType,
173
+ name: coinTypeKey,
109
174
  }),
110
175
  fetchDynamicObject(interestModelParentId, ADDRESS_TYPE, {
111
- name: coinType,
176
+ name: coinTypeKey,
112
177
  }),
113
178
  fetchDynamicObject(riskModelParentId, ADDRESS_TYPE, {
114
- name: coinType,
179
+ name: coinTypeKey,
115
180
  }),
116
- fetchDynamicObject(marketId, BORROW_FEE_TYPE, coinType),
117
- fetchDynamicObject(marketId, SUPPLY_LIMIT_TYPE, coinType),
118
- fetchDynamicObject(marketId, BORROW_LIMIT_TYPE, coinType),
119
- fetchDynamicObject(marketId, ISOLATED_ASSET_KEY, coinType),
181
+ fetchDynamicObject(marketId, BORROW_FEE_TYPE, coinTypeKey),
182
+ fetchDynamicObject(marketId, SUPPLY_LIMIT_TYPE, coinTypeKey),
183
+ fetchDynamicObject(marketId, BORROW_LIMIT_TYPE, coinTypeKey),
184
+ fetchDynamicObject(marketId, ISOLATED_ASSET_KEY, coinTypeKey),
120
185
  ]);
121
186
 
122
- const spool = query.address.get(
123
- // @ts-ignore
124
- `spool.pools.s${coinName}.id`
125
- );
126
- const rewardPool = query.address.get(
127
- // @ts-ignore
128
- `spool.pools.s${coinName}.rewardPoolId`
129
- );
130
- const sCoinType = query.address.get(
131
- // @ts-ignore
132
- `scoin.coins.s${coinName}.coinType`
133
- );
134
- const sCoinName = sCoinType
135
- ? query.utils.parseSCoinName(coinName)
136
- : undefined;
137
- const sCoinSymbol = sCoinName
138
- ? query.utils.parseSymbol(sCoinName)
139
- : undefined;
140
- const sCoinTreasury = query.address.get(
141
- // @ts-ignore
142
- `scoin.coins.s${coinName}.treasury`
143
- );
144
- const coinMetadataId = query.address.get(
145
- `core.coins.${coinName}.metaData`
146
- );
147
- const sCoinMetadataId = query.address.get(
187
+ // @ts-ignore
188
+ const { symbol, metaData: coinMetadataId } =
189
+ addressApiResponse.core.coins[coinName];
190
+
191
+ let spoolData = undefined;
192
+ const _spoolData = addressApiResponse.spool.pools[`s${coinName}`];
193
+ // @ts-ignore
194
+ if (_spoolData) {
148
195
  // @ts-ignore
149
- `scoin.coins.s${coinName}.metaData`
150
- );
196
+ const { id: spool, rewardPoolId: spoolReward } = _spoolData;
197
+ spoolData = {
198
+ spool,
199
+ spoolReward,
200
+ coinMetadataId,
201
+ };
202
+ }
151
203
 
152
- const pythFeed = PYTH_FEED_IDS[coinName];
153
- const pythFeedObjectId = query.address.get(
204
+ let sCoinData = undefined;
205
+ const sCoinName = `s${coinName}`;
206
+ const _sCoinData = addressApiResponse.scoin.coins[sCoinName];
207
+ if (_sCoinData) {
208
+ const {
209
+ coinType: sCoinType,
210
+ treasury: sCoinTreasury,
211
+ metaData: sCoinMetadataId,
212
+ symbol: sCoinSymbol,
213
+ } = _sCoinData;
214
+ sCoinData = {
215
+ sCoinType,
216
+ sCoinTreasury,
217
+ sCoinMetadataId,
218
+ sCoinSymbol,
219
+ };
220
+ }
221
+
222
+ const { feed: pythFeed, feedObject: pythFeedObjectId } =
154
223
  //@ts-ignore
155
- `core.coins.${coinName}.oracle.pyth.feedObject`
156
- );
157
- const decimals = query.utils.getCoinDecimal(coinName);
158
- const spoolName = spool ? `s${coinName}` : undefined;
159
- results[coinName as SupportPoolCoins] = {
224
+ addressApiResponse.core.coins[coinName].oracle.pyth;
225
+
226
+ const decimals =
227
+ (
228
+ await tryRequest(async (client) => {
229
+ return await client.getCoinMetadata({
230
+ coinType: coinType,
231
+ });
232
+ })
233
+ )?.decimals ?? 0;
234
+ const spoolName = spoolData ? `s${coinName}` : undefined;
235
+
236
+ // @TODO: add query for flashloanFeeObject
237
+ results[coinName] = {
160
238
  coinName,
161
- symbol: query.utils.parseSymbol(coinName),
162
- lendingPoolAddress: addresses[0],
163
- collateralPoolAddress: addresses[1],
164
- borrowDynamic: addresses[2],
165
- interestModel: addresses[3],
239
+ symbol,
240
+ lendingPoolAddress: addresses[0] ?? '',
241
+ collateralPoolAddress: addresses[1] ?? '',
242
+ borrowDynamic: addresses[2] ?? '',
243
+ interestModel: addresses[3] ?? '',
166
244
  riskModel: addresses[4],
167
- borrowFeeKey: addresses[5],
245
+ borrowFeeKey: addresses[5] ?? '',
168
246
  supplyLimitKey: addresses[6],
169
247
  borrowLimitKey: addresses[7],
170
248
  isolatedAssetKey: addresses[8],
171
- spool,
172
- spoolReward: rewardPool,
173
- sCoinTreasury,
174
- sCoinType,
249
+ ...(spoolData ?? {}),
250
+ ...(sCoinData ?? {}),
175
251
  sCoinName,
176
- sCoinSymbol,
177
252
  coinMetadataId,
178
- coinType: `0x${coinType}`,
179
- sCoinMetadataId,
253
+ coinType,
180
254
  spoolName,
181
255
  decimals,
182
256
  pythFeed,
183
257
  pythFeedObjectId,
258
+ flashloanFeeObject: flashloanFeeObjectIds[coinType] ?? '',
184
259
  };
185
260
 
186
- await new Promise((resolve) => setTimeout(resolve, 500));
261
+ await new Promise((resolve) => setTimeout(resolve, 1000));
187
262
  })
188
263
  );
189
264
 
@@ -1,14 +1,8 @@
1
1
  import BigNumber from 'bignumber.js';
2
- import {
3
- SUPPORT_COLLATERALS,
4
- SUPPORT_POOLS,
5
- SUPPORT_SPOOLS,
6
- } from '../constants';
7
2
  import { minBigNumber, estimatedFactor } from 'src/utils';
8
3
  import type { ScallopQuery } from '../models';
9
4
  import type {
10
5
  Market,
11
- SupportPoolCoins,
12
6
  MarketPool,
13
7
  Spool,
14
8
  StakeAccount,
@@ -16,16 +10,10 @@ import type {
16
10
  Lending,
17
11
  ObligationAccounts,
18
12
  ObligationAccount,
19
- SupportStakeMarketCoins,
20
- SupportCollateralCoins,
21
13
  CoinAmounts,
22
14
  CoinPrices,
23
- SupportMarketCoins,
24
15
  TotalValueLocked,
25
- SupportBorrowIncentiveCoins,
26
16
  ObligationBorrowIcentiveReward,
27
- SupportBorrowIncentiveRewardCoins,
28
- SupportAssetCoins,
29
17
  MarketPools,
30
18
  MarketCollaterals,
31
19
  } from '../types';
@@ -44,7 +32,7 @@ import { normalizeStructTag, SUI_TYPE_ARG } from '@scallop-io/sui-kit';
44
32
  */
45
33
  export const getLendings = async (
46
34
  query: ScallopQuery,
47
- poolCoinNames: SupportPoolCoins[] = [...SUPPORT_POOLS],
35
+ poolCoinNames: string[] = [...query.constants.whitelist.lending],
48
36
  ownerAddress?: string,
49
37
  marketPools?: MarketPools,
50
38
  coinPrices?: CoinPrices,
@@ -54,8 +42,10 @@ export const getLendings = async (
54
42
  query.utils.parseMarketCoinName(poolCoinName)
55
43
  );
56
44
  const stakeMarketCoinNames = marketCoinNames.filter((marketCoinName) =>
57
- (SUPPORT_SPOOLS as readonly SupportMarketCoins[]).includes(marketCoinName)
58
- ) as SupportStakeMarketCoins[];
45
+ ([...query.constants.whitelist.spool] as readonly string[]).includes(
46
+ marketCoinName
47
+ )
48
+ ) as string[];
59
49
 
60
50
  coinPrices = coinPrices ?? (await query.utils.getCoinPrices());
61
51
  marketPools =
@@ -123,7 +113,7 @@ export const getLendings = async (
123
113
  */
124
114
  export const getLending = async (
125
115
  query: ScallopQuery,
126
- poolCoinName: SupportPoolCoins,
116
+ poolCoinName: string,
127
117
  ownerAddress?: string,
128
118
  indexer: boolean = false,
129
119
  marketPool?: MarketPool,
@@ -150,8 +140,10 @@ export const getLending = async (
150
140
 
151
141
  spool =
152
142
  (spool ??
153
- (SUPPORT_SPOOLS as readonly SupportMarketCoins[]).includes(marketCoinName))
154
- ? await query.getSpool(marketCoinName as SupportStakeMarketCoins, {
143
+ ([...query.constants.whitelist.spool] as readonly string[]).includes(
144
+ marketCoinName
145
+ ))
146
+ ? await query.getSpool(marketCoinName as string, {
155
147
  indexer,
156
148
  marketPool,
157
149
  coinPrices: {
@@ -164,11 +156,10 @@ export const getLending = async (
164
156
 
165
157
  stakeAccounts =
166
158
  stakeAccounts ||
167
- (SUPPORT_SPOOLS as readonly SupportMarketCoins[]).includes(marketCoinName)
168
- ? await query.getStakeAccounts(
169
- marketCoinName as SupportStakeMarketCoins,
170
- ownerAddress
171
- )
159
+ ([...query.constants.whitelist.spool] as readonly string[]).includes(
160
+ marketCoinName
161
+ )
162
+ ? await query.getStakeAccounts(marketCoinName as string, ownerAddress)
172
163
  : [];
173
164
  coinAmount =
174
165
  coinAmount || (await query.getCoinAmount(poolCoinName, ownerAddress));
@@ -375,18 +366,15 @@ export const getObligationAccount = async (
375
366
  coinPrices?: CoinPrices,
376
367
  coinAmounts?: CoinAmounts
377
368
  ) => {
378
- const coinNames: SupportAssetCoins[] = Array.from(
379
- new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
380
- );
381
- const collateralAssetCoinNames = [
382
- ...SUPPORT_COLLATERALS,
383
- ] as SupportCollateralCoins[];
384
-
385
369
  market = market ?? (await query.getMarketPools(undefined, { indexer }));
386
370
  coinPrices =
387
371
  coinPrices ?? (await query.getAllCoinPrices({ marketPools: market.pools }));
388
372
  coinAmounts =
389
- coinAmounts ?? (await query.getCoinAmounts(coinNames, ownerAddress));
373
+ coinAmounts ??
374
+ (await query.getCoinAmounts(
375
+ Array.from(query.constants.whitelist.lending),
376
+ ownerAddress
377
+ ));
390
378
 
391
379
  const [obligationQuery, borrowIncentivePools, borrowIncentiveAccounts] =
392
380
  await Promise.all([
@@ -410,12 +398,13 @@ export const getObligationAccount = async (
410
398
  let totalBorrowedValue = BigNumber(0);
411
399
  let totalBorrowedValueWithWeight = BigNumber(0);
412
400
 
413
- for (const assetCoinName of collateralAssetCoinNames) {
401
+ for (const assetCoinName of Array.from(
402
+ query.constants.whitelist.collateral
403
+ )) {
414
404
  const collateral = obligationQuery?.collaterals.find((collateral) => {
415
- const collateralCoinName =
416
- query.utils.parseCoinNameFromType<SupportCollateralCoins>(
417
- collateral.type.name
418
- );
405
+ const collateralCoinName = query.utils.parseCoinNameFromType(
406
+ collateral.type.name
407
+ );
419
408
  return assetCoinName === collateralCoinName;
420
409
  });
421
410
 
@@ -474,15 +463,17 @@ export const getObligationAccount = async (
474
463
  }
475
464
  }
476
465
 
477
- const borrowAssetCoinNames: SupportPoolCoins[] = [
478
- ...new Set([...Object.values(market.pools).map((pool) => pool.coinName)]),
466
+ const borrowAssetCoinNames: string[] = [
467
+ ...new Set([
468
+ ...Object.values(market.pools)
469
+ .filter((t) => !!t)
470
+ .map((pool) => pool.coinName),
471
+ ]),
479
472
  ];
480
473
 
481
474
  for (const assetCoinName of borrowAssetCoinNames) {
482
475
  const debt = obligationQuery?.debts.find((debt) => {
483
- const poolCoinName = query.utils.parseCoinNameFromType<SupportPoolCoins>(
484
- debt.type.name
485
- );
476
+ const poolCoinName = query.utils.parseCoinNameFromType(debt.type.name);
486
477
  return assetCoinName === poolCoinName;
487
478
  });
488
479
 
@@ -546,7 +537,9 @@ export const getObligationAccount = async (
546
537
  for (const [poolCoinName, borrowIncentiveAccount] of Object.entries(
547
538
  borrowIncentiveAccounts
548
539
  )) {
549
- const coinName = poolCoinName as SupportBorrowIncentiveCoins;
540
+ if (!borrowIncentiveAccount) continue;
541
+
542
+ const coinName = poolCoinName as string;
550
543
  const borrowIncentivePool = borrowIncentivePools[coinName];
551
544
  if (borrowIncentivePool) {
552
545
  const rewards: ObligationBorrowIcentiveReward[] = [];
@@ -599,11 +592,6 @@ export const getObligationAccount = async (
599
592
  .toNumber()
600
593
  : 1;
601
594
 
602
- // console.log({
603
- // availableClaimAmount: availableClaimAmount.toString(),
604
- // coinName: poolPoint.coinName,
605
- // coinType: poolPoint.coinType,
606
- // });
607
595
  if (availableClaimAmount.isGreaterThanOrEqualTo(0)) {
608
596
  rewards.push({
609
597
  coinName: poolPoint.coinName,
@@ -623,9 +611,7 @@ export const getObligationAccount = async (
623
611
  if (
624
612
  Object.keys(borrowIncentivePool.points).some((coinName: any) => {
625
613
  const rewardApr =
626
- borrowIncentivePool.points[
627
- coinName as SupportBorrowIncentiveRewardCoins
628
- ]?.rewardApr;
614
+ borrowIncentivePool.points[coinName as string]?.rewardApr;
629
615
  return (
630
616
  rewardApr !== Infinity &&
631
617
  typeof rewardApr == 'number' &&
@@ -706,8 +692,8 @@ export const getObligationAccount = async (
706
692
  for (const [collateralCoinName, obligationCollateral] of Object.entries(
707
693
  obligationAccount.collaterals
708
694
  )) {
709
- const marketCollateral =
710
- market.collaterals[collateralCoinName as SupportCollateralCoins];
695
+ if (!obligationCollateral) continue;
696
+ const marketCollateral = market.collaterals[collateralCoinName as string];
711
697
  if (marketCollateral) {
712
698
  let estimatedAvailableWithdrawAmount = BigNumber(
713
699
  obligationAccount.totalAvailableCollateralValue
@@ -746,7 +732,8 @@ export const getObligationAccount = async (
746
732
  for (const [poolCoinName, obligationDebt] of Object.entries(
747
733
  obligationAccount.debts
748
734
  )) {
749
- const marketPool = market.pools[poolCoinName as SupportPoolCoins];
735
+ if (!obligationDebt) continue;
736
+ const marketPool = market.pools[poolCoinName as string];
750
737
  if (marketPool) {
751
738
  const estimatedRequiredRepayAmount = BigNumber(
752
739
  obligationDebt.requiredRepayAmount
@@ -836,6 +823,7 @@ export const getTotalValueLocked = async (
836
823
  }
837
824
 
838
825
  for (const pool of Object.values(market.pools)) {
826
+ if (!pool) continue;
839
827
  supplyLendingValue = supplyLendingValue.plus(
840
828
  BigNumber(pool.supplyCoin).multipliedBy(pool.coinPrice)
841
829
  );
@@ -846,6 +834,7 @@ export const getTotalValueLocked = async (
846
834
 
847
835
  // console.dir(market.collaterals, { depth: null });
848
836
  for (const collateral of Object.values(market.collaterals)) {
837
+ if (!collateral) continue;
849
838
  supplyCollateralValue = supplyCollateralValue.plus(
850
839
  BigNumber(collateral.depositCoin).multipliedBy(collateral.coinPrice)
851
840
  );
@@ -897,7 +886,9 @@ export const getUserPortfolio = async (
897
886
 
898
887
  // get pending rewards (spool and borrow incentive)
899
888
  const parsedLendings = Object.values(lendings)
900
- .filter((t) => t.availableWithdrawCoin > 0)
889
+ .filter(
890
+ (t): t is NonNullable<typeof t> => !!t && t.availableWithdrawCoin > 0
891
+ )
901
892
  .map((lending) => ({
902
893
  suppliedCoin: lending.availableWithdrawCoin,
903
894
  suppliedValue: lending.suppliedValue,
@@ -928,7 +919,10 @@ export const getUserPortfolio = async (
928
919
  totalUnhealthyCollateralInUsd:
929
920
  obligationAccount.totalUnhealthyCollateralValue,
930
921
  borrowedPools: Object.values(obligationAccount.debts)
931
- .filter((debt) => debt.borrowedCoin > 0)
922
+ .filter(
923
+ (debt): debt is NonNullable<typeof debt> =>
924
+ !!debt && debt.borrowedCoin > 0
925
+ )
932
926
  .map((debt) => ({
933
927
  coinName: debt.coinName,
934
928
  symbol: debt.symbol,
@@ -942,7 +936,9 @@ export const getUserPortfolio = async (
942
936
  incentiveInfos: Object.values(
943
937
  borrowIncentivePools[debt.coinName]?.points ?? {}
944
938
  )
945
- .filter((t) => isFinite(t.rewardApr))
939
+ .filter(
940
+ (t): t is NonNullable<typeof t> => !!t && isFinite(t.rewardApr)
941
+ )
946
942
  .map((t) => ({
947
943
  coinName: t.coinName,
948
944
  symbol: t.symbol,
@@ -955,16 +951,18 @@ export const getUserPortfolio = async (
955
951
 
956
952
  const pendingLendingRewards = Object.values(lendings).reduce(
957
953
  (acc, reward) => {
958
- if (reward.availableClaimCoin === 0) return acc;
959
- if (!acc[reward.symbol]) {
960
- acc[reward.symbol] = {
961
- symbol: reward.symbol,
962
- coinType: normalizeStructTag(SUI_TYPE_ARG), // @TODO: for now lending reward is all in SUI
963
- coinPrice: reward.coinPrice,
964
- pendingRewardInCoin: reward.availableClaimCoin,
965
- };
966
- } else {
967
- acc[reward.symbol].pendingRewardInCoin += reward.availableClaimCoin;
954
+ if (reward) {
955
+ if (reward.availableClaimCoin === 0) return acc;
956
+ if (!acc[reward.symbol]) {
957
+ acc[reward.symbol] = {
958
+ symbol: reward.symbol,
959
+ coinType: normalizeStructTag(SUI_TYPE_ARG), // @TODO: for now lending reward is all in SUI
960
+ coinPrice: reward.coinPrice,
961
+ pendingRewardInCoin: reward.availableClaimCoin,
962
+ };
963
+ } else {
964
+ acc[reward.symbol].pendingRewardInCoin += reward.availableClaimCoin;
965
+ }
968
966
  }
969
967
  return acc;
970
968
  },
@@ -984,7 +982,7 @@ export const getUserPortfolio = async (
984
982
  .reduce(
985
983
  (acc, curr) => {
986
984
  Object.values(curr.borrowIncentives).forEach((incentive) => {
987
- incentive.rewards.forEach((reward) => {
985
+ incentive?.rewards.forEach((reward) => {
988
986
  if (reward.availableClaimCoin === 0) return acc;
989
987
  if (!acc[reward.coinName]) {
990
988
  acc[reward.coinName] = {