@scallop-io/sui-scallop-sdk 0.46.53 → 0.46.55
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.
- package/dist/constants/tokenBucket.d.ts +2 -0
- package/dist/index.js +1982 -1888
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1933 -1839
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallop.d.ts +2 -1
- package/dist/models/scallopCache.d.ts +11 -8
- package/dist/models/scallopClient.d.ts +2 -2
- package/dist/models/scallopQuery.d.ts +1 -1
- package/dist/models/scallopUtils.d.ts +9 -1
- package/dist/queries/coreQuery.d.ts +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/tokenBucket.d.ts +11 -0
- package/package.json +1 -1
- package/src/builders/loyaltyProgramBuilder.ts +8 -18
- package/src/builders/spoolBuilder.ts +1 -33
- package/src/constants/tokenBucket.ts +2 -0
- package/src/models/scallop.ts +13 -2
- package/src/models/scallopCache.ts +55 -25
- package/src/models/scallopClient.ts +28 -13
- package/src/models/scallopUtils.ts +42 -10
- package/src/queries/borrowIncentiveQuery.ts +12 -10
- package/src/queries/coreQuery.ts +33 -16
- package/src/queries/loyaltyProgramQuery.ts +2 -2
- package/src/queries/portfolioQuery.ts +2 -2
- package/src/queries/priceQuery.ts +1 -1
- package/src/queries/referralQuery.ts +1 -1
- package/src/queries/sCoinQuery.ts +1 -1
- package/src/queries/spoolQuery.ts +4 -2
- package/src/queries/vescaQuery.ts +8 -3
- package/src/utils/index.ts +1 -0
- package/src/utils/tokenBucket.ts +63 -0
|
@@ -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
|
|
77
|
-
|
|
76
|
+
const borrowIncentivePoolsQueryData = queryResult?.events[0].parsedJson as
|
|
77
|
+
| BorrowIncentivePoolsQueryInterface
|
|
78
|
+
| undefined;
|
|
78
79
|
|
|
79
|
-
for (const pool of borrowIncentivePoolsQueryData
|
|
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
|
|
181
|
-
|
|
181
|
+
const borrowIncentiveAccountsQueryData = queryResult?.events[0].parsedJson as
|
|
182
|
+
| BorrowIncentiveAccountsQueryInterface
|
|
183
|
+
| undefined;
|
|
182
184
|
|
|
183
185
|
const borrowIncentiveAccounts: BorrowIncentiveAccounts = Object.values(
|
|
184
|
-
borrowIncentiveAccountsQueryData
|
|
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
|
|
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
|
|
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
|
|
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
|
|
287
|
+
if (bindedIncentiveAcc?.data?.content?.dataType !== 'moveObject') return null;
|
|
286
288
|
const bindedIncentiveAccFields = bindedIncentiveAcc.data.content
|
|
287
289
|
.fields as any;
|
|
288
290
|
|
package/src/queries/coreQuery.ts
CHANGED
|
@@ -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
|
|
85
|
+
const marketData = queryResult?.events[0].parsedJson as
|
|
86
|
+
| MarketQueryInterface
|
|
87
|
+
| undefined;
|
|
86
88
|
|
|
87
|
-
for (const pool of marketData
|
|
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
|
|
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
|
|
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
|
-
)
|
|
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
|
|
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
|
-
)
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
435
|
+
const debt = obligationQuery?.debts.find((debt) => {
|
|
436
436
|
const poolCoinName = query.utils.parseCoinNameFromType<SupportPoolCoins>(
|
|
437
437
|
debt.type.name
|
|
438
438
|
);
|
|
@@ -19,7 +19,7 @@ export const queryVeScaKeyIdFromReferralBindings = async (
|
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
if (referralBindResponse
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/src/utils/index.ts
CHANGED
|
@@ -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 };
|