@scallop-io/sui-scallop-sdk 2.3.2 → 2.3.5
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/index.d.mts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +5 -5
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
- package/src/constants/queryKeys.ts +7 -1
- package/src/models/scallopQuery.ts +1 -1
- package/src/models/scallopSuiKit.ts +1 -56
- package/src/models/scallopUtils.ts +48 -33
- package/src/types/constant/queryKeys.ts +1 -1
package/package.json
CHANGED
|
@@ -74,10 +74,16 @@ export const queryKeys = {
|
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
oracle: {
|
|
77
|
-
getPythLatestPriceFeeds: (priceIds
|
|
77
|
+
getPythLatestPriceFeeds: (endpoint?: string, priceIds?: string[]) => [
|
|
78
78
|
'oracle',
|
|
79
79
|
'getPythPriceIds',
|
|
80
80
|
priceIds,
|
|
81
|
+
endpoint,
|
|
82
|
+
],
|
|
83
|
+
getCoinPrices: (priceIds: string[]) => [
|
|
84
|
+
'oracle',
|
|
85
|
+
'getCoinPrices',
|
|
86
|
+
priceIds,
|
|
81
87
|
],
|
|
82
88
|
},
|
|
83
89
|
};
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
queryObligation,
|
|
61
61
|
queryVeScaKeyIdFromReferralBindings,
|
|
62
62
|
} from 'src/queries';
|
|
63
|
-
import { SuiObjectRef, SuiObjectData } from '@mysten/sui/
|
|
63
|
+
import { SuiObjectRef, SuiObjectData } from '@mysten/sui/client';
|
|
64
64
|
import { SuiObjectArg } from '@scallop-io/sui-kit';
|
|
65
65
|
import { ScallopQueryInterface } from './interface';
|
|
66
66
|
|
|
@@ -26,6 +26,7 @@ import { QueryKey } from '@tanstack/query-core';
|
|
|
26
26
|
import ScallopQueryClient, {
|
|
27
27
|
ScallopQueryClientParams,
|
|
28
28
|
} from './scallopQueryClient';
|
|
29
|
+
import { RateLimiter } from './rateLimiter';
|
|
29
30
|
|
|
30
31
|
type QueryInspectTxnParams = {
|
|
31
32
|
queryTarget: string;
|
|
@@ -65,62 +66,6 @@ const deepMergeObject = <T>(curr: T, update: T): T => {
|
|
|
65
66
|
return result;
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
export class RateLimiter {
|
|
69
|
-
private tokens: number;
|
|
70
|
-
private lastRefillTime: number;
|
|
71
|
-
private readonly refillRate: number; // tokens per millisecond
|
|
72
|
-
|
|
73
|
-
constructor(private readonly capacity: number = 10) {
|
|
74
|
-
this.refillRate = this.capacity / 1000; // 10 tokens per second = 0.01 tokens/ms
|
|
75
|
-
this.tokens = this.capacity;
|
|
76
|
-
this.lastRefillTime = Date.now();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private refill() {
|
|
80
|
-
const now = Date.now();
|
|
81
|
-
const elapsed = now - this.lastRefillTime;
|
|
82
|
-
const newTokens = elapsed * this.refillRate;
|
|
83
|
-
|
|
84
|
-
this.tokens = Math.min(this.capacity, this.tokens + newTokens);
|
|
85
|
-
this.lastRefillTime = now;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private getTimeToNextToken(): number {
|
|
89
|
-
this.refill();
|
|
90
|
-
|
|
91
|
-
if (this.tokens >= 1) {
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Calculate exact milliseconds needed for 1 full token
|
|
96
|
-
const deficit = 1 - this.tokens;
|
|
97
|
-
return Math.ceil(deficit / this.refillRate);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async acquireToken(): Promise<void> {
|
|
101
|
-
// eslint-disable-next-line no-constant-condition
|
|
102
|
-
while (true) {
|
|
103
|
-
const waitTime = this.getTimeToNextToken();
|
|
104
|
-
|
|
105
|
-
if (waitTime === 0) {
|
|
106
|
-
if (this.tokens >= 1) {
|
|
107
|
-
this.tokens -= 1;
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
114
|
-
this.refill();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
119
|
-
await this.acquireToken();
|
|
120
|
-
return await fn();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
69
|
class ScallopSuiKit extends ScallopQueryClient {
|
|
125
70
|
public readonly suiKit: SuiKit;
|
|
126
71
|
private _walletAddress: string;
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from 'src/constants';
|
|
17
17
|
import { PriceFeed, SuiPriceServiceConnection } from '@pythnetwork/pyth-sui-js';
|
|
18
18
|
import ScallopSuiKit, { ScallopSuiKitParams } from './scallopSuiKit';
|
|
19
|
-
import { SuiObjectData } from '@mysten/sui/
|
|
19
|
+
import { SuiObjectData } from '@mysten/sui/client';
|
|
20
20
|
import { queryObligation } from 'src/queries';
|
|
21
21
|
import { ScallopUtilsInterface } from './interface';
|
|
22
22
|
|
|
@@ -521,25 +521,24 @@ class ScallopUtils implements ScallopUtilsInterface {
|
|
|
521
521
|
]),
|
|
522
522
|
] as string[]
|
|
523
523
|
) {
|
|
524
|
-
|
|
524
|
+
const priceIdsMap = new Map(
|
|
525
|
+
coinNames.map((coinName) => [
|
|
526
|
+
coinName,
|
|
527
|
+
this.address.get(`core.coins.${coinName}.oracle.pyth.feed`),
|
|
528
|
+
])
|
|
529
|
+
);
|
|
525
530
|
|
|
526
|
-
const
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const priceIdPairs = Array.from(failedRequests.values()).reduce(
|
|
531
|
-
(acc, coinName) => {
|
|
532
|
-
const priceId =
|
|
533
|
-
this.address.get(`core.coins.${coinName}.oracle.pyth.feed`) ??
|
|
534
|
-
this.constants.poolAddresses[coinName]?.pythFeed;
|
|
535
|
-
acc.push([coinName, priceId]);
|
|
536
|
-
return acc;
|
|
537
|
-
},
|
|
538
|
-
[] as [string, string][]
|
|
539
|
-
);
|
|
540
|
-
if (priceIdPairs.length === 0) break;
|
|
531
|
+
const priceIds = Array.from(priceIdsMap.values());
|
|
532
|
+
const state = this.queryClient.getQueryState(
|
|
533
|
+
queryKeys.oracle.getCoinPrices(priceIds)
|
|
534
|
+
);
|
|
541
535
|
|
|
542
|
-
|
|
536
|
+
if (state && state && Date.now() - (state.dataUpdatedAt ?? 0) < 30_000) {
|
|
537
|
+
return state.data as CoinPrices;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
let coinPrices: CoinPrices = {};
|
|
541
|
+
for (const endpoint of this.pythEndpoints) {
|
|
543
542
|
const pythConnection = new SuiPriceServiceConnection(endpoint, {
|
|
544
543
|
timeout: this.timeout,
|
|
545
544
|
httpRetries: 0,
|
|
@@ -547,33 +546,49 @@ class ScallopUtils implements ScallopUtilsInterface {
|
|
|
547
546
|
|
|
548
547
|
try {
|
|
549
548
|
const feeds = await this.queryClient.fetchQuery({
|
|
550
|
-
queryKey: queryKeys.oracle.getPythLatestPriceFeeds(
|
|
549
|
+
queryKey: queryKeys.oracle.getPythLatestPriceFeeds(
|
|
550
|
+
endpoint,
|
|
551
|
+
priceIds
|
|
552
|
+
),
|
|
551
553
|
queryFn: async () => {
|
|
552
554
|
return await pythConnection.getLatestPriceFeeds(priceIds);
|
|
553
555
|
},
|
|
554
|
-
|
|
555
|
-
|
|
556
|
+
retry: false,
|
|
557
|
+
staleTime: 30_000,
|
|
558
|
+
gcTime: 30_000,
|
|
556
559
|
});
|
|
557
|
-
if (feeds)
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
560
|
+
if (!feeds) throw new Error('No feeds returned from pyth');
|
|
561
|
+
|
|
562
|
+
if (feeds.length !== priceIds.length)
|
|
563
|
+
throw new Error('Incomplete feeds returned from pyth');
|
|
564
|
+
|
|
565
|
+
feeds.forEach((feed, idx) => {
|
|
566
|
+
const coinName = coinNames[idx] as string;
|
|
567
|
+
const data = this.parseDataFromPythPriceFeed(feed);
|
|
568
|
+
coinPrices[coinName as string] = data.price;
|
|
569
|
+
});
|
|
570
|
+
this.queryClient.setQueryData(
|
|
571
|
+
queryKeys.oracle.getCoinPrices(priceIds),
|
|
572
|
+
coinPrices
|
|
573
|
+
);
|
|
565
574
|
} catch (e: any) {
|
|
575
|
+
if ('status' in e && e.status === 403) {
|
|
576
|
+
console.log(`trying next pyth endpoint`);
|
|
577
|
+
continue; // try next endpoint
|
|
578
|
+
}
|
|
566
579
|
console.error(e.message);
|
|
567
580
|
}
|
|
568
|
-
if (failedRequests.size === 0) break;
|
|
569
581
|
}
|
|
570
582
|
|
|
571
|
-
if (
|
|
583
|
+
if (Object.keys(coinPrices).length === 0) {
|
|
572
584
|
coinPrices = {
|
|
573
585
|
...coinPrices,
|
|
574
|
-
...(await this.getPythPrices(Array.from(
|
|
586
|
+
...(await this.getPythPrices(Array.from(coinNames))),
|
|
575
587
|
};
|
|
576
|
-
|
|
588
|
+
this.queryClient.setQueryData(
|
|
589
|
+
queryKeys.oracle.getCoinPrices(priceIds),
|
|
590
|
+
coinPrices
|
|
591
|
+
);
|
|
577
592
|
}
|
|
578
593
|
|
|
579
594
|
return coinPrices;
|