@scallop-io/sui-scallop-sdk 0.46.53 → 0.46.54

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.
@@ -73,10 +73,11 @@ export const queryBorrowIncentivePools = async (
73
73
  const queryTarget = `${queryPkgId}::incentive_pools_query::incentive_pools_data`;
74
74
  const args = [incentivePoolsId];
75
75
  const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
76
- const borrowIncentivePoolsQueryData = queryResult.events[0]
77
- .parsedJson as BorrowIncentivePoolsQueryInterface;
76
+ const borrowIncentivePoolsQueryData = queryResult?.events[0].parsedJson as
77
+ | BorrowIncentivePoolsQueryInterface
78
+ | undefined;
78
79
 
79
- for (const pool of borrowIncentivePoolsQueryData.incentive_pools) {
80
+ for (const pool of borrowIncentivePoolsQueryData?.incentive_pools ?? []) {
80
81
  const borrowIncentivePoolPoints: OptionalKeys<
81
82
  Record<SupportBorrowIncentiveRewardCoins, BorrowIncentivePoolPoints>
82
83
  > = {};
@@ -177,11 +178,12 @@ export const queryBorrowIncentiveAccounts = async (
177
178
  const args = [incentiveAccountsId, obligationId];
178
179
 
179
180
  const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
180
- const borrowIncentiveAccountsQueryData = queryResult.events[0]
181
- .parsedJson as BorrowIncentiveAccountsQueryInterface;
181
+ const borrowIncentiveAccountsQueryData = queryResult?.events[0].parsedJson as
182
+ | BorrowIncentiveAccountsQueryInterface
183
+ | undefined;
182
184
 
183
185
  const borrowIncentiveAccounts: BorrowIncentiveAccounts = Object.values(
184
- borrowIncentiveAccountsQueryData.pool_records
186
+ borrowIncentiveAccountsQueryData?.pool_records ?? []
185
187
  ).reduce((accounts, accountData) => {
186
188
  const parsedBorrowIncentiveAccount =
187
189
  parseOriginBorrowIncentiveAccountData(accountData);
@@ -224,7 +226,7 @@ export const getBindedObligationId = async (
224
226
  }
225
227
  );
226
228
 
227
- if (incentivePoolsResponse.data?.content?.dataType !== 'moveObject')
229
+ if (incentivePoolsResponse?.data?.content?.dataType !== 'moveObject')
228
230
  return null;
229
231
  const incentivePoolFields = incentivePoolsResponse.data.content.fields as any;
230
232
  const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id
@@ -240,7 +242,7 @@ export const getBindedObligationId = async (
240
242
  },
241
243
  });
242
244
 
243
- if (veScaBindTableResponse.data?.content?.dataType !== 'moveObject')
245
+ if (veScaBindTableResponse?.data?.content?.dataType !== 'moveObject')
244
246
  return null;
245
247
  const veScaBindTableFields = veScaBindTableResponse.data.content
246
248
  .fields as any;
@@ -267,7 +269,7 @@ export const getBindedVeScaKey = async (
267
269
  showContent: true,
268
270
  }
269
271
  );
270
- if (incentiveAccountsObject.data?.content?.dataType !== 'moveObject')
272
+ if (incentiveAccountsObject?.data?.content?.dataType !== 'moveObject')
271
273
  return null;
272
274
  const incentiveAccountsTableId = (
273
275
  incentiveAccountsObject.data.content.fields as any
@@ -282,7 +284,7 @@ export const getBindedVeScaKey = async (
282
284
  },
283
285
  });
284
286
 
285
- if (bindedIncentiveAcc.data?.content?.dataType !== 'moveObject') return null;
287
+ if (bindedIncentiveAcc?.data?.content?.dataType !== 'moveObject') return null;
286
288
  const bindedIncentiveAccFields = bindedIncentiveAcc.data.content
287
289
  .fields as any;
288
290
 
@@ -82,9 +82,11 @@ export const queryMarket = async (
82
82
  const args = [marketId];
83
83
 
84
84
  const queryResult = await query.cache.queryInspectTxn({ queryTarget, args });
85
- const marketData = queryResult.events[0].parsedJson as MarketQueryInterface;
85
+ const marketData = queryResult?.events[0].parsedJson as
86
+ | MarketQueryInterface
87
+ | undefined;
86
88
 
87
- for (const pool of marketData.pools) {
89
+ for (const pool of marketData?.pools ?? []) {
88
90
  const coinType = normalizeStructTag(pool.type.name);
89
91
  const poolCoinName =
90
92
  query.utils.parseCoinNameFromType<SupportPoolCoins>(coinType);
@@ -141,7 +143,7 @@ export const queryMarket = async (
141
143
  };
142
144
  }
143
145
 
144
- for (const collateral of marketData.collaterals) {
146
+ for (const collateral of marketData?.collaterals ?? []) {
145
147
  const coinType = normalizeStructTag(collateral.type.name);
146
148
  const collateralCoinName =
147
149
  query.utils.parseCoinNameFromType<SupportCollateralCoins>(coinType);
@@ -240,7 +242,7 @@ export const getMarketPools = async (
240
242
  query,
241
243
  poolCoinName,
242
244
  indexer,
243
- marketObjectResponse.data,
245
+ marketObjectResponse?.data,
244
246
  coinPrices?.[poolCoinName]
245
247
  );
246
248
 
@@ -293,7 +295,7 @@ export const getMarketPool = async (
293
295
  await query.cache.queryGetObject(marketId, {
294
296
  showContent: true,
295
297
  })
296
- ).data;
298
+ )?.data;
297
299
 
298
300
  coinPrice =
299
301
  coinPrice ||
@@ -317,6 +319,8 @@ export const getMarketPool = async (
317
319
  },
318
320
  },
319
321
  });
322
+ if (!balanceSheetDynamicFieldObjectResponse) return undefined;
323
+
320
324
  const balanceSheetDynamicFieldObject =
321
325
  balanceSheetDynamicFieldObjectResponse.data;
322
326
  if (
@@ -342,6 +346,8 @@ export const getMarketPool = async (
342
346
  },
343
347
  },
344
348
  });
349
+ if (!borrowIndexDynamicFieldObjectResponse) return undefined;
350
+
345
351
  const borrowIndexDynamicFieldObject =
346
352
  borrowIndexDynamicFieldObjectResponse.data;
347
353
  if (
@@ -367,6 +373,8 @@ export const getMarketPool = async (
367
373
  },
368
374
  },
369
375
  });
376
+
377
+ if (!interestModelDynamicFieldObjectResponse) return undefined;
370
378
  const interestModelDynamicFieldObject =
371
379
  interestModelDynamicFieldObjectResponse.data;
372
380
  if (
@@ -393,6 +401,7 @@ export const getMarketPool = async (
393
401
  },
394
402
  });
395
403
 
404
+ if (!borrowFeeDynamicFieldObjectResponse) return undefined;
396
405
  const borrowFeeDynamicFieldObject =
397
406
  borrowFeeDynamicFieldObjectResponse.data;
398
407
  if (
@@ -508,7 +517,7 @@ export const getMarketCollaterals = async (
508
517
  query,
509
518
  collateralCoinName,
510
519
  indexer,
511
- marketObjectResponse.data,
520
+ marketObjectResponse?.data,
512
521
  coinPrices?.[collateralCoinName]
513
522
  );
514
523
 
@@ -561,7 +570,7 @@ export const getMarketCollateral = async (
561
570
  await query.cache.queryGetObject(marketId, {
562
571
  showContent: true,
563
572
  })
564
- ).data;
573
+ )?.data;
565
574
 
566
575
  coinPrice =
567
576
  coinPrice ||
@@ -586,6 +595,8 @@ export const getMarketCollateral = async (
586
595
  },
587
596
  },
588
597
  });
598
+
599
+ if (!riskModelDynamicFieldObjectResponse) return undefined;
589
600
  const riskModelDynamicFieldObject =
590
601
  riskModelDynamicFieldObjectResponse.data;
591
602
  if (
@@ -610,6 +621,8 @@ export const getMarketCollateral = async (
610
621
  },
611
622
  },
612
623
  });
624
+
625
+ if (!collateralStatDynamicFieldObjectResponse) return undefined;
613
626
  const collateralStatDynamicFieldObject =
614
627
  collateralStatDynamicFieldObjectResponse.data;
615
628
  if (
@@ -687,6 +700,7 @@ export const getObligations = async (
687
700
  },
688
701
  cursor: nextCursor,
689
702
  });
703
+ if (!paginatedKeyObjectsResponse) continue;
690
704
 
691
705
  keyObjectsResponse.push(...paginatedKeyObjectsResponse.data);
692
706
  if (
@@ -738,7 +752,7 @@ export const getObligationLocked = async (
738
752
  );
739
753
  let obligationLocked = false;
740
754
  if (
741
- obligationObjectResponse.data &&
755
+ obligationObjectResponse?.data &&
742
756
  obligationObjectResponse?.data?.content?.dataType === 'moveObject' &&
743
757
  'lock_key' in obligationObjectResponse.data.content.fields
744
758
  ) {
@@ -774,7 +788,9 @@ export const queryObligation = async (
774
788
  { queryTarget, args }
775
789
  // txBlock
776
790
  );
777
- return queryResult.events[0].parsedJson as ObligationQueryInterface;
791
+ return queryResult?.events[0].parsedJson as
792
+ | ObligationQueryInterface
793
+ | undefined;
778
794
  };
779
795
 
780
796
  /**
@@ -929,7 +945,7 @@ export const getFlashLoanFees = async (
929
945
  const marketObjectRes = await query.cache.queryGetObject(marketObjectId, {
930
946
  showContent: true,
931
947
  });
932
- if (marketObjectRes.data?.content?.dataType !== 'moveObject')
948
+ if (marketObjectRes?.data?.content?.dataType !== 'moveObject')
933
949
  throw new Error('Failed to get market object');
934
950
 
935
951
  // get vault
@@ -946,12 +962,13 @@ export const getFlashLoanFees = async (
946
962
  });
947
963
 
948
964
  // get the dynamic object ids
949
- const dynamicFieldObjectIds = balanceSheetDynamicFields.data
950
- .filter((field) => {
951
- const assetType = (field.name.value as any).name as string;
952
- return !!assetTypeMap[assetType];
953
- })
954
- .map((field) => field.objectId);
965
+ const dynamicFieldObjectIds =
966
+ balanceSheetDynamicFields?.data
967
+ .filter((field) => {
968
+ const assetType = (field.name.value as any).name as string;
969
+ return !!assetTypeMap[assetType];
970
+ })
971
+ .map((field) => field.objectId) ?? [];
955
972
 
956
973
  flashloanFeeObjects.push(
957
974
  ...(await query.cache.queryGetObjects(dynamicFieldObjectIds, {
@@ -40,7 +40,7 @@ export const getLoyaltyProgramInformations = async (
40
40
  showContent: true,
41
41
  });
42
42
 
43
- if (rewardPoolObject.data?.content?.dataType !== 'moveObject') return null;
43
+ if (rewardPoolObject?.data?.content?.dataType !== 'moveObject') return null;
44
44
  const rewardPoolFields = rewardPoolObject.data.content.fields;
45
45
  const { isClaimEnabled, totalPoolReward } = rewardPoolFieldsZod.parse(
46
46
  rewardPoolFields
@@ -68,7 +68,7 @@ export const getLoyaltyProgramInformations = async (
68
68
  },
69
69
  });
70
70
 
71
- if (userRewardObject.data?.content?.dataType !== 'moveObject') return result;
71
+ if (userRewardObject?.data?.content?.dataType !== 'moveObject') return result;
72
72
  const userRewardFields = userRewardObject.data.content.fields;
73
73
  result.pendingReward = userRewardFieldsZod.parse(
74
74
  userRewardFields
@@ -362,7 +362,7 @@ export const getObligationAccount = async (
362
362
  let totalBorrowedValueWithWeight = BigNumber(0);
363
363
 
364
364
  for (const assetCoinName of collateralAssetCoinNames) {
365
- const collateral = obligationQuery.collaterals.find((collateral) => {
365
+ const collateral = obligationQuery?.collaterals.find((collateral) => {
366
366
  const collateralCoinName =
367
367
  query.utils.parseCoinNameFromType<SupportCollateralCoins>(
368
368
  collateral.type.name
@@ -432,7 +432,7 @@ export const getObligationAccount = async (
432
432
  ];
433
433
 
434
434
  for (const assetCoinName of borrowAssetCoinNames) {
435
- const debt = obligationQuery.debts.find((debt) => {
435
+ const debt = obligationQuery?.debts.find((debt) => {
436
436
  const poolCoinName = query.utils.parseCoinNameFromType<SupportPoolCoins>(
437
437
  debt.type.name
438
438
  );
@@ -20,7 +20,7 @@ export const getPythPrice = async (
20
20
  priceFeedObject =
21
21
  priceFeedObject ||
22
22
  (await query.cache.queryGetObject(pythFeedObjectId, { showContent: true }))
23
- .data;
23
+ ?.data;
24
24
 
25
25
  if (priceFeedObject) {
26
26
  const priceFeedPoolObject = priceFeedObject;
@@ -19,7 +19,7 @@ export const queryVeScaKeyIdFromReferralBindings = async (
19
19
  },
20
20
  });
21
21
 
22
- if (referralBindResponse.data?.content?.dataType !== 'moveObject')
22
+ if (referralBindResponse?.data?.content?.dataType !== 'moveObject')
23
23
  return null;
24
24
 
25
25
  const fields = referralBindResponse.data.content.fields as any;
@@ -28,7 +28,7 @@ export const getSCoinTotalSupply = async (
28
28
  args,
29
29
  typeArgs,
30
30
  });
31
- const results = queryResults.results;
31
+ const results = queryResults?.results;
32
32
  if (results && results[0].returnValues) {
33
33
  const value = Uint8Array.from(results[0].returnValues[0][0]);
34
34
  const type = results[0].returnValues[0][1]; // should be u64
@@ -251,6 +251,8 @@ export const getStakeAccounts = async (
251
251
  },
252
252
  cursor: nextCursor,
253
253
  });
254
+ if (!paginatedStakeObjectsResponse) continue;
255
+
254
256
  stakeObjectsResponse.push(...paginatedStakeObjectsResponse.data);
255
257
  if (
256
258
  paginatedStakeObjectsResponse.hasNextPage &&
@@ -420,7 +422,7 @@ export const getStakePool = async (
420
422
  showContent: true,
421
423
  showType: true,
422
424
  });
423
- if (stakePoolObjectResponse.data) {
425
+ if (stakePoolObjectResponse?.data) {
424
426
  const stakePoolObject = stakePoolObjectResponse.data;
425
427
  const id = stakePoolObject.objectId;
426
428
  const type = stakePoolObject.type!;
@@ -482,7 +484,7 @@ export const getStakeRewardPool = async (
482
484
  }
483
485
  );
484
486
 
485
- if (stakeRewardPoolObjectResponse.data) {
487
+ if (stakeRewardPoolObjectResponse?.data) {
486
488
  const stakeRewardPoolObject = stakeRewardPoolObjectResponse.data;
487
489
  const id = stakeRewardPoolObject.objectId;
488
490
  const type = stakeRewardPoolObject.type!;
@@ -35,8 +35,11 @@ export const getVescaKeys = async (
35
35
  },
36
36
  cursor: nextCursor,
37
37
  });
38
+ if (!paginatedKeyObjectsResponse) continue;
39
+
38
40
  keyObjectsResponse.push(...paginatedKeyObjectsResponse.data);
39
41
  if (
42
+ paginatedKeyObjectsResponse &&
40
43
  paginatedKeyObjectsResponse.hasNextPage &&
41
44
  paginatedKeyObjectsResponse.nextCursor
42
45
  ) {
@@ -115,6 +118,8 @@ export const getVeSca = async (
115
118
  value: typeof veScaKey === 'string' ? veScaKey : veScaKey.objectId,
116
119
  },
117
120
  });
121
+ if (!veScaDynamicFieldObjectResponse) return undefined;
122
+
118
123
  const veScaDynamicFieldObject = veScaDynamicFieldObjectResponse.data;
119
124
  if (
120
125
  veScaDynamicFieldObject &&
@@ -177,7 +182,7 @@ const getTotalVeScaTreasuryAmount = async (
177
182
  refreshArgs.map(async (arg) => {
178
183
  if (typeof arg === 'string') {
179
184
  return (await query.cache.queryGetObject(arg, { showContent: true }))
180
- .data;
185
+ ?.data;
181
186
  }
182
187
  return arg;
183
188
  })
@@ -187,7 +192,7 @@ const getTotalVeScaTreasuryAmount = async (
187
192
  veScaAmountArgs.map(async (arg) => {
188
193
  if (typeof arg === 'string') {
189
194
  return (await query.cache.queryGetObject(arg, { showContent: true }))
190
- .data;
195
+ ?.data;
191
196
  }
192
197
  return arg;
193
198
  })
@@ -201,7 +206,7 @@ const getTotalVeScaTreasuryAmount = async (
201
206
  const txBytes = await txb.txBlock.build({
202
207
  client: query.suiKit.client(),
203
208
  onlyTransactionKind: true,
204
- protocolConfig: await query.cache.getProtocolConfig(),
209
+ protocolConfig: (await query.cache.getProtocolConfig()) ?? undefined,
205
210
  });
206
211
 
207
212
  // return result
@@ -1,3 +1,4 @@
1
1
  export * from './builder';
2
2
  export * from './query';
3
3
  export * from './util';
4
+ export * from './tokenBucket';
@@ -0,0 +1,63 @@
1
+ import { DEFAULT_INTERVAL_IN_MS } from 'src/constants/tokenBucket';
2
+
3
+ class TokenBucket {
4
+ private tokensPerInterval: number;
5
+ private interval: number;
6
+ private tokens: number;
7
+ private lastRefill: number;
8
+
9
+ constructor(tokensPerInterval: number, intervalInMs: number) {
10
+ this.tokensPerInterval = tokensPerInterval;
11
+ this.interval = intervalInMs;
12
+ this.tokens = tokensPerInterval;
13
+ this.lastRefill = Date.now();
14
+ }
15
+
16
+ refill() {
17
+ const now = Date.now();
18
+ const elapsed = now - this.lastRefill;
19
+ if (elapsed > this.interval) {
20
+ const tokensToAdd =
21
+ Math.floor(elapsed / this.interval) * this.tokensPerInterval;
22
+ this.tokens = Math.min(this.tokens + tokensToAdd, this.tokensPerInterval);
23
+ this.lastRefill = now;
24
+ }
25
+ }
26
+
27
+ removeTokens(count: number) {
28
+ this.refill();
29
+ if (this.tokens >= count) {
30
+ this.tokens -= count;
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ }
36
+
37
+ const callWithRateLimit = async <T>(
38
+ tokenBucket: TokenBucket,
39
+ fn: () => Promise<T>,
40
+ retryDelayInMs = DEFAULT_INTERVAL_IN_MS,
41
+ maxRetries = 5 // Adding a maximum retries limit,
42
+ ): Promise<T | null> => {
43
+ let retries = 0;
44
+
45
+ const tryRequest = async (): Promise<T | null> => {
46
+ if (tokenBucket.removeTokens(1)) {
47
+ return await fn();
48
+ } else if (retries < maxRetries) {
49
+ retries++;
50
+ // Use a Promise to correctly handle the async operation with setTimeout
51
+ await new Promise((resolve) => setTimeout(resolve, retryDelayInMs));
52
+ return tryRequest();
53
+ } else {
54
+ // Optionally, handle the case where the maximum number of retries is reached
55
+ console.error('Maximum retries reached');
56
+ return null;
57
+ }
58
+ };
59
+
60
+ return tryRequest();
61
+ };
62
+
63
+ export { TokenBucket, callWithRateLimit };