@scallop-io/sui-scallop-sdk 2.2.2 → 2.3.0-lst-x-oracle-alpha.1

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.
Files changed (70) hide show
  1. package/dist/address-Bp_gAUMw.d.ts +165 -0
  2. package/dist/chunk-4GSK5DO7.js +25 -0
  3. package/dist/chunk-B4M6FI47.mjs +5 -0
  4. package/dist/constants/index.d.mts +262 -0
  5. package/dist/constants/index.d.ts +262 -0
  6. package/dist/constants/index.js +86 -0
  7. package/dist/constants/index.mjs +5 -0
  8. package/dist/models/index.d.mts +393 -0
  9. package/dist/models/index.d.ts +393 -0
  10. package/dist/models/index.js +34 -0
  11. package/dist/models/index.mjs +16 -0
  12. package/dist/queryKeys-AaZqDYle.d.ts +43 -0
  13. package/dist/{index.d.mts → scallopUtils-Cxm9zldY.d.ts} +1748 -2586
  14. package/dist/types/index.d.mts +9 -0
  15. package/dist/types/index.d.ts +9 -0
  16. package/dist/types/index.js +2 -0
  17. package/dist/types/index.mjs +1 -0
  18. package/package.json +23 -11
  19. package/src/builders/borrowIncentiveBuilder.ts +2 -2
  20. package/src/builders/coreBuilder.ts +1 -1
  21. package/src/builders/index.ts +2 -2
  22. package/src/builders/oracles/error.ts +29 -0
  23. package/src/builders/oracles/index.ts +115 -363
  24. package/src/builders/oracles/oraclePackageRegistry.ts +323 -0
  25. package/src/builders/oracles/priceFeedUpdater.ts +112 -0
  26. package/src/builders/oracles/priceUpdateRequester.ts +50 -0
  27. package/src/builders/oracles/xOracleUpdateStrategy.ts +178 -0
  28. package/src/builders/oracles/xOracleUpdater.ts +160 -0
  29. package/src/builders/vescaBuilder.ts +2 -2
  30. package/src/constants/api.ts +2 -0
  31. package/src/constants/common.ts +0 -3
  32. package/src/constants/index.ts +2 -1
  33. package/src/constants/package.ts +14 -0
  34. package/src/constants/testAddress.ts +190 -105
  35. package/src/constants/xoracle.ts +8 -2
  36. package/src/models/scallopAddress.ts +24 -4
  37. package/src/models/scallopBuilder.ts +4 -4
  38. package/src/models/scallopClient.ts +1 -1
  39. package/src/models/scallopConstants.ts +2 -2
  40. package/src/models/scallopIndexer.ts +3 -2
  41. package/src/models/scallopQuery.ts +52 -36
  42. package/src/models/scallopQueryClient.ts +1 -1
  43. package/src/models/scallopSuiKit.ts +1 -1
  44. package/src/models/scallopUtils.ts +5 -8
  45. package/src/queries/borrowIncentiveQuery.ts +2 -3
  46. package/src/queries/coreQuery.ts +2 -3
  47. package/src/queries/index.ts +4 -3
  48. package/src/queries/loyaltyProgramQuery.ts +1 -1
  49. package/src/queries/portfolioQuery.ts +13 -13
  50. package/src/queries/sCoinQuery.ts +2 -2
  51. package/src/queries/spoolQuery.ts +8 -8
  52. package/src/queries/vescaQuery.ts +2 -2
  53. package/src/queries/xOracleQuery.ts +20 -3
  54. package/src/types/address.ts +85 -47
  55. package/src/types/constant/index.ts +2 -1
  56. package/src/types/constant/package.ts +3 -0
  57. package/src/types/constant/xOracle.ts +10 -7
  58. package/src/types/query/index.ts +0 -1
  59. package/src/utils/builder.ts +1 -1
  60. package/src/utils/index.ts +2 -2
  61. package/src/utils/query.ts +6 -6
  62. package/src/utils/util.ts +1 -1
  63. package/dist/index.d.ts +0 -3242
  64. package/dist/index.js +0 -49
  65. package/dist/index.mjs +0 -15
  66. package/src/builders/oracles/pyth.ts +0 -44
  67. package/src/index.ts +0 -13
  68. package/src/queries/ownerQuery.ts +0 -32
  69. package/src/types/constant/enum.ts +0 -64
  70. package/src/types/query/sCoin.ts +0 -1
@@ -1,14 +1,18 @@
1
- import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';
2
- import type { TransactionArgument } from '@mysten/sui/transactions';
1
+ import { X_ORACLE_LIST } from 'src/constants/xoracle';
2
+ import { createXOracleUpdater, IXOracleUpdater } from './xOracleUpdater';
3
+ import {
4
+ createPackageRegistry,
5
+ XOraclePackageRegistry,
6
+ } from './oraclePackageRegistry';
7
+ import {
8
+ createPriceFeedUpdater,
9
+ PriceFeedUpdateOptions,
10
+ } from './priceFeedUpdater';
3
11
  import type { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
4
12
  import type { ScallopBuilder } from 'src/models';
5
- import type {
6
- SupportOracleType,
7
- xOracleRules,
8
- xOracleRuleType,
9
- } from 'src/types';
10
- import { xOracleList as X_ORACLE_LIST } from 'src/constants';
11
- import { updatePythPriceFeeds } from './pyth';
13
+ import type { SupportOracleType, xOracleRuleType } from 'src/types';
14
+ import { PriceUpdateRequester } from './priceUpdateRequester';
15
+ import { UnsupportedOracleError } from './error';
12
16
 
13
17
  /**
14
18
  * Update the price of the oracle for multiple coin.
@@ -22,378 +26,126 @@ export const updateOracles = async (
22
26
  builder: ScallopBuilder,
23
27
  txBlock: SuiKitTxBlock,
24
28
  assetCoinNames: string[] = [...builder.constants.whitelist.lending],
25
- options: {
26
- usePythPullModel: boolean;
27
- useOnChainXOracleList: boolean;
28
- sponsoredFeeds: string[];
29
- } = {
30
- usePythPullModel: true,
31
- useOnChainXOracleList: true,
32
- sponsoredFeeds: [],
33
- }
29
+ options: Partial<PriceFeedUpdateOptions> = {}
34
30
  ) => {
35
- const sponsoredFeeds = new Set(
36
- builder.sponsoredFeeds ?? options.sponsoredFeeds
37
- );
38
-
39
- // Validate the sponsoredFeeds content.
40
- sponsoredFeeds.forEach((feed) => {
41
- if (!builder.constants.whitelist.lending.has(feed)) {
42
- throw new Error(`${feed} is not valid feed`);
43
- }
44
- });
45
-
46
- const usePythPullModel = builder.usePythPullModel ?? options.usePythPullModel;
47
- const useOnChainXOracleList =
48
- builder.useOnChainXOracleList ?? options.useOnChainXOracleList;
49
-
50
- const xOracleList = useOnChainXOracleList
31
+ // Validate the options
32
+ assetCoinNames = [...new Set(assetCoinNames)]; // Remove duplicates
33
+ const mergedOptions = {
34
+ usePythPullModel: builder.usePythPullModel,
35
+ useOnChainXOracleList: builder.useOnChainXOracleList,
36
+ pythSponsoredFeeds: builder.pythSponsoredFeeds,
37
+ ...options,
38
+ } as PriceFeedUpdateOptions;
39
+
40
+ // Retrieve the xOracle list from the builder or use the default one.
41
+ const xOracleList = mergedOptions.useOnChainXOracleList
51
42
  ? await builder.query.getAssetOracles()
52
- : X_ORACLE_LIST;
43
+ : X_ORACLE_LIST; // Record<coinName, Record<xOracleRuleType, SupportOracleType[]>>
44
+
45
+ const xOracleListAsSet = Object.entries(xOracleList).reduce(
46
+ (acc, [coinName, { primary, secondary }]) => {
47
+ acc[coinName] = {
48
+ primary: new Set(primary),
49
+ secondary: new Set(secondary),
50
+ };
51
+ return acc;
52
+ },
53
+ {} as Record<string, Record<xOracleRuleType, Set<SupportOracleType>>>
54
+ );
53
55
 
54
- // const rules: SupportOracleType[] = builder.isTestnet ? ['pyth'] : ['pyth'];
55
- const flattenedRules = new Set(
56
+ // Get all oracle types no duplicates from all rules (primary and secondary).
57
+ const oracleTypesSet = new Set(
56
58
  Object.values(xOracleList).flatMap(({ primary, secondary }) => [
57
59
  ...primary,
58
60
  ...secondary,
59
61
  ])
60
62
  );
61
63
 
62
- const filterAssetCoinNames = (
64
+ const getRuleType = (
63
65
  assetCoinName: string,
64
- rule: SupportOracleType
66
+ oracleType: SupportOracleType
65
67
  ) => {
66
- const assetXOracle = xOracleList[assetCoinName];
67
- return (
68
- assetXOracle &&
69
- (assetXOracle.primary.includes(rule) ||
70
- assetXOracle.secondary.includes(rule))
71
- );
68
+ const ruleSet = xOracleListAsSet[assetCoinName];
69
+ if (!ruleSet)
70
+ return {
71
+ isPrimary: false,
72
+ isSecondary: false,
73
+ };
74
+
75
+ const { primary, secondary } = ruleSet;
76
+ const isPrimary = primary.has(oracleType);
77
+ const isSecondary = secondary.has(oracleType);
78
+
79
+ return {
80
+ isPrimary,
81
+ isSecondary,
82
+ };
72
83
  };
73
84
 
74
- const updateAssetCoinNames = [...new Set(assetCoinNames)];
75
- const pythAssetCoinNames = updateAssetCoinNames.filter((assetCoinName) =>
76
- filterAssetCoinNames(assetCoinName, 'pyth')
77
- );
78
-
79
- if (flattenedRules.has('pyth')) {
80
- const needToUpdatePythPriceFeeds: string[] = [];
81
- for (const pythAssetCoinName of pythAssetCoinNames) {
82
- /**
83
- * Check if the Pyth pull model is not used but the feed is not sponsored.
84
- * This is used to determine if we should update the Pyth price feeds.
85
- */
86
- const notUsingPullAndNotSponsored =
87
- !usePythPullModel && !sponsoredFeeds.has(pythAssetCoinName);
88
-
89
- if (usePythPullModel || notUsingPullAndNotSponsored) {
90
- needToUpdatePythPriceFeeds.push(pythAssetCoinName);
91
- }
85
+ // Create a package registry for xOracle
86
+ const xOraclePackageRegistry = new XOraclePackageRegistry(builder.utils);
87
+
88
+ // Create xOracle updater for each oracle type
89
+ const xOracleUpdaters: Partial<Record<SupportOracleType, IXOracleUpdater>> =
90
+ {};
91
+
92
+ // Iterate through oracle set
93
+ for (const oracleType of oracleTypesSet) {
94
+ const filteredAssetCoinNames = assetCoinNames.filter((assetCoinName) => {
95
+ const { isPrimary, isSecondary } = getRuleType(assetCoinName, oracleType);
96
+ if (!isPrimary && !isSecondary) return false;
97
+ return true;
98
+ });
99
+
100
+ if (filteredAssetCoinNames.length > 0) {
101
+ // Update all necessary price feeds
102
+ await createPriceFeedUpdater(
103
+ oracleType,
104
+ txBlock,
105
+ builder,
106
+ filteredAssetCoinNames,
107
+ mergedOptions
108
+ ).updatePriceFeeds();
92
109
  }
93
110
 
94
- if (needToUpdatePythPriceFeeds.length > 0) {
95
- await updatePythPriceFeeds(builder, needToUpdatePythPriceFeeds, txBlock);
96
- }
97
- }
98
-
99
- // Remove duplicate coin names.
100
- for (const assetCoinName of updateAssetCoinNames) {
101
- updateOracle(builder, txBlock, assetCoinName, xOracleList[assetCoinName]);
111
+ // Create the xOracle updater for the current oracle type
112
+ xOracleUpdaters[oracleType] = createXOracleUpdater(
113
+ txBlock,
114
+ createPackageRegistry(oracleType, xOraclePackageRegistry)
115
+ );
102
116
  }
103
- };
104
-
105
- /**
106
- * Update the price of the oracle for specific coin.
107
- *
108
- * @param builder - The scallop builder.
109
- * @param txBlock - TxBlock created by SuiKit.
110
- * @param assetCoinName - Specific support asset coin name.
111
- */
112
- const updateOracle = (
113
- builder: ScallopBuilder,
114
- txBlock: SuiKitTxBlock,
115
- assetCoinName: string,
116
- rules: xOracleRules
117
- ) => {
118
- const coinType = builder.utils.parseCoinType(assetCoinName);
119
117
 
120
- updatePrice(
118
+ // Create a price update requester
119
+ const priceUpdateRequester = new PriceUpdateRequester(
121
120
  txBlock,
122
- rules,
123
- builder.address.get('core.packages.xOracle.id'),
124
- builder.address.get('core.oracles.xOracle'),
125
- builder.address.get('core.packages.pyth.id'),
126
- builder.address.get('core.oracles.pyth.registry'),
127
- builder.address.get('core.oracles.pyth.state'),
128
- builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feedObject`),
129
- builder.address.get('core.packages.switchboard.id'),
130
- builder.address.get('core.oracles.switchboard.registry'),
131
- builder.address.get(`core.coins.${assetCoinName}.oracle.switchboard`),
132
- builder.address.get('core.packages.supra.id'),
133
- builder.address.get('core.oracles.supra.registry'),
134
- builder.address.get(`core.oracles.supra.holder`),
135
- coinType
121
+ xOraclePackageRegistry
136
122
  );
137
- };
138
123
 
139
- /**
140
- * Construct a transaction block for update the price.
141
- *
142
- * @param txBlock - The transaction block.
143
- * @param rules - The oracle rules.
144
- * @param xOraclePackageId - The xOracle package id.
145
- * @param xOracleId - The xOracle Id from xOracle package.
146
- * @param pythPackageId - The pyth package id.
147
- * @param pythRegistryId - The registry id from pyth package.
148
- * @param pythStateId - The price state id from pyth package.
149
- * @param pythFeedObjectId - The feed object id from pyth package.
150
- * @param switchboardPackageId - The switchboard package id.
151
- * @param switchboardRegistryId - The registry id from switchboard package.
152
- * @param switchboardAggregatorId - The aggregator id from switchboard package.
153
- * @param supraPackageId - The supra package id.
154
- * @param supraRegistryId - The registry id from supra package.
155
- * @param supraHolderId - The holder id from supra package.
156
- * @param coinType - The type of coin.
157
- * @return TxBlock created by SuiKit.
158
- */
159
- const updatePrice = (
160
- txBlock: SuiKitTxBlock,
161
- rules: xOracleRules,
162
- xOraclePackageId: string,
163
- xOracleId: TransactionArgument | string,
164
- pythPackageId: string,
165
- pythRegistryId: TransactionArgument | string,
166
- pythStateId: TransactionArgument | string,
167
- pythFeedObjectId: TransactionArgument | string,
168
- switchboardPackageId: string,
169
- switchboardRegistryId: TransactionArgument | string,
170
- switchboardAggregatorId: TransactionArgument | string,
171
- supraPackageId: string,
172
- supraRegistryId: TransactionArgument | string,
173
- supraHolderId: TransactionArgument | string,
174
- coinType: string
175
- ) => {
176
- const request = priceUpdateRequest(
177
- txBlock,
178
- xOraclePackageId,
179
- xOracleId,
180
- coinType
181
- );
182
- Object.entries(rules).forEach(([type, rule]: [any, string[]]) => {
183
- if (rule.includes('pyth')) {
184
- updatePythPrice(
185
- type,
186
- txBlock,
187
- pythPackageId,
188
- request,
189
- pythStateId,
190
- pythFeedObjectId,
191
- pythRegistryId,
192
- coinType
193
- );
194
- }
195
- if (rule.includes('supra')) {
196
- updateSupraPrice(
197
- type,
198
- txBlock,
199
- supraPackageId,
200
- request,
201
- supraHolderId,
202
- supraRegistryId,
203
- coinType
204
- );
205
- }
206
- if (rule.includes('switchboard')) {
207
- updateSwitchboardPrice(
208
- type,
209
- txBlock,
210
- switchboardPackageId,
211
- request,
212
- switchboardAggregatorId,
213
- switchboardRegistryId,
214
- coinType
215
- );
216
- }
217
- });
218
-
219
- confirmPriceUpdateRequest(
220
- txBlock,
221
- xOraclePackageId,
222
- xOracleId,
223
- request,
224
- coinType
225
- );
226
- return txBlock;
227
- };
228
-
229
- /**
230
- * Construct a transaction block for request price update.
231
- *
232
- * @param txBlock - The transaction block.
233
- * @param packageId - The xOracle package id.
234
- * @param xOracleId - The xOracle Id from xOracle package.
235
- * @param coinType - The type of coin.
236
- * @return TxBlock created by SuiKit.
237
- */
238
- const priceUpdateRequest = (
239
- txBlock: SuiKitTxBlock,
240
- packageId: string,
241
- xOracleId: TransactionArgument | string,
242
- coinType: string
243
- ) => {
244
- const target = `${packageId}::x_oracle::price_update_request`;
245
- const typeArgs = [coinType];
246
- return txBlock.moveCall(target, [xOracleId], typeArgs);
247
- };
248
-
249
- /**
250
- * Construct a transaction block for confirm price update request.
251
- *
252
- * @param txBlock - The transaction block.
253
- * @param packageId - The xOracle package id.
254
- * @param xOracleId - The xOracle Id from xOracle package.
255
- * @param request - The result of the request.
256
- * @param coinType - The type of coin.
257
- * @return TxBlock created by SuiKit.
258
- */
259
- const confirmPriceUpdateRequest = (
260
- txBlock: SuiKitTxBlock,
261
- packageId: string,
262
- xOracleId: TransactionArgument | string,
263
- request: TransactionArgument,
264
- coinType: string
265
- ) => {
266
- const target = `${packageId}::x_oracle::confirm_price_update_request`;
267
- const typeArgs = [coinType];
268
- txBlock.moveCall(
269
- target,
270
- [
271
- xOracleId,
272
- request,
273
- txBlock.sharedObjectRef({
274
- objectId: SUI_CLOCK_OBJECT_ID,
275
- mutable: false,
276
- initialSharedVersion: '1',
277
- }),
278
- ],
279
- typeArgs
280
- );
281
- return txBlock;
282
- };
283
-
284
- /**
285
- * Construct a transaction block for update supra price.
286
- *
287
- * @param type - The type of price rule.
288
- * @param txBlock - The transaction block.
289
- * @param packageId - The supra package id.
290
- * @param request - The result of the request.
291
- * @param holderId - The holder id from supra package.
292
- * @param registryId - The registry id from supra package.
293
- * @param coinType - The type of coin.
294
- * @return TxBlock created by SuiKit.
295
- */
296
- const updateSupraPrice = (
297
- type: xOracleRuleType,
298
- txBlock: SuiKitTxBlock,
299
- packageId: string,
300
- request: TransactionArgument,
301
- holderId: TransactionArgument | string,
302
- registryId: TransactionArgument | string,
303
- coinType: string
304
- ) => {
305
- txBlock.moveCall(
306
- `${packageId}::rule::set_price_as_${type}`,
307
- [
308
- request,
309
- holderId,
310
- registryId,
311
- txBlock.sharedObjectRef({
312
- objectId: SUI_CLOCK_OBJECT_ID,
313
- initialSharedVersion: '1',
314
- mutable: false,
315
- }),
316
- ],
317
- [coinType]
318
- );
319
- };
320
-
321
- /**
322
- * Construct a transaction block for update switchboard price.
323
- *
324
- * @param type - The type of price rule.
325
- * @param txBlock - The transaction block.
326
- * @param packageId - The switchboard package id.
327
- * @param request - The result of the request.
328
- * @param aggregatorId - The aggregator id from switchboard package.
329
- * @param registryId - The registry id from switchboard package.
330
- * @param coinType - The type of coin.
331
- * @return TxBlock created by SuiKit.
332
- */
333
- const updateSwitchboardPrice = (
334
- type: xOracleRuleType,
335
- txBlock: SuiKitTxBlock,
336
- packageId: string,
337
- request: TransactionArgument,
338
- aggregatorId: TransactionArgument | string,
339
- registryId: TransactionArgument | string,
340
- coinType: string
341
- ) => {
342
- txBlock.moveCall(
343
- // `${packageId}::rule::set_price_as_${type}`,
344
- `${packageId}::rule::set_as_${type}_price`,
345
- [
346
- request,
347
- aggregatorId,
348
- registryId,
349
- txBlock.sharedObjectRef({
350
- objectId: SUI_CLOCK_OBJECT_ID,
351
- initialSharedVersion: '1',
352
- mutable: false,
353
- }),
354
- ],
355
- [coinType]
356
- );
357
- };
358
-
359
- /**
360
- * Construct a transaction block for update pyth price.
361
- *
362
- * @param type - The type of price rule.
363
- * @param txBlock - The transaction block.
364
- * @param packageId - The pyth package id.
365
- * @param request - The result of the request.
366
- * @param stateId - The price state id from pyth package.
367
- * @param wormholeStateId - The whormhole state id from pyth package.
368
- * @param feedObjectId - The feed object id from pyth package.
369
- * @param vaaFromFeeId - The vaa from pyth api with feed id.
370
- * @param registryId - The registry id from pyth package.
371
- * @param coinType - The type of coin.
372
- * @return TxBlock created by SuiKit.
373
- */
374
- const updatePythPrice = (
375
- type: xOracleRuleType,
376
- txBlock: SuiKitTxBlock,
377
- packageId: string,
378
- request: TransactionArgument,
379
- stateId: TransactionArgument | string,
380
- feedObjectId: TransactionArgument | string,
381
- registryId: TransactionArgument | string,
382
- coinType: string
383
- ) => {
384
- txBlock.moveCall(
385
- `${packageId}::rule::set_price_as_${type}`,
386
- [
387
- request,
388
- stateId,
389
- feedObjectId,
390
- registryId,
391
- txBlock.sharedObjectRef({
392
- objectId: SUI_CLOCK_OBJECT_ID,
393
- initialSharedVersion: '1',
394
- mutable: false,
395
- }),
396
- ],
397
- [coinType]
398
- );
124
+ for (const assetCoinName of assetCoinNames) {
125
+ const rules = xOracleList[assetCoinName];
126
+
127
+ // build the price update request for the asset coin
128
+ // Each coin name has its own price update request
129
+ const updateRequest = priceUpdateRequester.buildRequest(assetCoinName);
130
+
131
+ // Iterate through each rule and update the xOracle for each oracle type
132
+ Object.keys(rules).forEach((rule) => {
133
+ const oracles = rules[rule as xOracleRuleType];
134
+ oracles.forEach((oracleType) => {
135
+ const updater = xOracleUpdaters[oracleType];
136
+ if (!updater) {
137
+ // Should never happen if ORACLE_TYPES is the source of truth
138
+ throw new UnsupportedOracleError(oracleType);
139
+ }
140
+ updater.updateXOracle(
141
+ assetCoinName,
142
+ rule as xOracleRuleType,
143
+ updateRequest
144
+ );
145
+ });
146
+ });
147
+
148
+ // Confirm the price update request for all oracles
149
+ priceUpdateRequester.confirmRequest(assetCoinName, updateRequest);
150
+ }
399
151
  };