@scallop-io/sui-scallop-sdk 1.4.1 → 1.4.12
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 -2
- package/dist/index.js +72 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +72 -31
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallopQuery.d.ts +1 -1
- package/package.json +1 -1
- package/src/constants/testAddress.ts +42 -0
- package/src/constants/tokenBucket.ts +2 -2
- package/src/models/scallopCache.ts +36 -15
- package/src/models/scallopQuery.ts +1 -1
- package/src/models/scallopUtils.ts +1 -1
- package/src/queries/borrowLimitQuery.ts +1 -0
- package/src/queries/portfolioQuery.ts +9 -4
- package/src/utils/query.ts +5 -1
- package/src/utils/tokenBucket.ts +8 -28
|
@@ -306,7 +306,7 @@ export declare class ScallopQuery {
|
|
|
306
306
|
* @return Borrow incentive pools data.
|
|
307
307
|
*/
|
|
308
308
|
getBorrowIncentivePools(coinNames?: SupportBorrowIncentiveCoins[], args?: {
|
|
309
|
-
coinPrices
|
|
309
|
+
coinPrices?: CoinPrices;
|
|
310
310
|
indexer?: boolean;
|
|
311
311
|
marketPools?: MarketPools;
|
|
312
312
|
}): Promise<{
|
package/package.json
CHANGED
|
@@ -236,6 +236,36 @@ export const TEST_ADDRESSES: AddressesInterface = {
|
|
|
236
236
|
},
|
|
237
237
|
},
|
|
238
238
|
},
|
|
239
|
+
deep: {
|
|
240
|
+
id: '0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270',
|
|
241
|
+
metaData:
|
|
242
|
+
'0x6e60b051a08fa836f5a7acd7c464c8d9825bc29c44657fe170fe9b8e1e4770c0',
|
|
243
|
+
treasury: '',
|
|
244
|
+
oracle: {
|
|
245
|
+
supra: '',
|
|
246
|
+
switchboard: '',
|
|
247
|
+
pyth: {
|
|
248
|
+
feed: '29bdd5248234e33bd93d3b81100b5fa32eaa5997843847e2c2cb16d7c6d9f7ff',
|
|
249
|
+
feedObject:
|
|
250
|
+
'0x8c7f3a322b94cc69db2a2ac575cbd94bf5766113324c3a3eceac91e3e88a51ed',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
fud: {
|
|
255
|
+
id: '0x76cb819b01abed502bee8a702b4c2d547532c12f25001c9dea795a5e631c26f1',
|
|
256
|
+
metaData:
|
|
257
|
+
'0x01087411ef48aaac1eb6e24803213e3a60a03b147dac930e5e341f17a85e524e',
|
|
258
|
+
treasury: '',
|
|
259
|
+
oracle: {
|
|
260
|
+
supra: '',
|
|
261
|
+
switchboard: '',
|
|
262
|
+
pyth: {
|
|
263
|
+
feed: '6a4090703da959247727f2b490eb21aea95c8684ecfac675f432008830890c75',
|
|
264
|
+
feedObject:
|
|
265
|
+
'0x4531c3ed0d22f21f5fce882905372006c9aafa30f01db03b789e95a6c50de7b2',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
239
269
|
},
|
|
240
270
|
oracles: {
|
|
241
271
|
xOracle:
|
|
@@ -513,6 +543,18 @@ export const TEST_ADDRESSES: AddressesInterface = {
|
|
|
513
543
|
treasury:
|
|
514
544
|
'0xfd0f02def6358a1f266acfa1493d4707ee8387460d434fb667d63d755ff907ed',
|
|
515
545
|
},
|
|
546
|
+
sdeep: {
|
|
547
|
+
coinType:
|
|
548
|
+
'0xeb7a05a3224837c5e5503575aed0be73c091d1ce5e43aa3c3e716e0ae614608f::scallop_deep::SCALLOP_DEEP',
|
|
549
|
+
treasury:
|
|
550
|
+
'0xc63838fabe37b25ad897392d89876d920f5e0c6a406bf3abcb84753d2829bc88',
|
|
551
|
+
},
|
|
552
|
+
sfud: {
|
|
553
|
+
coinType:
|
|
554
|
+
'0xe56d5167f427cbe597da9e8150ef5c337839aaf46891d62468dcf80bdd8e10d1::scallop_fud::SCALLOP_FUD',
|
|
555
|
+
treasury:
|
|
556
|
+
'0xf25212f11d182decff7a86165699a73e3d5787aced203ca539f43cfbc10db867',
|
|
557
|
+
},
|
|
516
558
|
},
|
|
517
559
|
},
|
|
518
560
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const DEFAULT_TOKENS_PER_INTERVAL =
|
|
2
|
-
export const DEFAULT_INTERVAL_IN_MS =
|
|
1
|
+
export const DEFAULT_TOKENS_PER_INTERVAL = 10;
|
|
2
|
+
export const DEFAULT_INTERVAL_IN_MS = 50;
|
|
@@ -122,10 +122,13 @@ export class ScallopCache {
|
|
|
122
122
|
txBlock.moveCall(queryTarget, args, typeArgs);
|
|
123
123
|
|
|
124
124
|
const query = await this.queryClient.fetchQuery({
|
|
125
|
+
retry: 5,
|
|
126
|
+
retryDelay: 1000,
|
|
125
127
|
queryKey: queryKeys.rpc.getInspectTxn(queryTarget, args, typeArgs),
|
|
126
128
|
queryFn: async () => {
|
|
127
|
-
return await callWithRateLimit(
|
|
128
|
-
this.
|
|
129
|
+
return await callWithRateLimit(
|
|
130
|
+
this.tokenBucket,
|
|
131
|
+
async () => await this.suiKit.inspectTxn(txBlock)
|
|
129
132
|
);
|
|
130
133
|
},
|
|
131
134
|
});
|
|
@@ -143,13 +146,17 @@ export class ScallopCache {
|
|
|
143
146
|
options?: SuiObjectDataOptions
|
|
144
147
|
): Promise<SuiObjectResponse | null> {
|
|
145
148
|
return this.queryClient.fetchQuery({
|
|
149
|
+
retry: 5,
|
|
150
|
+
retryDelay: 1000,
|
|
146
151
|
queryKey: queryKeys.rpc.getObject(objectId, this.walletAddress, options),
|
|
147
152
|
queryFn: async () => {
|
|
148
|
-
return await callWithRateLimit(
|
|
149
|
-
this.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
return await callWithRateLimit(
|
|
154
|
+
this.tokenBucket,
|
|
155
|
+
async () =>
|
|
156
|
+
await this.client.getObject({
|
|
157
|
+
id: objectId,
|
|
158
|
+
options,
|
|
159
|
+
})
|
|
153
160
|
);
|
|
154
161
|
},
|
|
155
162
|
});
|
|
@@ -170,14 +177,17 @@ export class ScallopCache {
|
|
|
170
177
|
// objectIds.sort();
|
|
171
178
|
|
|
172
179
|
return this.queryClient.fetchQuery({
|
|
180
|
+
retry: 5,
|
|
181
|
+
retryDelay: 1000,
|
|
173
182
|
queryKey: queryKeys.rpc.getObjects(
|
|
174
183
|
objectIds,
|
|
175
184
|
this.walletAddress,
|
|
176
185
|
options
|
|
177
186
|
),
|
|
178
187
|
queryFn: async () => {
|
|
179
|
-
return await callWithRateLimit(
|
|
180
|
-
this.
|
|
188
|
+
return await callWithRateLimit(
|
|
189
|
+
this.tokenBucket,
|
|
190
|
+
async () => await this.suiKit.getObjects(objectIds, options)
|
|
181
191
|
);
|
|
182
192
|
},
|
|
183
193
|
});
|
|
@@ -190,10 +200,13 @@ export class ScallopCache {
|
|
|
190
200
|
*/
|
|
191
201
|
public async queryGetOwnedObjects(input: GetOwnedObjectsParams) {
|
|
192
202
|
return this.queryClient.fetchQuery({
|
|
203
|
+
retry: 5,
|
|
204
|
+
retryDelay: 1000,
|
|
193
205
|
queryKey: queryKeys.rpc.getOwnedObjects(input),
|
|
194
206
|
queryFn: async () => {
|
|
195
|
-
return await callWithRateLimit(
|
|
196
|
-
this.
|
|
207
|
+
return await callWithRateLimit(
|
|
208
|
+
this.tokenBucket,
|
|
209
|
+
async () => await this.client.getOwnedObjects(input)
|
|
197
210
|
);
|
|
198
211
|
},
|
|
199
212
|
});
|
|
@@ -203,10 +216,13 @@ export class ScallopCache {
|
|
|
203
216
|
input: GetDynamicFieldsParams
|
|
204
217
|
): Promise<DynamicFieldPage | null> {
|
|
205
218
|
return this.queryClient.fetchQuery({
|
|
219
|
+
retry: 5,
|
|
220
|
+
retryDelay: 1000,
|
|
206
221
|
queryKey: queryKeys.rpc.getDynamicFields(input),
|
|
207
222
|
queryFn: async () => {
|
|
208
|
-
return await callWithRateLimit(
|
|
209
|
-
this.
|
|
223
|
+
return await callWithRateLimit(
|
|
224
|
+
this.tokenBucket,
|
|
225
|
+
async () => await this.client.getDynamicFields(input)
|
|
210
226
|
);
|
|
211
227
|
},
|
|
212
228
|
});
|
|
@@ -216,6 +232,8 @@ export class ScallopCache {
|
|
|
216
232
|
input: GetDynamicFieldObjectParams
|
|
217
233
|
): Promise<SuiObjectResponse | null> {
|
|
218
234
|
return this.queryClient.fetchQuery({
|
|
235
|
+
retry: 5,
|
|
236
|
+
retryDelay: (attemptIndex) => Math.min(1000 * attemptIndex, 8000),
|
|
219
237
|
queryKey: queryKeys.rpc.getDynamicFieldObject(input),
|
|
220
238
|
queryFn: async () => {
|
|
221
239
|
return await callWithRateLimit(this.tokenBucket, () =>
|
|
@@ -229,10 +247,13 @@ export class ScallopCache {
|
|
|
229
247
|
owner: string
|
|
230
248
|
): Promise<{ [k: string]: string }> {
|
|
231
249
|
return this.queryClient.fetchQuery({
|
|
250
|
+
retry: 5,
|
|
251
|
+
retryDelay: 1000,
|
|
232
252
|
queryKey: queryKeys.rpc.getAllCoinBalances(owner),
|
|
233
253
|
queryFn: async () => {
|
|
234
|
-
const allBalances = await callWithRateLimit(
|
|
235
|
-
this.
|
|
254
|
+
const allBalances = await callWithRateLimit(
|
|
255
|
+
this.tokenBucket,
|
|
256
|
+
async () => await this.client.getAllBalances({ owner })
|
|
236
257
|
);
|
|
237
258
|
if (!allBalances) return {};
|
|
238
259
|
const balances = allBalances.reduce(
|
|
@@ -19,6 +19,7 @@ const borrowLimitZod = zod.object({
|
|
|
19
19
|
|
|
20
20
|
const borrowLimitKeyType = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da26c7221b220f01af6::market_dynamic_keys::BorrowLimitKey`; // prod
|
|
21
21
|
// const borrowLimitKeyType = `0xb784ea287d944e478a3ceaa071f8885072cce6b7224cf245914dc2f9963f460e::market_dynamic_keys::BorrowLimitKey`;
|
|
22
|
+
|
|
22
23
|
/**
|
|
23
24
|
* Return supply limit of a pool (including the decimals)
|
|
24
25
|
* @param utils
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
SupportBorrowIncentiveCoins,
|
|
26
26
|
ObligationBorrowIcentiveReward,
|
|
27
27
|
SupportBorrowIncentiveRewardCoins,
|
|
28
|
+
SupportAssetCoins,
|
|
28
29
|
} from '../types';
|
|
29
30
|
|
|
30
31
|
/**
|
|
@@ -349,15 +350,18 @@ export const getObligationAccount = async (
|
|
|
349
350
|
coinPrices?: CoinPrices,
|
|
350
351
|
coinAmounts?: CoinAmounts
|
|
351
352
|
) => {
|
|
352
|
-
const
|
|
353
|
+
const coinNames: SupportAssetCoins[] = Array.from(
|
|
354
|
+
new Set([...SUPPORT_POOLS, ...SUPPORT_COLLATERALS])
|
|
355
|
+
);
|
|
356
|
+
const collateralAssetCoinNames = [
|
|
353
357
|
...SUPPORT_COLLATERALS,
|
|
354
|
-
];
|
|
358
|
+
] as SupportCollateralCoins[];
|
|
359
|
+
|
|
355
360
|
market = market ?? (await query.queryMarket({ indexer }));
|
|
356
361
|
coinPrices =
|
|
357
362
|
coinPrices ?? (await query.getAllCoinPrices({ marketPools: market.pools }));
|
|
358
363
|
coinAmounts =
|
|
359
|
-
coinAmounts ||
|
|
360
|
-
(await query.getCoinAmounts(collateralAssetCoinNames, ownerAddress));
|
|
364
|
+
coinAmounts || (await query.getCoinAmounts(coinNames, ownerAddress));
|
|
361
365
|
|
|
362
366
|
const [obligationQuery, borrowIncentivePools, borrowIncentiveAccounts] =
|
|
363
367
|
await Promise.all([
|
|
@@ -365,6 +369,7 @@ export const getObligationAccount = async (
|
|
|
365
369
|
query.getBorrowIncentivePools(undefined, {
|
|
366
370
|
coinPrices,
|
|
367
371
|
indexer,
|
|
372
|
+
marketPools: market.pools,
|
|
368
373
|
}),
|
|
369
374
|
query.getBorrowIncentiveAccounts(obligationId),
|
|
370
375
|
]);
|
package/src/utils/query.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
ParsedBorrowIncentiveAccountPoolData,
|
|
28
28
|
SupportBorrowIncentiveRewardCoins,
|
|
29
29
|
} from '../types';
|
|
30
|
+
import { sCoinRawNameToName } from 'src/constants';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Parse origin market pool data to a more readable format.
|
|
@@ -433,9 +434,12 @@ export const parseOriginBorrowIncentivePoolData = (
|
|
|
433
434
|
poolPoints: originBorrowIncentivePoolData.points.reduce(
|
|
434
435
|
(acc, point) => {
|
|
435
436
|
const parsed = parseOriginBorrowIncentivesPoolPointData(point);
|
|
436
|
-
|
|
437
|
+
let name = parseStructTag(
|
|
437
438
|
parsed.pointType
|
|
438
439
|
).name.toLowerCase() as SupportBorrowIncentiveRewardCoins;
|
|
440
|
+
if (sCoinRawNameToName[name]) {
|
|
441
|
+
name = sCoinRawNameToName[name];
|
|
442
|
+
}
|
|
439
443
|
acc[name] = parsed;
|
|
440
444
|
return acc;
|
|
441
445
|
},
|
package/src/utils/tokenBucket.ts
CHANGED
|
@@ -16,11 +16,14 @@ class TokenBucket {
|
|
|
16
16
|
refill() {
|
|
17
17
|
const now = Date.now();
|
|
18
18
|
const elapsed = now - this.lastRefill;
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
if (elapsed >= this.interval) {
|
|
20
21
|
const tokensToAdd =
|
|
21
22
|
Math.floor(elapsed / this.interval) * this.tokensPerInterval;
|
|
22
23
|
this.tokens = Math.min(this.tokens + tokensToAdd, this.tokensPerInterval);
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
// Update lastRefill to reflect the exact time of the last "refill"
|
|
26
|
+
this.lastRefill += Math.floor(elapsed / this.interval) * this.interval;
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -45,35 +48,12 @@ const callWithRateLimit = async <T>(
|
|
|
45
48
|
|
|
46
49
|
const tryRequest = async (): Promise<T | null> => {
|
|
47
50
|
if (tokenBucket.removeTokens(1)) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Check if the result is an object with status code (assuming the response has a status property)
|
|
52
|
-
if (result && (result as any).status === 429) {
|
|
53
|
-
throw new Error('Unexpected status code: 429');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return result;
|
|
57
|
-
} catch (error: any) {
|
|
58
|
-
if (
|
|
59
|
-
error.message === 'Unexpected status code: 429' &&
|
|
60
|
-
retries < maxRetries
|
|
61
|
-
) {
|
|
62
|
-
retries++;
|
|
63
|
-
const delay = retryDelayInMs * Math.pow(backoffFactor, retries);
|
|
64
|
-
// console.warn(`429 encountered, retrying in ${delay} ms`);
|
|
65
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
66
|
-
return tryRequest();
|
|
67
|
-
} else {
|
|
68
|
-
// console.error(error);
|
|
69
|
-
console.error('An error occurred:', error.message);
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
51
|
+
const result = await fn();
|
|
52
|
+
return result;
|
|
73
53
|
} else if (retries < maxRetries) {
|
|
74
54
|
retries++;
|
|
75
55
|
const delay = retryDelayInMs * Math.pow(backoffFactor, retries);
|
|
76
|
-
|
|
56
|
+
console.error(`Rate limit exceeded, retrying in ${delay} ms`);
|
|
77
57
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
78
58
|
return tryRequest();
|
|
79
59
|
} else {
|