@scallop-io/sui-scallop-sdk 2.3.0-lst-x-oracle-alpha.9 → 2.3.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.
- package/dist/index.d.mts +1841 -1809
- package/dist/index.d.ts +1841 -1809
- package/dist/index.js +49 -2
- package/dist/index.mjs +15 -2
- package/package.json +8 -7
- package/src/builders/borrowIncentiveBuilder.ts +4 -4
- package/src/builders/coreBuilder.ts +86 -59
- package/src/builders/index.ts +2 -2
- package/src/builders/loyaltyProgramBuilder.ts +2 -2
- package/src/builders/oracles/index.ts +365 -114
- package/src/builders/oracles/pyth.ts +135 -0
- package/src/builders/referralBuilder.ts +4 -10
- package/src/builders/sCoinBuilder.ts +2 -2
- package/src/builders/spoolBuilder.ts +5 -8
- package/src/builders/vescaBuilder.ts +5 -5
- package/src/constants/common.ts +3 -0
- package/src/constants/index.ts +1 -1
- package/src/constants/queryKeys.ts +1 -1
- package/src/constants/rpc.ts +0 -1
- package/src/constants/testAddress.ts +99 -271
- package/src/constants/xoracle.ts +2 -8
- package/src/index.ts +1 -1
- package/src/models/index.ts +1 -2
- package/src/models/interface.ts +7 -7
- package/src/models/rateLimiter.ts +55 -0
- package/src/models/scallop.ts +2 -2
- package/src/models/scallopAddress.ts +7 -35
- package/src/models/scallopBuilder.ts +19 -12
- package/src/models/scallopClient.ts +47 -33
- package/src/models/scallopConstants.ts +3 -3
- package/src/models/scallopIndexer.ts +3 -4
- package/src/models/scallopQuery.ts +113 -57
- package/src/models/scallopQueryClient.ts +1 -1
- package/src/models/scallopSuiKit.ts +1 -1
- package/src/models/scallopUtils.ts +12 -7
- package/src/queries/borrowIncentiveQuery.ts +4 -3
- package/src/queries/coreQuery.ts +114 -186
- package/src/queries/index.ts +3 -4
- package/src/queries/loyaltyProgramQuery.ts +2 -2
- package/src/queries/ownerQuery.ts +32 -0
- package/src/queries/poolAddressesQuery.ts +1 -4
- package/src/queries/portfolioQuery.ts +68 -16
- package/src/queries/priceQuery.ts +2 -3
- package/src/queries/sCoinQuery.ts +2 -2
- package/src/queries/spoolQuery.ts +57 -74
- package/src/queries/vescaQuery.ts +3 -3
- package/src/queries/xOracleQuery.ts +4 -21
- package/src/types/address.ts +47 -98
- package/src/types/builder/core.ts +40 -15
- package/src/types/builder/index.ts +17 -1
- package/src/types/constant/enum.ts +64 -0
- package/src/types/constant/index.ts +1 -2
- package/src/types/constant/xOracle.ts +7 -10
- package/src/types/index.ts +1 -1
- package/src/types/query/core.ts +3 -0
- package/src/types/query/index.ts +1 -0
- package/src/types/query/sCoin.ts +1 -0
- package/src/{builders/utils.ts → utils/builder.ts} +1 -1
- package/src/utils/core.ts +18 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/indexer.ts +47 -0
- package/src/{queries/utils.ts → utils/query.ts} +7 -25
- package/src/utils/util.ts +42 -0
- package/src/builders/oracles/error.ts +0 -18
- package/src/builders/oracles/oraclePackageRegistry.ts +0 -336
- package/src/builders/oracles/priceFeedUpdater.ts +0 -112
- package/src/builders/oracles/priceUpdateRequester.ts +0 -50
- package/src/builders/oracles/xOracleUpdateStrategy.ts +0 -214
- package/src/builders/oracles/xOracleUpdater.ts +0 -153
- package/src/constants/api.ts +0 -2
- package/src/models/utils.ts +0 -97
- package/src/types/builder/type.ts +0 -25
- package/src/types/constant/package.ts +0 -16
- /package/src/types/{util.ts → utils.ts} +0 -0
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
createPackageRegistry,
|
|
5
|
-
XOraclePackageRegistry,
|
|
6
|
-
} from './oraclePackageRegistry';
|
|
7
|
-
import {
|
|
8
|
-
createPriceFeedUpdater,
|
|
9
|
-
PriceFeedUpdateOptions,
|
|
10
|
-
} from './priceFeedUpdater';
|
|
1
|
+
import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';
|
|
2
|
+
import type { TransactionArgument } from '@mysten/sui/transactions';
|
|
11
3
|
import type { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit';
|
|
12
4
|
import type { ScallopBuilder } from 'src/models';
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
|
|
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';
|
|
16
12
|
|
|
17
13
|
/**
|
|
18
14
|
* Update the price of the oracle for multiple coin.
|
|
@@ -26,126 +22,381 @@ export const updateOracles = async (
|
|
|
26
22
|
builder: ScallopBuilder,
|
|
27
23
|
txBlock: SuiKitTxBlock,
|
|
28
24
|
assetCoinNames: string[] = [...builder.constants.whitelist.lending],
|
|
29
|
-
options
|
|
25
|
+
options?: {
|
|
26
|
+
usePythPullModel?: boolean;
|
|
27
|
+
useOnChainXOracleList?: boolean;
|
|
28
|
+
sponsoredFeeds?: string[];
|
|
29
|
+
isSponsoredTx?: boolean;
|
|
30
|
+
}
|
|
30
31
|
) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
...options,
|
|
38
|
-
} as PriceFeedUpdateOptions;
|
|
39
|
-
|
|
40
|
-
// Retrieve the xOracle list from the builder or use the default one.
|
|
41
|
-
const xOracleList = mergedOptions.useOnChainXOracleList
|
|
42
|
-
? await builder.query.getAssetOracles()
|
|
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>>>
|
|
32
|
+
const usePythPullModel =
|
|
33
|
+
options?.usePythPullModel ?? builder.usePythPullModel;
|
|
34
|
+
const useOnChainXOracleList =
|
|
35
|
+
options?.useOnChainXOracleList ?? builder.useOnChainXOracleList;
|
|
36
|
+
const sponsoredFeeds = new Set(
|
|
37
|
+
options?.sponsoredFeeds ?? builder.sponsoredFeeds
|
|
54
38
|
);
|
|
39
|
+
const isSponsoredTx = options?.isSponsoredTx ?? false;
|
|
40
|
+
|
|
41
|
+
// Validate the sponsoredFeeds content.
|
|
42
|
+
sponsoredFeeds.forEach((feed) => {
|
|
43
|
+
if (!builder.constants.whitelist.lending.has(feed)) {
|
|
44
|
+
throw new Error(`${feed} is not valid feed`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const xOracleList = useOnChainXOracleList
|
|
49
|
+
? await builder.query.getAssetOracles()
|
|
50
|
+
: X_ORACLE_LIST;
|
|
55
51
|
|
|
56
|
-
//
|
|
57
|
-
const
|
|
52
|
+
// const rules: SupportOracleType[] = builder.isTestnet ? ['pyth'] : ['pyth'];
|
|
53
|
+
const flattenedRules = new Set(
|
|
58
54
|
Object.values(xOracleList).flatMap(({ primary, secondary }) => [
|
|
59
55
|
...primary,
|
|
60
56
|
...secondary,
|
|
61
57
|
])
|
|
62
58
|
);
|
|
63
59
|
|
|
64
|
-
const
|
|
60
|
+
const filterAssetCoinNames = (
|
|
65
61
|
assetCoinName: string,
|
|
66
|
-
|
|
62
|
+
rule: SupportOracleType
|
|
67
63
|
) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
};
|
|
64
|
+
const assetXOracle = xOracleList[assetCoinName];
|
|
65
|
+
return (
|
|
66
|
+
assetXOracle &&
|
|
67
|
+
(assetXOracle.primary.includes(rule) ||
|
|
68
|
+
assetXOracle.secondary.includes(rule))
|
|
69
|
+
);
|
|
83
70
|
};
|
|
84
71
|
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
72
|
+
const updateAssetCoinNames = [...new Set(assetCoinNames)];
|
|
73
|
+
const pythAssetCoinNames = updateAssetCoinNames.filter((assetCoinName) =>
|
|
74
|
+
filterAssetCoinNames(assetCoinName, 'pyth')
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (flattenedRules.has('pyth')) {
|
|
78
|
+
const needToUpdatePythPriceFeeds: string[] = [];
|
|
79
|
+
for (const pythAssetCoinName of pythAssetCoinNames) {
|
|
80
|
+
/**
|
|
81
|
+
* Check if the Pyth pull model is not used but the feed is not sponsored.
|
|
82
|
+
* This is used to determine if we should update the Pyth price feeds.
|
|
83
|
+
*/
|
|
84
|
+
const notUsingPullAndNotSponsored =
|
|
85
|
+
!usePythPullModel && !sponsoredFeeds.has(pythAssetCoinName);
|
|
86
|
+
|
|
87
|
+
if (usePythPullModel || notUsingPullAndNotSponsored) {
|
|
88
|
+
needToUpdatePythPriceFeeds.push(pythAssetCoinName);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (needToUpdatePythPriceFeeds.length > 0) {
|
|
93
|
+
await updatePythPriceFeeds(
|
|
105
94
|
builder,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
needToUpdatePythPriceFeeds,
|
|
96
|
+
txBlock,
|
|
97
|
+
isSponsoredTx
|
|
98
|
+
);
|
|
109
99
|
}
|
|
100
|
+
}
|
|
110
101
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
createPackageRegistry(oracleType, xOraclePackageRegistry)
|
|
115
|
-
);
|
|
102
|
+
// Remove duplicate coin names.
|
|
103
|
+
for (const assetCoinName of updateAssetCoinNames) {
|
|
104
|
+
updateOracle(builder, txBlock, assetCoinName, xOracleList[assetCoinName]);
|
|
116
105
|
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Update the price of the oracle for specific coin.
|
|
110
|
+
*
|
|
111
|
+
* @param builder - The scallop builder.
|
|
112
|
+
* @param txBlock - TxBlock created by SuiKit.
|
|
113
|
+
* @param assetCoinName - Specific support asset coin name.
|
|
114
|
+
*/
|
|
115
|
+
const updateOracle = (
|
|
116
|
+
builder: ScallopBuilder,
|
|
117
|
+
txBlock: SuiKitTxBlock,
|
|
118
|
+
assetCoinName: string,
|
|
119
|
+
rules: xOracleRules
|
|
120
|
+
) => {
|
|
121
|
+
const coinType = builder.utils.parseCoinType(assetCoinName);
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
const priceUpdateRequester = new PriceUpdateRequester(
|
|
123
|
+
updatePrice(
|
|
120
124
|
txBlock,
|
|
121
|
-
|
|
125
|
+
rules,
|
|
126
|
+
builder.address.get('core.packages.xOracle.id'),
|
|
127
|
+
builder.address.get('core.oracles.xOracle'),
|
|
128
|
+
builder.address.get('core.packages.pyth.id'),
|
|
129
|
+
builder.address.get('core.oracles.pyth.registry'),
|
|
130
|
+
builder.address.get('core.oracles.pyth.state'),
|
|
131
|
+
builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feedObject`),
|
|
132
|
+
builder.address.get('core.packages.switchboard.id'),
|
|
133
|
+
builder.address.get('core.oracles.switchboard.registry'),
|
|
134
|
+
builder.address.get(`core.coins.${assetCoinName}.oracle.switchboard`),
|
|
135
|
+
builder.address.get('core.packages.supra.id'),
|
|
136
|
+
builder.address.get('core.oracles.supra.registry'),
|
|
137
|
+
builder.address.get(`core.oracles.supra.holder`),
|
|
138
|
+
coinType
|
|
122
139
|
);
|
|
140
|
+
};
|
|
123
141
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Construct a transaction block for update the price.
|
|
144
|
+
*
|
|
145
|
+
* @param txBlock - The transaction block.
|
|
146
|
+
* @param rules - The oracle rules.
|
|
147
|
+
* @param xOraclePackageId - The xOracle package id.
|
|
148
|
+
* @param xOracleId - The xOracle Id from xOracle package.
|
|
149
|
+
* @param pythPackageId - The pyth package id.
|
|
150
|
+
* @param pythRegistryId - The registry id from pyth package.
|
|
151
|
+
* @param pythStateId - The price state id from pyth package.
|
|
152
|
+
* @param pythFeedObjectId - The feed object id from pyth package.
|
|
153
|
+
* @param switchboardPackageId - The switchboard package id.
|
|
154
|
+
* @param switchboardRegistryId - The registry id from switchboard package.
|
|
155
|
+
* @param switchboardAggregatorId - The aggregator id from switchboard package.
|
|
156
|
+
* @param supraPackageId - The supra package id.
|
|
157
|
+
* @param supraRegistryId - The registry id from supra package.
|
|
158
|
+
* @param supraHolderId - The holder id from supra package.
|
|
159
|
+
* @param coinType - The type of coin.
|
|
160
|
+
* @return TxBlock created by SuiKit.
|
|
161
|
+
*/
|
|
162
|
+
const updatePrice = (
|
|
163
|
+
txBlock: SuiKitTxBlock,
|
|
164
|
+
rules: xOracleRules,
|
|
165
|
+
xOraclePackageId: string,
|
|
166
|
+
xOracleId: TransactionArgument | string,
|
|
167
|
+
pythPackageId: string,
|
|
168
|
+
pythRegistryId: TransactionArgument | string,
|
|
169
|
+
pythStateId: TransactionArgument | string,
|
|
170
|
+
pythFeedObjectId: TransactionArgument | string,
|
|
171
|
+
switchboardPackageId: string,
|
|
172
|
+
switchboardRegistryId: TransactionArgument | string,
|
|
173
|
+
switchboardAggregatorId: TransactionArgument | string,
|
|
174
|
+
supraPackageId: string,
|
|
175
|
+
supraRegistryId: TransactionArgument | string,
|
|
176
|
+
supraHolderId: TransactionArgument | string,
|
|
177
|
+
coinType: string
|
|
178
|
+
) => {
|
|
179
|
+
const request = priceUpdateRequest(
|
|
180
|
+
txBlock,
|
|
181
|
+
xOraclePackageId,
|
|
182
|
+
xOracleId,
|
|
183
|
+
coinType
|
|
184
|
+
);
|
|
185
|
+
Object.entries(rules).forEach(([type, rule]: [any, string[]]) => {
|
|
186
|
+
if (rule.includes('pyth')) {
|
|
187
|
+
updatePythPrice(
|
|
188
|
+
type,
|
|
189
|
+
txBlock,
|
|
190
|
+
pythPackageId,
|
|
191
|
+
request,
|
|
192
|
+
pythStateId,
|
|
193
|
+
pythFeedObjectId,
|
|
194
|
+
pythRegistryId,
|
|
195
|
+
coinType
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (rule.includes('supra')) {
|
|
199
|
+
updateSupraPrice(
|
|
200
|
+
type,
|
|
201
|
+
txBlock,
|
|
202
|
+
supraPackageId,
|
|
203
|
+
request,
|
|
204
|
+
supraHolderId,
|
|
205
|
+
supraRegistryId,
|
|
206
|
+
coinType
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (rule.includes('switchboard')) {
|
|
210
|
+
updateSwitchboardPrice(
|
|
211
|
+
type,
|
|
212
|
+
txBlock,
|
|
213
|
+
switchboardPackageId,
|
|
214
|
+
request,
|
|
215
|
+
switchboardAggregatorId,
|
|
216
|
+
switchboardRegistryId,
|
|
217
|
+
coinType
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
confirmPriceUpdateRequest(
|
|
223
|
+
txBlock,
|
|
224
|
+
xOraclePackageId,
|
|
225
|
+
xOracleId,
|
|
226
|
+
request,
|
|
227
|
+
coinType
|
|
228
|
+
);
|
|
229
|
+
return txBlock;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Construct a transaction block for request price update.
|
|
234
|
+
*
|
|
235
|
+
* @param txBlock - The transaction block.
|
|
236
|
+
* @param packageId - The xOracle package id.
|
|
237
|
+
* @param xOracleId - The xOracle Id from xOracle package.
|
|
238
|
+
* @param coinType - The type of coin.
|
|
239
|
+
* @return TxBlock created by SuiKit.
|
|
240
|
+
*/
|
|
241
|
+
const priceUpdateRequest = (
|
|
242
|
+
txBlock: SuiKitTxBlock,
|
|
243
|
+
packageId: string,
|
|
244
|
+
xOracleId: TransactionArgument | string,
|
|
245
|
+
coinType: string
|
|
246
|
+
) => {
|
|
247
|
+
const target = `${packageId}::x_oracle::price_update_request`;
|
|
248
|
+
const typeArgs = [coinType];
|
|
249
|
+
return txBlock.moveCall(target, [xOracleId], typeArgs);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Construct a transaction block for confirm price update request.
|
|
254
|
+
*
|
|
255
|
+
* @param txBlock - The transaction block.
|
|
256
|
+
* @param packageId - The xOracle package id.
|
|
257
|
+
* @param xOracleId - The xOracle Id from xOracle package.
|
|
258
|
+
* @param request - The result of the request.
|
|
259
|
+
* @param coinType - The type of coin.
|
|
260
|
+
* @return TxBlock created by SuiKit.
|
|
261
|
+
*/
|
|
262
|
+
const confirmPriceUpdateRequest = (
|
|
263
|
+
txBlock: SuiKitTxBlock,
|
|
264
|
+
packageId: string,
|
|
265
|
+
xOracleId: TransactionArgument | string,
|
|
266
|
+
request: TransactionArgument,
|
|
267
|
+
coinType: string
|
|
268
|
+
) => {
|
|
269
|
+
const target = `${packageId}::x_oracle::confirm_price_update_request`;
|
|
270
|
+
const typeArgs = [coinType];
|
|
271
|
+
txBlock.moveCall(
|
|
272
|
+
target,
|
|
273
|
+
[
|
|
274
|
+
xOracleId,
|
|
275
|
+
request,
|
|
276
|
+
txBlock.sharedObjectRef({
|
|
277
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
278
|
+
mutable: false,
|
|
279
|
+
initialSharedVersion: '1',
|
|
280
|
+
}),
|
|
281
|
+
],
|
|
282
|
+
typeArgs
|
|
283
|
+
);
|
|
284
|
+
return txBlock;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Construct a transaction block for update supra price.
|
|
289
|
+
*
|
|
290
|
+
* @param type - The type of price rule.
|
|
291
|
+
* @param txBlock - The transaction block.
|
|
292
|
+
* @param packageId - The supra package id.
|
|
293
|
+
* @param request - The result of the request.
|
|
294
|
+
* @param holderId - The holder id from supra package.
|
|
295
|
+
* @param registryId - The registry id from supra package.
|
|
296
|
+
* @param coinType - The type of coin.
|
|
297
|
+
* @return TxBlock created by SuiKit.
|
|
298
|
+
*/
|
|
299
|
+
const updateSupraPrice = (
|
|
300
|
+
type: xOracleRuleType,
|
|
301
|
+
txBlock: SuiKitTxBlock,
|
|
302
|
+
packageId: string,
|
|
303
|
+
request: TransactionArgument,
|
|
304
|
+
holderId: TransactionArgument | string,
|
|
305
|
+
registryId: TransactionArgument | string,
|
|
306
|
+
coinType: string
|
|
307
|
+
) => {
|
|
308
|
+
txBlock.moveCall(
|
|
309
|
+
`${packageId}::rule::set_price_as_${type}`,
|
|
310
|
+
[
|
|
311
|
+
request,
|
|
312
|
+
holderId,
|
|
313
|
+
registryId,
|
|
314
|
+
txBlock.sharedObjectRef({
|
|
315
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
316
|
+
initialSharedVersion: '1',
|
|
317
|
+
mutable: false,
|
|
318
|
+
}),
|
|
319
|
+
],
|
|
320
|
+
[coinType]
|
|
321
|
+
);
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Construct a transaction block for update switchboard price.
|
|
326
|
+
*
|
|
327
|
+
* @param type - The type of price rule.
|
|
328
|
+
* @param txBlock - The transaction block.
|
|
329
|
+
* @param packageId - The switchboard package id.
|
|
330
|
+
* @param request - The result of the request.
|
|
331
|
+
* @param aggregatorId - The aggregator id from switchboard package.
|
|
332
|
+
* @param registryId - The registry id from switchboard package.
|
|
333
|
+
* @param coinType - The type of coin.
|
|
334
|
+
* @return TxBlock created by SuiKit.
|
|
335
|
+
*/
|
|
336
|
+
const updateSwitchboardPrice = (
|
|
337
|
+
type: xOracleRuleType,
|
|
338
|
+
txBlock: SuiKitTxBlock,
|
|
339
|
+
packageId: string,
|
|
340
|
+
request: TransactionArgument,
|
|
341
|
+
aggregatorId: TransactionArgument | string,
|
|
342
|
+
registryId: TransactionArgument | string,
|
|
343
|
+
coinType: string
|
|
344
|
+
) => {
|
|
345
|
+
txBlock.moveCall(
|
|
346
|
+
// `${packageId}::rule::set_price_as_${type}`,
|
|
347
|
+
`${packageId}::rule::set_as_${type}_price`,
|
|
348
|
+
[
|
|
349
|
+
request,
|
|
350
|
+
aggregatorId,
|
|
351
|
+
registryId,
|
|
352
|
+
txBlock.sharedObjectRef({
|
|
353
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
354
|
+
initialSharedVersion: '1',
|
|
355
|
+
mutable: false,
|
|
356
|
+
}),
|
|
357
|
+
],
|
|
358
|
+
[coinType]
|
|
359
|
+
);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Construct a transaction block for update pyth price.
|
|
364
|
+
*
|
|
365
|
+
* @param type - The type of price rule.
|
|
366
|
+
* @param txBlock - The transaction block.
|
|
367
|
+
* @param packageId - The pyth package id.
|
|
368
|
+
* @param request - The result of the request.
|
|
369
|
+
* @param stateId - The price state id from pyth package.
|
|
370
|
+
* @param wormholeStateId - The whormhole state id from pyth package.
|
|
371
|
+
* @param feedObjectId - The feed object id from pyth package.
|
|
372
|
+
* @param vaaFromFeeId - The vaa from pyth api with feed id.
|
|
373
|
+
* @param registryId - The registry id from pyth package.
|
|
374
|
+
* @param coinType - The type of coin.
|
|
375
|
+
* @return TxBlock created by SuiKit.
|
|
376
|
+
*/
|
|
377
|
+
const updatePythPrice = (
|
|
378
|
+
type: xOracleRuleType,
|
|
379
|
+
txBlock: SuiKitTxBlock,
|
|
380
|
+
packageId: string,
|
|
381
|
+
request: TransactionArgument,
|
|
382
|
+
stateId: TransactionArgument | string,
|
|
383
|
+
feedObjectId: TransactionArgument | string,
|
|
384
|
+
registryId: TransactionArgument | string,
|
|
385
|
+
coinType: string
|
|
386
|
+
) => {
|
|
387
|
+
txBlock.moveCall(
|
|
388
|
+
`${packageId}::rule::set_price_as_${type}`,
|
|
389
|
+
[
|
|
390
|
+
request,
|
|
391
|
+
stateId,
|
|
392
|
+
feedObjectId,
|
|
393
|
+
registryId,
|
|
394
|
+
txBlock.sharedObjectRef({
|
|
395
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
396
|
+
initialSharedVersion: '1',
|
|
397
|
+
mutable: false,
|
|
398
|
+
}),
|
|
399
|
+
],
|
|
400
|
+
[coinType]
|
|
401
|
+
);
|
|
151
402
|
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HexString,
|
|
3
|
+
SuiPriceServiceConnection,
|
|
4
|
+
SuiPythClient,
|
|
5
|
+
} from '@pythnetwork/pyth-sui-js';
|
|
6
|
+
import { ScallopBuilder } from 'src/models';
|
|
7
|
+
import {
|
|
8
|
+
SUI_CLOCK_OBJECT_ID,
|
|
9
|
+
type SuiTxBlock as SuiKitTxBlock,
|
|
10
|
+
type Transaction,
|
|
11
|
+
} from '@scallop-io/sui-kit';
|
|
12
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
13
|
+
|
|
14
|
+
type ObjectId = string;
|
|
15
|
+
class ScallopPythClient extends SuiPythClient {
|
|
16
|
+
constructor(
|
|
17
|
+
provider: SuiClient,
|
|
18
|
+
pythStateId: ObjectId,
|
|
19
|
+
wormholeStateId: ObjectId,
|
|
20
|
+
private params: {
|
|
21
|
+
// addressId?: string;
|
|
22
|
+
defaultPackageId: ObjectId;
|
|
23
|
+
gasStationId: ObjectId;
|
|
24
|
+
}
|
|
25
|
+
) {
|
|
26
|
+
super(provider, pythStateId, wormholeStateId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async updatePriceFeedsWithSponsoredBaseUpdateFee(
|
|
30
|
+
tx: Transaction,
|
|
31
|
+
updates: Buffer[],
|
|
32
|
+
feedIds: HexString[]
|
|
33
|
+
) {
|
|
34
|
+
if (!this.params) throw new Error('Please provide params');
|
|
35
|
+
const { defaultPackageId: scallopSponsorPackage, gasStationId } =
|
|
36
|
+
this.params;
|
|
37
|
+
const packageId = await this.getPythPackageId();
|
|
38
|
+
let priceUpdatesHotPotato = await this.verifyVaasAndGetHotPotato(
|
|
39
|
+
tx,
|
|
40
|
+
updates,
|
|
41
|
+
packageId
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const priceInfoObjects = [];
|
|
45
|
+
for (const feedId of feedIds) {
|
|
46
|
+
const priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
|
|
47
|
+
if (!priceInfoObjectId) {
|
|
48
|
+
throw new Error(`Price feed object not found for ID: ${feedId}`);
|
|
49
|
+
}
|
|
50
|
+
priceInfoObjects.push(priceInfoObjectId);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const clockObjectRef = tx.sharedObjectRef({
|
|
54
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
55
|
+
mutable: false,
|
|
56
|
+
initialSharedVersion: '1',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < priceInfoObjects.length; i++) {
|
|
60
|
+
const priceInfoObjectId = priceInfoObjects[i];
|
|
61
|
+
[priceUpdatesHotPotato] = tx.moveCall({
|
|
62
|
+
target: `${scallopSponsorPackage}::pyth_sponsor::update_single_price_feed_with_sponsor`,
|
|
63
|
+
arguments: [
|
|
64
|
+
tx.object(this.pythStateId),
|
|
65
|
+
priceUpdatesHotPotato,
|
|
66
|
+
tx.object(priceInfoObjectId),
|
|
67
|
+
tx.object(gasStationId),
|
|
68
|
+
clockObjectRef,
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
tx.moveCall({
|
|
74
|
+
target: `${packageId}::hot_potato_vector::destroy`,
|
|
75
|
+
arguments: [priceUpdatesHotPotato],
|
|
76
|
+
typeArguments: [`${packageId}::price_info::PriceInfo`],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const updatePythPriceFeeds = async (
|
|
82
|
+
builder: ScallopBuilder,
|
|
83
|
+
assetCoinNames: string[],
|
|
84
|
+
txBlock: SuiKitTxBlock,
|
|
85
|
+
isSponsoredTx: boolean = false
|
|
86
|
+
) => {
|
|
87
|
+
const pythClient = new ScallopPythClient(
|
|
88
|
+
builder.suiKit.client,
|
|
89
|
+
builder.address.get('core.oracles.pyth.state'),
|
|
90
|
+
builder.address.get('core.oracles.pyth.wormholeState'),
|
|
91
|
+
{
|
|
92
|
+
defaultPackageId:
|
|
93
|
+
'0xa6f9bec2f9748656b6af8aafb5d7bc1a0d5faf25ac9645fc7f447822cd509325',
|
|
94
|
+
gasStationId:
|
|
95
|
+
'0xa8b8dcc9880166edb57b53e05f8df7364d31b5d9b7d107fd27f0b69cf338b687',
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
const priceIds = assetCoinNames.map((assetCoinName) =>
|
|
99
|
+
builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feed`)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const endpoints = builder.utils.pythEndpoints ?? [
|
|
103
|
+
...builder.constants.whitelist.pythEndpoints,
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
// iterate through the endpoints
|
|
107
|
+
for (const endpoint of endpoints) {
|
|
108
|
+
try {
|
|
109
|
+
const pythConnection = new SuiPriceServiceConnection(endpoint);
|
|
110
|
+
const priceUpdateData =
|
|
111
|
+
await pythConnection.getPriceFeedsUpdateData(priceIds);
|
|
112
|
+
|
|
113
|
+
if (isSponsoredTx) {
|
|
114
|
+
// Use gas station to sponsor the baseFeeUpdate
|
|
115
|
+
await pythClient.updatePriceFeedsWithSponsoredBaseUpdateFee(
|
|
116
|
+
txBlock.txBlock,
|
|
117
|
+
priceUpdateData,
|
|
118
|
+
priceIds
|
|
119
|
+
);
|
|
120
|
+
} else {
|
|
121
|
+
await pythClient.updatePriceFeeds(
|
|
122
|
+
txBlock.txBlock,
|
|
123
|
+
priceUpdateData,
|
|
124
|
+
priceIds
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return;
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.warn(
|
|
131
|
+
`Failed to update price feeds with endpoint ${endpoint}: ${e}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ScallopBuilder } from 'src/models';
|
|
2
|
-
import { ScallopTxBlock } from 'src/types
|
|
2
|
+
import { ScallopTxBlock } from 'src/types';
|
|
3
3
|
import {
|
|
4
4
|
SUI_CLOCK_OBJECT_ID,
|
|
5
5
|
SuiTxBlock as SuiKitTxBlock,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
ReferralTxBlock,
|
|
14
14
|
SuiTxBlockWithReferralNormalMethods,
|
|
15
15
|
} from 'src/types/builder/referral';
|
|
16
|
-
import { requireSender } from '
|
|
16
|
+
import { requireSender } from 'src/utils';
|
|
17
17
|
|
|
18
18
|
const generateReferralNormalMethod: GenerateReferralNormalMethod = ({
|
|
19
19
|
builder,
|
|
@@ -111,16 +111,10 @@ const generateReferralQuickMethod: GenerateReferralQuickMethod = ({
|
|
|
111
111
|
const objToTransfer: SuiObjectArg[] = [];
|
|
112
112
|
for (const coinName of coinNames) {
|
|
113
113
|
if (coinName === 'sui') {
|
|
114
|
-
const rewardCoin =
|
|
115
|
-
veScaKey,
|
|
116
|
-
coinName
|
|
117
|
-
);
|
|
114
|
+
const rewardCoin = txBlock.claimReferralRevenue(veScaKey, coinName);
|
|
118
115
|
objToTransfer.push(rewardCoin);
|
|
119
116
|
} else {
|
|
120
|
-
const rewardCoin =
|
|
121
|
-
veScaKey,
|
|
122
|
-
coinName
|
|
123
|
-
);
|
|
117
|
+
const rewardCoin = txBlock.claimReferralRevenue(veScaKey, coinName);
|
|
124
118
|
try {
|
|
125
119
|
// get the matching user coin if exists
|
|
126
120
|
const coins = await builder.suiKit.suiInteractor.selectCoins(
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
ScallopTxBlock,
|
|
9
9
|
SuiTxBlockWithSCoinNormalMethods,
|
|
10
10
|
sCoinPkgIds,
|
|
11
|
-
} from 'src/types
|
|
12
|
-
import { requireSender } from '
|
|
11
|
+
} from 'src/types';
|
|
12
|
+
import { requireSender } from 'src/utils';
|
|
13
13
|
|
|
14
14
|
const generateSCoinNormalMethod: GenerateSCoinNormalMethod = ({
|
|
15
15
|
builder,
|