@scallop-io/sui-scallop-sdk 1.4.15-rc.3 → 1.4.16
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/common.d.ts +6 -6
- package/dist/constants/enum.d.ts +2 -2
- package/dist/constants/index.d.ts +0 -1
- package/dist/constants/poolAddress.d.ts +2 -1
- package/dist/constants/queryKeys.d.ts +3 -4
- package/dist/index.d.ts +0 -1
- package/dist/index.js +2009 -1627
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2088 -1701
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallop.d.ts +1 -2
- package/dist/models/scallopBuilder.d.ts +2 -1
- package/dist/models/scallopCache.d.ts +18 -12
- package/dist/models/scallopQuery.d.ts +95 -10
- package/dist/models/scallopUtils.d.ts +4 -4
- package/dist/queries/borrowIncentiveQuery.d.ts +6 -1
- package/dist/queries/coreQuery.d.ts +2 -0
- package/dist/queries/objectsQuery.d.ts +1 -2
- package/dist/queries/poolAddressesQuery.d.ts +4 -2
- package/dist/queries/portfolioQuery.d.ts +71 -5
- package/dist/queries/priceQuery.d.ts +4 -0
- package/dist/queries/sCoinQuery.d.ts +1 -1
- package/dist/types/builder/core.d.ts +3 -3
- package/dist/types/model.d.ts +8 -2
- package/dist/utils/index.d.ts +0 -2
- package/package.json +7 -7
- package/src/builders/borrowIncentiveBuilder.ts +11 -5
- package/src/builders/coreBuilder.ts +61 -32
- package/src/builders/loyaltyProgramBuilder.ts +3 -2
- package/src/builders/referralBuilder.ts +16 -6
- package/src/builders/sCoinBuilder.ts +6 -4
- package/src/builders/spoolBuilder.ts +14 -7
- package/src/builders/vescaBuilder.ts +13 -7
- package/src/constants/coinGecko.ts +2 -0
- package/src/constants/common.ts +7 -1
- package/src/constants/enum.ts +46 -20
- package/src/constants/index.ts +0 -1
- package/src/constants/poolAddress.ts +163 -41
- package/src/constants/pyth.ts +2 -0
- package/src/constants/queryKeys.ts +7 -9
- package/src/constants/testAddress.ts +24 -0
- package/src/index.ts +0 -1
- package/src/models/scallop.ts +9 -13
- package/src/models/scallopAddress.ts +2 -9
- package/src/models/scallopBuilder.ts +62 -8
- package/src/models/scallopCache.ts +220 -114
- package/src/models/scallopClient.ts +3 -6
- package/src/models/scallopIndexer.ts +1 -5
- package/src/models/scallopQuery.ts +53 -19
- package/src/models/scallopUtils.ts +9 -13
- package/src/queries/borrowIncentiveQuery.ts +6 -13
- package/src/queries/coreQuery.ts +62 -48
- package/src/queries/loyaltyProgramQuery.ts +1 -3
- package/src/queries/objectsQuery.ts +1 -3
- package/src/queries/poolAddressesQuery.ts +13 -10
- package/src/queries/portfolioQuery.ts +252 -20
- package/src/queries/priceQuery.ts +2 -7
- package/src/queries/sCoinQuery.ts +2 -2
- package/src/queries/spoolQuery.ts +21 -20
- package/src/queries/vescaQuery.ts +3 -7
- package/src/types/builder/core.ts +21 -3
- package/src/types/model.ts +13 -2
- package/src/utils/index.ts +0 -2
- package/src/utils/indexer.ts +3 -1
- package/src/utils/query.ts +2 -2
- package/dist/constants/tokenBucket.d.ts +0 -2
- package/dist/utils/tokenBucket.d.ts +0 -11
- package/src/constants/tokenBucket.ts +0 -2
- package/src/utils/tokenBucket.ts +0 -68
package/src/models/scallop.ts
CHANGED
|
@@ -15,12 +15,6 @@ import type {
|
|
|
15
15
|
import { ScallopIndexer } from './scallopIndexer';
|
|
16
16
|
import { ScallopCache } from './scallopCache';
|
|
17
17
|
import { QueryClientConfig } from '@tanstack/query-core';
|
|
18
|
-
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
19
|
-
import { TokenBucket } from 'src/utils';
|
|
20
|
-
import {
|
|
21
|
-
DEFAULT_INTERVAL_IN_MS,
|
|
22
|
-
DEFAULT_TOKENS_PER_INTERVAL,
|
|
23
|
-
} from 'src/constants/tokenBucket';
|
|
24
18
|
import type { QueryClient } from '@tanstack/query-core';
|
|
25
19
|
import { newSuiKit } from './suiKit';
|
|
26
20
|
|
|
@@ -51,18 +45,19 @@ export class Scallop {
|
|
|
51
45
|
public constructor(
|
|
52
46
|
params: ScallopParams,
|
|
53
47
|
cacheOptions?: QueryClientConfig,
|
|
54
|
-
tokenBucket?: TokenBucket,
|
|
55
48
|
queryClient?: QueryClient
|
|
56
49
|
) {
|
|
57
50
|
this.params = params;
|
|
58
51
|
this.suiKit = newSuiKit(params);
|
|
59
52
|
this.cache = new ScallopCache(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
{
|
|
54
|
+
...this.params,
|
|
55
|
+
cacheOptions,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
suiKit: this.suiKit,
|
|
59
|
+
queryClient,
|
|
60
|
+
}
|
|
66
61
|
);
|
|
67
62
|
this.address = new ScallopAddress(
|
|
68
63
|
{
|
|
@@ -168,6 +163,7 @@ export class Scallop {
|
|
|
168
163
|
},
|
|
169
164
|
{
|
|
170
165
|
address: this.address,
|
|
166
|
+
suiKit: this.suiKit,
|
|
171
167
|
}
|
|
172
168
|
);
|
|
173
169
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { API_BASE_URL, USE_TEST_ADDRESS } from '../constants';
|
|
2
|
-
import {
|
|
2
|
+
import { type NetworkType } from '@scallop-io/sui-kit';
|
|
3
3
|
import type {
|
|
4
4
|
ScallopAddressParams,
|
|
5
5
|
AddressesInterface,
|
|
@@ -7,7 +7,6 @@ import type {
|
|
|
7
7
|
ScallopAddressInstanceParams,
|
|
8
8
|
} from '../types';
|
|
9
9
|
import { ScallopCache } from './scallopCache';
|
|
10
|
-
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
11
10
|
import axios, { AxiosInstance } from 'axios';
|
|
12
11
|
import { TEST_ADDRESSES } from 'src/constants/testAddress';
|
|
13
12
|
import { queryKeys } from 'src/constants';
|
|
@@ -379,13 +378,7 @@ export class ScallopAddress {
|
|
|
379
378
|
instance?: ScallopAddressInstanceParams
|
|
380
379
|
) {
|
|
381
380
|
const { id, auth, network, forceInterface } = params;
|
|
382
|
-
this.cache =
|
|
383
|
-
instance?.cache ??
|
|
384
|
-
new ScallopCache(
|
|
385
|
-
instance?.suiKit ?? new SuiKit({}),
|
|
386
|
-
undefined,
|
|
387
|
-
DEFAULT_CACHE_OPTIONS
|
|
388
|
-
);
|
|
381
|
+
this.cache = instance?.cache ?? new ScallopCache({});
|
|
389
382
|
|
|
390
383
|
this._requestClient = axios.create({
|
|
391
384
|
baseURL: API_BASE_URL,
|
|
@@ -7,7 +7,13 @@ import { ScallopQuery } from './scallopQuery';
|
|
|
7
7
|
import { ScallopUtils } from './scallopUtils';
|
|
8
8
|
import type { SuiTransactionBlockResponse } from '@mysten/sui/client';
|
|
9
9
|
import type { Transaction } from '@mysten/sui/transactions';
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
SuiAmountsArg,
|
|
12
|
+
SuiTxBlock as SuiKitTxBlock,
|
|
13
|
+
SuiObjectArg,
|
|
14
|
+
SuiTxArg,
|
|
15
|
+
SuiVecTxArg,
|
|
16
|
+
} from '@scallop-io/sui-kit';
|
|
11
17
|
import type {
|
|
12
18
|
ScallopBuilderParams,
|
|
13
19
|
ScallopTxBlock,
|
|
@@ -18,7 +24,6 @@ import type {
|
|
|
18
24
|
SelectCoinReturnType,
|
|
19
25
|
} from '../types';
|
|
20
26
|
import { ScallopCache } from './scallopCache';
|
|
21
|
-
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
22
27
|
import { newSuiKit } from './suiKit';
|
|
23
28
|
|
|
24
29
|
/**
|
|
@@ -60,11 +65,9 @@ export class ScallopBuilder {
|
|
|
60
65
|
this.address = this.utils.address;
|
|
61
66
|
this.cache = this.address.cache;
|
|
62
67
|
} else {
|
|
63
|
-
this.cache = new ScallopCache(
|
|
64
|
-
this.suiKit,
|
|
65
|
-
|
|
66
|
-
DEFAULT_CACHE_OPTIONS
|
|
67
|
-
);
|
|
68
|
+
this.cache = new ScallopCache(this.params, {
|
|
69
|
+
suiKit: this.suiKit,
|
|
70
|
+
});
|
|
68
71
|
this.address = new ScallopAddress(
|
|
69
72
|
{
|
|
70
73
|
id: params?.addressesId ?? ADDRESSES_ID,
|
|
@@ -104,7 +107,7 @@ export class ScallopBuilder {
|
|
|
104
107
|
await this.address.read();
|
|
105
108
|
}
|
|
106
109
|
await this.query.init(force, this.address);
|
|
107
|
-
await this.utils.init(force, this.address);
|
|
110
|
+
// await this.utils.init(force, this.address);
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
/**
|
|
@@ -215,4 +218,55 @@ export class ScallopBuilder {
|
|
|
215
218
|
txBlock
|
|
216
219
|
)) as SuiTransactionBlockResponse;
|
|
217
220
|
}
|
|
221
|
+
|
|
222
|
+
public moveCall(
|
|
223
|
+
txb: ScallopTxBlock | SuiKitTxBlock,
|
|
224
|
+
target: string,
|
|
225
|
+
args?: (SuiTxArg | SuiVecTxArg | SuiObjectArg | SuiAmountsArg)[],
|
|
226
|
+
typeArgs?: string[]
|
|
227
|
+
) {
|
|
228
|
+
// Disable for now
|
|
229
|
+
// const resolvedQueryTarget =
|
|
230
|
+
// await this.cache.queryGetNormalizedMoveFunction(target);
|
|
231
|
+
// if (!resolvedQueryTarget) throw new Error('Invalid query target');
|
|
232
|
+
|
|
233
|
+
// const { parameters } = resolvedQueryTarget;
|
|
234
|
+
// try {
|
|
235
|
+
// // we can try resolve the args first
|
|
236
|
+
// const resolvedArgs = await Promise.all(
|
|
237
|
+
// (args ?? []).map(async (arg, idx) => {
|
|
238
|
+
// if (typeof arg !== 'string') return arg;
|
|
239
|
+
|
|
240
|
+
// const cachedData = (await this.cache.queryGetObject(arg))?.data;
|
|
241
|
+
// if (!cachedData) return arg;
|
|
242
|
+
|
|
243
|
+
// const owner = cachedData.owner;
|
|
244
|
+
// if (!owner || typeof owner !== 'object' || !('Shared' in owner))
|
|
245
|
+
// return {
|
|
246
|
+
// objectId: cachedData.objectId,
|
|
247
|
+
// version: cachedData.version,
|
|
248
|
+
// digest: cachedData.digest,
|
|
249
|
+
// };
|
|
250
|
+
|
|
251
|
+
// const parameter = parameters[idx];
|
|
252
|
+
// if (
|
|
253
|
+
// typeof parameter !== 'object' ||
|
|
254
|
+
// !('MutableReference' in parameter || 'Reference' in parameter)
|
|
255
|
+
// )
|
|
256
|
+
// return arg;
|
|
257
|
+
|
|
258
|
+
// return {
|
|
259
|
+
// objectId: cachedData.objectId,
|
|
260
|
+
// initialSharedVersion: owner.Shared.initial_shared_version,
|
|
261
|
+
// mutable: 'MutableReference' in parameter,
|
|
262
|
+
// };
|
|
263
|
+
// })
|
|
264
|
+
// );
|
|
265
|
+
// return txb.moveCall(target, resolvedArgs, typeArgs);
|
|
266
|
+
// } catch (e: any) {
|
|
267
|
+
// console.error(e.message);
|
|
268
|
+
// return txb.moveCall(target, args, typeArgs);
|
|
269
|
+
// }
|
|
270
|
+
return txb.moveCall(target, args, typeArgs);
|
|
271
|
+
}
|
|
218
272
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { QueryClient
|
|
1
|
+
import { QueryClient } from '@tanstack/query-core';
|
|
2
2
|
import {
|
|
3
3
|
SuiObjectArg,
|
|
4
4
|
SuiTxBlock,
|
|
5
5
|
normalizeStructTag,
|
|
6
|
+
parseStructTag,
|
|
6
7
|
} from '@scallop-io/sui-kit';
|
|
7
8
|
import { SuiKit } from '@scallop-io/sui-kit';
|
|
8
9
|
import type {
|
|
@@ -16,14 +17,12 @@ import type {
|
|
|
16
17
|
GetDynamicFieldObjectParams,
|
|
17
18
|
GetBalanceParams,
|
|
18
19
|
SuiClient,
|
|
20
|
+
CoinBalance,
|
|
19
21
|
} from '@mysten/sui/client';
|
|
20
22
|
import { DEFAULT_CACHE_OPTIONS } from 'src/constants/cache';
|
|
21
|
-
import { callWithRateLimit, TokenBucket } from 'src/utils';
|
|
22
|
-
import {
|
|
23
|
-
DEFAULT_INTERVAL_IN_MS,
|
|
24
|
-
DEFAULT_TOKENS_PER_INTERVAL,
|
|
25
|
-
} from 'src/constants/tokenBucket';
|
|
26
23
|
import { queryKeys } from 'src/constants';
|
|
24
|
+
import { ScallopCacheInstanceParams, ScallopCacheParams } from 'src/types';
|
|
25
|
+
import { newSuiKit } from './suiKit';
|
|
27
26
|
|
|
28
27
|
type QueryInspectTxnParams = {
|
|
29
28
|
queryTarget: string;
|
|
@@ -31,6 +30,32 @@ type QueryInspectTxnParams = {
|
|
|
31
30
|
typeArgs?: any[];
|
|
32
31
|
};
|
|
33
32
|
|
|
33
|
+
const DEFAULT_TOKENS_PER_INTERVAL = 10;
|
|
34
|
+
const DEFAULT_INTERVAL_IN_MS = 250;
|
|
35
|
+
|
|
36
|
+
const deepMergeObject = <T>(curr: T, update: T): T => {
|
|
37
|
+
const result = { ...curr }; // Clone the current object to avoid mutation
|
|
38
|
+
|
|
39
|
+
for (const key in update) {
|
|
40
|
+
if (
|
|
41
|
+
update[key] &&
|
|
42
|
+
typeof update[key] === 'object' &&
|
|
43
|
+
!Array.isArray(update[key])
|
|
44
|
+
) {
|
|
45
|
+
// If the value is an object, recurse
|
|
46
|
+
result[key] = deepMergeObject(
|
|
47
|
+
curr[key] || ({} as T[Extract<keyof T, string>]),
|
|
48
|
+
update[key]
|
|
49
|
+
);
|
|
50
|
+
} else {
|
|
51
|
+
// Otherwise, directly assign the value
|
|
52
|
+
result[key] = update[key];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
|
|
34
59
|
/**
|
|
35
60
|
* @description
|
|
36
61
|
* It provides caching for moveCall, RPC Request, and API Request.
|
|
@@ -45,20 +70,26 @@ type QueryInspectTxnParams = {
|
|
|
45
70
|
*/
|
|
46
71
|
|
|
47
72
|
export class ScallopCache {
|
|
48
|
-
public readonly
|
|
49
|
-
|
|
50
|
-
|
|
73
|
+
public readonly params: ScallopCacheParams;
|
|
74
|
+
|
|
75
|
+
public queryClient: QueryClient;
|
|
76
|
+
public suiKit: SuiKit;
|
|
77
|
+
// private tokenBucket: TokenBucket;
|
|
51
78
|
public walletAddress: string;
|
|
79
|
+
private tokensPerInterval: number = DEFAULT_TOKENS_PER_INTERVAL;
|
|
80
|
+
private interval: number = DEFAULT_INTERVAL_IN_MS;
|
|
81
|
+
private tokens: number;
|
|
82
|
+
private lastRefill: number;
|
|
52
83
|
|
|
53
84
|
public constructor(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
cacheOptions?: QueryClientConfig,
|
|
57
|
-
tokenBucket?: TokenBucket,
|
|
58
|
-
queryClient?: QueryClient
|
|
85
|
+
params: ScallopCacheParams,
|
|
86
|
+
instance?: ScallopCacheInstanceParams
|
|
59
87
|
) {
|
|
88
|
+
this.params = params;
|
|
89
|
+
this.suiKit = instance?.suiKit ?? newSuiKit(params);
|
|
60
90
|
this.queryClient =
|
|
61
|
-
queryClient ??
|
|
91
|
+
instance?.queryClient ??
|
|
92
|
+
new QueryClient(params?.cacheOptions ?? DEFAULT_CACHE_OPTIONS);
|
|
62
93
|
|
|
63
94
|
// handle case where there's existing queryClient and cacheOptions is also passed
|
|
64
95
|
// if (queryClient && cacheOptions) {
|
|
@@ -70,22 +101,62 @@ export class ScallopCache {
|
|
|
70
101
|
// // if(cacheOptions.mutations)this.queryClient.setMutationDefaults(cacheOptions.mutations);
|
|
71
102
|
// }
|
|
72
103
|
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
this.tokens = this.tokensPerInterval;
|
|
105
|
+
this.lastRefill = Date.now();
|
|
106
|
+
this.walletAddress = params.walletAddress ?? this.suiKit.currentAddress();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private get client(): SuiClient {
|
|
110
|
+
return this.suiKit.client();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private refill() {
|
|
114
|
+
const now = Date.now();
|
|
115
|
+
const elapsed = now - this.lastRefill;
|
|
116
|
+
|
|
117
|
+
if (elapsed >= this.interval) {
|
|
118
|
+
const tokensToAdd =
|
|
119
|
+
Math.floor(elapsed / this.interval) * this.tokensPerInterval;
|
|
120
|
+
this.tokens = Math.min(this.tokens + tokensToAdd, this.tokensPerInterval);
|
|
121
|
+
|
|
122
|
+
// Update lastRefill to reflect the exact time of the last "refill"
|
|
123
|
+
this.lastRefill += Math.floor(elapsed / this.interval) * this.interval;
|
|
124
|
+
}
|
|
78
125
|
}
|
|
79
126
|
|
|
80
|
-
private
|
|
81
|
-
|
|
82
|
-
|
|
127
|
+
private removeTokens(count: number) {
|
|
128
|
+
this.refill();
|
|
129
|
+
if (this.tokens >= count) {
|
|
130
|
+
this.tokens -= count;
|
|
131
|
+
return true;
|
|
83
132
|
}
|
|
84
|
-
return
|
|
133
|
+
return false;
|
|
85
134
|
}
|
|
86
135
|
|
|
87
|
-
private
|
|
88
|
-
|
|
136
|
+
private async callWithRateLimit<T>(
|
|
137
|
+
fn: () => Promise<T>,
|
|
138
|
+
maxRetries = 15,
|
|
139
|
+
backoffFactor = 1.25 // The factor by which to increase the delay
|
|
140
|
+
): Promise<T | null> {
|
|
141
|
+
let retries = 0;
|
|
142
|
+
|
|
143
|
+
const tryRequest = async (): Promise<T | null> => {
|
|
144
|
+
if (this.removeTokens(1)) {
|
|
145
|
+
const result = await fn();
|
|
146
|
+
return result;
|
|
147
|
+
} else if (retries < maxRetries) {
|
|
148
|
+
retries++;
|
|
149
|
+
const delay = this.interval * Math.pow(backoffFactor, retries);
|
|
150
|
+
// console.error(`Rate limit exceeded, retrying in ${delay} ms`);
|
|
151
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
152
|
+
return tryRequest();
|
|
153
|
+
} else {
|
|
154
|
+
console.error('Maximum retries reached');
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return tryRequest();
|
|
89
160
|
}
|
|
90
161
|
|
|
91
162
|
/**
|
|
@@ -97,14 +168,14 @@ export class ScallopCache {
|
|
|
97
168
|
* - `all`: All queries that match the refetch predicate will be refetched in the background.
|
|
98
169
|
* - `none`: No queries will be refetched. Queries that match the refetch predicate will only be marked as invalid.
|
|
99
170
|
*/
|
|
100
|
-
public async invalidateAllCache() {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
171
|
+
// public async invalidateAllCache() {
|
|
172
|
+
// return Object.values(queryKeys.rpc).map((t) =>
|
|
173
|
+
// this.queryClient.invalidateQueries({
|
|
174
|
+
// queryKey: t(),
|
|
175
|
+
// type: 'all',
|
|
176
|
+
// })
|
|
177
|
+
// );
|
|
178
|
+
// }
|
|
108
179
|
|
|
109
180
|
private retryFn(errCount: number, e: any) {
|
|
110
181
|
if (errCount === 5) return false;
|
|
@@ -125,12 +196,39 @@ export class ScallopCache {
|
|
|
125
196
|
}: QueryInspectTxnParams): Promise<DevInspectResults | null> {
|
|
126
197
|
const txBlock = new SuiTxBlock();
|
|
127
198
|
|
|
199
|
+
const resolvedQueryTarget =
|
|
200
|
+
await this.queryGetNormalizedMoveFunction(queryTarget);
|
|
201
|
+
if (!resolvedQueryTarget) throw new Error('Invalid query target');
|
|
202
|
+
|
|
203
|
+
const { parameters } = resolvedQueryTarget;
|
|
204
|
+
|
|
128
205
|
const resolvedArgs = await Promise.all(
|
|
129
|
-
args.map(async (arg) => {
|
|
130
|
-
if (typeof arg
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return arg;
|
|
206
|
+
(args ?? []).map(async (arg, idx) => {
|
|
207
|
+
if (typeof arg !== 'string') return arg;
|
|
208
|
+
|
|
209
|
+
const cachedData = (await this.queryGetObject(arg))?.data;
|
|
210
|
+
if (!cachedData) return arg;
|
|
211
|
+
|
|
212
|
+
const owner = cachedData.owner;
|
|
213
|
+
if (!owner || typeof owner !== 'object' || !('Shared' in owner))
|
|
214
|
+
return {
|
|
215
|
+
objectId: cachedData.objectId,
|
|
216
|
+
version: cachedData.version,
|
|
217
|
+
digest: cachedData.digest,
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const parameter = parameters[idx];
|
|
221
|
+
if (
|
|
222
|
+
typeof parameter !== 'object' ||
|
|
223
|
+
!('MutableReference' in parameter || 'Reference' in parameter)
|
|
224
|
+
)
|
|
225
|
+
return arg;
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
objectId: cachedData.objectId,
|
|
229
|
+
initialSharedVersion: owner.Shared.initial_shared_version,
|
|
230
|
+
mutable: 'MutableReference' in parameter,
|
|
231
|
+
};
|
|
134
232
|
})
|
|
135
233
|
);
|
|
136
234
|
txBlock.moveCall(queryTarget, resolvedArgs, typeArgs);
|
|
@@ -140,8 +238,7 @@ export class ScallopCache {
|
|
|
140
238
|
retryDelay: 1000,
|
|
141
239
|
queryKey: queryKeys.rpc.getInspectTxn(queryTarget, args, typeArgs),
|
|
142
240
|
queryFn: async () => {
|
|
143
|
-
return await callWithRateLimit(
|
|
144
|
-
this.tokenBucket,
|
|
241
|
+
return await this.callWithRateLimit(
|
|
145
242
|
async () => await this.suiKit.inspectTxn(txBlock)
|
|
146
243
|
);
|
|
147
244
|
},
|
|
@@ -149,6 +246,23 @@ export class ScallopCache {
|
|
|
149
246
|
return query;
|
|
150
247
|
}
|
|
151
248
|
|
|
249
|
+
public async queryGetNormalizedMoveFunction(target: string) {
|
|
250
|
+
const { address, module, name } = parseStructTag(target);
|
|
251
|
+
return this.queryClient.fetchQuery({
|
|
252
|
+
queryKey: queryKeys.rpc.getNormalizedMoveFunction(target),
|
|
253
|
+
queryFn: async () => {
|
|
254
|
+
return await this.callWithRateLimit(
|
|
255
|
+
async () =>
|
|
256
|
+
await this.suiKit.client().getNormalizedMoveFunction({
|
|
257
|
+
package: address,
|
|
258
|
+
module,
|
|
259
|
+
function: name,
|
|
260
|
+
})
|
|
261
|
+
);
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
152
266
|
/**
|
|
153
267
|
* @description Provides cache for getObject of the SuiKit.
|
|
154
268
|
* @param objectId
|
|
@@ -159,13 +273,18 @@ export class ScallopCache {
|
|
|
159
273
|
objectId: string,
|
|
160
274
|
options?: SuiObjectDataOptions
|
|
161
275
|
) {
|
|
276
|
+
options = {
|
|
277
|
+
...options,
|
|
278
|
+
showOwner: true,
|
|
279
|
+
showContent: true,
|
|
280
|
+
showType: true,
|
|
281
|
+
};
|
|
162
282
|
return this.queryClient.fetchQuery({
|
|
163
283
|
retry: this.retryFn,
|
|
164
284
|
retryDelay: 1000,
|
|
165
285
|
queryKey: queryKeys.rpc.getObject(objectId, options),
|
|
166
286
|
queryFn: async () => {
|
|
167
|
-
return await callWithRateLimit(
|
|
168
|
-
this.tokenBucket,
|
|
287
|
+
return await this.callWithRateLimit(
|
|
169
288
|
async () =>
|
|
170
289
|
await this.client.getObject({
|
|
171
290
|
id: objectId,
|
|
@@ -181,43 +300,38 @@ export class ScallopCache {
|
|
|
181
300
|
* @param objectIds
|
|
182
301
|
* @returns Promise<SuiObjectData[]>
|
|
183
302
|
*/
|
|
184
|
-
public async queryGetObjects(
|
|
185
|
-
objectIds: string[],
|
|
186
|
-
options: SuiObjectDataOptions = {
|
|
187
|
-
showContent: true,
|
|
188
|
-
}
|
|
189
|
-
): Promise<SuiObjectData[]> {
|
|
303
|
+
public async queryGetObjects(objectIds: string[]): Promise<SuiObjectData[]> {
|
|
190
304
|
if (objectIds.length === 0) return [];
|
|
191
|
-
|
|
305
|
+
const options: SuiObjectDataOptions = {
|
|
306
|
+
showContent: true,
|
|
307
|
+
showOwner: true,
|
|
308
|
+
showType: true,
|
|
309
|
+
};
|
|
192
310
|
|
|
193
311
|
return this.queryClient.fetchQuery({
|
|
194
312
|
retry: this.retryFn,
|
|
195
313
|
retryDelay: 1000,
|
|
196
|
-
queryKey: queryKeys.rpc.getObjects(
|
|
197
|
-
objectIds,
|
|
198
|
-
this.walletAddress,
|
|
199
|
-
options
|
|
200
|
-
),
|
|
314
|
+
queryKey: queryKeys.rpc.getObjects(objectIds),
|
|
201
315
|
queryFn: async () => {
|
|
202
|
-
const results = await callWithRateLimit(
|
|
203
|
-
this.tokenBucket,
|
|
316
|
+
const results = await this.callWithRateLimit(
|
|
204
317
|
async () => await this.suiKit.getObjects(objectIds, options)
|
|
205
318
|
);
|
|
206
319
|
if (results) {
|
|
207
320
|
results.forEach((result) => {
|
|
208
|
-
|
|
209
|
-
|
|
321
|
+
// fetch previous data
|
|
322
|
+
const queryKey = queryKeys.rpc.getObject(result.objectId);
|
|
323
|
+
const prevDatas =
|
|
324
|
+
this.queryClient.getQueriesData<SuiObjectResponse>({
|
|
210
325
|
exact: false,
|
|
211
|
-
queryKey
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
);
|
|
326
|
+
queryKey,
|
|
327
|
+
});
|
|
328
|
+
prevDatas.forEach(([key, prevData]) => {
|
|
329
|
+
this.queryClient.setQueryData(
|
|
330
|
+
key,
|
|
331
|
+
deepMergeObject(prevData, { data: result, error: null }),
|
|
332
|
+
{ updatedAt: Date.now() }
|
|
333
|
+
);
|
|
334
|
+
});
|
|
221
335
|
});
|
|
222
336
|
}
|
|
223
337
|
return results;
|
|
@@ -231,14 +345,13 @@ export class ScallopCache {
|
|
|
231
345
|
* @returns Promise<PaginatedObjectsResponse>
|
|
232
346
|
*/
|
|
233
347
|
public async queryGetOwnedObjects(input: GetOwnedObjectsParams) {
|
|
234
|
-
// TODO: This query need its own separate rate limiter (as owned objects can theoretically be infinite), need a better way to handle this
|
|
348
|
+
// @TODO: This query need its own separate rate limiter (as owned objects can theoretically be infinite), need a better way to handle this
|
|
235
349
|
return this.queryClient.fetchQuery({
|
|
236
350
|
retry: this.retryFn,
|
|
237
351
|
retryDelay: 1000,
|
|
238
352
|
queryKey: queryKeys.rpc.getOwnedObjects(input),
|
|
239
353
|
queryFn: async () => {
|
|
240
|
-
const results = await callWithRateLimit(
|
|
241
|
-
this.tokenBucket,
|
|
354
|
+
const results = await this.callWithRateLimit(
|
|
242
355
|
async () => await this.client.getOwnedObjects(input)
|
|
243
356
|
);
|
|
244
357
|
if (results && results.data.length > 0) {
|
|
@@ -250,22 +363,20 @@ export class ScallopCache {
|
|
|
250
363
|
NonNullable<{ data: SuiObjectData }> => !!result.data
|
|
251
364
|
)
|
|
252
365
|
.forEach((result) => {
|
|
253
|
-
|
|
254
|
-
|
|
366
|
+
// fetch previous data
|
|
367
|
+
const queryKey = queryKeys.rpc.getObject(result.data.objectId);
|
|
368
|
+
const prevDatas =
|
|
369
|
+
this.queryClient.getQueriesData<SuiObjectResponse>({
|
|
255
370
|
exact: false,
|
|
256
|
-
queryKey
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
{
|
|
266
|
-
updatedAt: Date.now(),
|
|
267
|
-
}
|
|
268
|
-
);
|
|
371
|
+
queryKey,
|
|
372
|
+
});
|
|
373
|
+
prevDatas.forEach(([key, prevData]) => {
|
|
374
|
+
this.queryClient.setQueryData(
|
|
375
|
+
key,
|
|
376
|
+
deepMergeObject(prevData, { data: result.data, error: null }),
|
|
377
|
+
{ updatedAt: Date.now() }
|
|
378
|
+
);
|
|
379
|
+
});
|
|
269
380
|
});
|
|
270
381
|
}
|
|
271
382
|
return results;
|
|
@@ -281,8 +392,7 @@ export class ScallopCache {
|
|
|
281
392
|
retryDelay: 1000,
|
|
282
393
|
queryKey: queryKeys.rpc.getDynamicFields(input),
|
|
283
394
|
queryFn: async () => {
|
|
284
|
-
return await callWithRateLimit(
|
|
285
|
-
this.tokenBucket,
|
|
395
|
+
return await this.callWithRateLimit(
|
|
286
396
|
async () => await this.client.getDynamicFields(input)
|
|
287
397
|
);
|
|
288
398
|
},
|
|
@@ -297,26 +407,22 @@ export class ScallopCache {
|
|
|
297
407
|
retryDelay: (attemptIndex) => Math.min(1000 * attemptIndex, 8000),
|
|
298
408
|
queryKey: queryKeys.rpc.getDynamicFieldObject(input),
|
|
299
409
|
queryFn: async () => {
|
|
300
|
-
const result = await
|
|
410
|
+
const result = await this.callWithRateLimit(() =>
|
|
301
411
|
this.client.getDynamicFieldObject(input)
|
|
302
412
|
);
|
|
303
413
|
if (result?.data) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
{
|
|
317
|
-
updatedAt: Date.now(),
|
|
318
|
-
}
|
|
319
|
-
);
|
|
414
|
+
const queryKey = queryKeys.rpc.getObject(result.data.objectId);
|
|
415
|
+
const prevDatas = this.queryClient.getQueriesData<SuiObjectResponse>({
|
|
416
|
+
exact: false,
|
|
417
|
+
queryKey,
|
|
418
|
+
});
|
|
419
|
+
prevDatas.forEach(([key, prevData]) => {
|
|
420
|
+
this.queryClient.setQueryData(
|
|
421
|
+
key,
|
|
422
|
+
deepMergeObject(prevData, { data: result.data, error: null }),
|
|
423
|
+
{ updatedAt: Date.now() }
|
|
424
|
+
);
|
|
425
|
+
});
|
|
320
426
|
}
|
|
321
427
|
return result;
|
|
322
428
|
},
|
|
@@ -325,26 +431,24 @@ export class ScallopCache {
|
|
|
325
431
|
|
|
326
432
|
public async queryGetAllCoinBalances(
|
|
327
433
|
owner: string
|
|
328
|
-
): Promise<{ [k: string]:
|
|
434
|
+
): Promise<{ [k: string]: CoinBalance }> {
|
|
329
435
|
return this.queryClient.fetchQuery({
|
|
330
436
|
retry: this.retryFn,
|
|
331
437
|
retryDelay: 1000,
|
|
332
438
|
queryKey: queryKeys.rpc.getAllCoinBalances(owner),
|
|
333
439
|
queryFn: async () => {
|
|
334
|
-
const allBalances = await callWithRateLimit(
|
|
335
|
-
this.tokenBucket,
|
|
440
|
+
const allBalances = await this.callWithRateLimit(
|
|
336
441
|
async () => await this.client.getAllBalances({ owner })
|
|
337
442
|
);
|
|
338
443
|
if (!allBalances) return {};
|
|
339
444
|
const balances = allBalances.reduce(
|
|
340
445
|
(acc, coinBalance) => {
|
|
341
446
|
if (coinBalance.totalBalance !== '0') {
|
|
342
|
-
acc[normalizeStructTag(coinBalance.coinType)] =
|
|
343
|
-
coinBalance.totalBalance;
|
|
447
|
+
acc[normalizeStructTag(coinBalance.coinType)] = coinBalance;
|
|
344
448
|
}
|
|
345
449
|
return acc;
|
|
346
450
|
},
|
|
347
|
-
{} as { [k: string]:
|
|
451
|
+
{} as { [k: string]: CoinBalance }
|
|
348
452
|
);
|
|
349
453
|
|
|
350
454
|
return balances;
|
|
@@ -352,8 +456,10 @@ export class ScallopCache {
|
|
|
352
456
|
});
|
|
353
457
|
}
|
|
354
458
|
|
|
355
|
-
public async queryGetCoinBalance(
|
|
356
|
-
|
|
459
|
+
public async queryGetCoinBalance(
|
|
460
|
+
input: GetBalanceParams
|
|
461
|
+
): Promise<CoinBalance | null> {
|
|
462
|
+
if (!input.coinType) return null;
|
|
357
463
|
|
|
358
464
|
return (
|
|
359
465
|
((await this.queryGetAllCoinBalances(input.owner)) ?? {})[
|