@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.
- package/dist/address-Bp_gAUMw.d.ts +165 -0
- package/dist/chunk-4GSK5DO7.js +25 -0
- package/dist/chunk-B4M6FI47.mjs +5 -0
- package/dist/constants/index.d.mts +262 -0
- package/dist/constants/index.d.ts +262 -0
- package/dist/constants/index.js +86 -0
- package/dist/constants/index.mjs +5 -0
- package/dist/models/index.d.mts +393 -0
- package/dist/models/index.d.ts +393 -0
- package/dist/models/index.js +34 -0
- package/dist/models/index.mjs +16 -0
- package/dist/queryKeys-AaZqDYle.d.ts +43 -0
- package/dist/{index.d.mts → scallopUtils-Cxm9zldY.d.ts} +1748 -2586
- package/dist/types/index.d.mts +9 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +23 -11
- package/src/builders/borrowIncentiveBuilder.ts +2 -2
- package/src/builders/coreBuilder.ts +1 -1
- package/src/builders/index.ts +2 -2
- package/src/builders/oracles/error.ts +29 -0
- package/src/builders/oracles/index.ts +115 -363
- package/src/builders/oracles/oraclePackageRegistry.ts +323 -0
- package/src/builders/oracles/priceFeedUpdater.ts +112 -0
- package/src/builders/oracles/priceUpdateRequester.ts +50 -0
- package/src/builders/oracles/xOracleUpdateStrategy.ts +178 -0
- package/src/builders/oracles/xOracleUpdater.ts +160 -0
- package/src/builders/vescaBuilder.ts +2 -2
- package/src/constants/api.ts +2 -0
- package/src/constants/common.ts +0 -3
- package/src/constants/index.ts +2 -1
- package/src/constants/package.ts +14 -0
- package/src/constants/testAddress.ts +190 -105
- package/src/constants/xoracle.ts +8 -2
- package/src/models/scallopAddress.ts +24 -4
- package/src/models/scallopBuilder.ts +4 -4
- package/src/models/scallopClient.ts +1 -1
- package/src/models/scallopConstants.ts +2 -2
- package/src/models/scallopIndexer.ts +3 -2
- package/src/models/scallopQuery.ts +52 -36
- package/src/models/scallopQueryClient.ts +1 -1
- package/src/models/scallopSuiKit.ts +1 -1
- package/src/models/scallopUtils.ts +5 -8
- package/src/queries/borrowIncentiveQuery.ts +2 -3
- package/src/queries/coreQuery.ts +2 -3
- package/src/queries/index.ts +4 -3
- package/src/queries/loyaltyProgramQuery.ts +1 -1
- package/src/queries/portfolioQuery.ts +13 -13
- package/src/queries/sCoinQuery.ts +2 -2
- package/src/queries/spoolQuery.ts +8 -8
- package/src/queries/vescaQuery.ts +2 -2
- package/src/queries/xOracleQuery.ts +20 -3
- package/src/types/address.ts +85 -47
- package/src/types/constant/index.ts +2 -1
- package/src/types/constant/package.ts +3 -0
- package/src/types/constant/xOracle.ts +10 -7
- package/src/types/query/index.ts +0 -1
- package/src/utils/builder.ts +1 -1
- package/src/utils/index.ts +2 -2
- package/src/utils/query.ts +6 -6
- package/src/utils/util.ts +1 -1
- package/dist/index.d.ts +0 -3242
- package/dist/index.js +0 -49
- package/dist/index.mjs +0 -15
- package/src/builders/oracles/pyth.ts +0 -44
- package/src/index.ts +0 -13
- package/src/queries/ownerQuery.ts +0 -32
- package/src/types/constant/enum.ts +0 -64
- package/src/types/query/sCoin.ts +0 -1
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { TransactionArgument } from '@scallop-io/sui-kit';
|
|
2
|
+
import { ScallopUtils } from 'src/models';
|
|
3
|
+
import {
|
|
4
|
+
AddressStringPath,
|
|
5
|
+
BasePackage,
|
|
6
|
+
OracleLst,
|
|
7
|
+
OracleLstConfig,
|
|
8
|
+
SupportedOracleSuiLst,
|
|
9
|
+
SupportOracleLst,
|
|
10
|
+
SupportOracleType,
|
|
11
|
+
} from 'src/types';
|
|
12
|
+
import { UnsupportedOracleError } from './error';
|
|
13
|
+
|
|
14
|
+
export type XOraclePackages = {
|
|
15
|
+
xOraclePackageId: string;
|
|
16
|
+
xOracleId: TransactionArgument | string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type LstPackages<
|
|
20
|
+
T extends SupportOracleLst,
|
|
21
|
+
U extends SupportedOracleSuiLst = SupportedOracleSuiLst,
|
|
22
|
+
> = {
|
|
23
|
+
[K in U]: OracleLst<T, U>[K] & BasePackage;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type MaybeWithLstPackage<T, U> = T extends SupportOracleLst
|
|
27
|
+
? U & { lst: LstPackages<T> }
|
|
28
|
+
: U;
|
|
29
|
+
|
|
30
|
+
type PythStaticPackages = {
|
|
31
|
+
pythPackageId: string;
|
|
32
|
+
pythRegistryId: TransactionArgument | string;
|
|
33
|
+
pythStateId: TransactionArgument | string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type PythDynamicPackages = MaybeWithLstPackage<
|
|
37
|
+
'pyth',
|
|
38
|
+
{
|
|
39
|
+
pythFeedObjectId: TransactionArgument | string;
|
|
40
|
+
}
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
export type PythPackages = PythStaticPackages & PythDynamicPackages;
|
|
44
|
+
|
|
45
|
+
type SwitchboardStaticPackages = {
|
|
46
|
+
switchboardPackageId: string;
|
|
47
|
+
switchboardRegistryId: TransactionArgument | string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type SwitchboardDynamicPackages = MaybeWithLstPackage<
|
|
51
|
+
'switchboard',
|
|
52
|
+
{
|
|
53
|
+
switchboardAggregatorId: TransactionArgument | string;
|
|
54
|
+
}
|
|
55
|
+
>;
|
|
56
|
+
|
|
57
|
+
export type SwitchboardPackages = SwitchboardStaticPackages &
|
|
58
|
+
SwitchboardDynamicPackages;
|
|
59
|
+
|
|
60
|
+
export type SupraPackages = {
|
|
61
|
+
supraPackageId: string;
|
|
62
|
+
supraHolderId: TransactionArgument | string;
|
|
63
|
+
supraRegistryId: TransactionArgument | string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type OraclePackages<T extends SupportOracleType> = T extends 'pyth'
|
|
67
|
+
? PythPackages
|
|
68
|
+
: T extends 'switchboard'
|
|
69
|
+
? SwitchboardPackages
|
|
70
|
+
: T extends 'supra'
|
|
71
|
+
? SupraPackages
|
|
72
|
+
: never;
|
|
73
|
+
|
|
74
|
+
type getLstPackagesReturnType<T> = T extends SupportOracleLst
|
|
75
|
+
? LstPackages<T, SupportedOracleSuiLst>
|
|
76
|
+
: never;
|
|
77
|
+
|
|
78
|
+
export interface IOraclePackageRegistry<
|
|
79
|
+
T extends SupportOracleType = SupportOracleType,
|
|
80
|
+
> {
|
|
81
|
+
utils: ScallopUtils;
|
|
82
|
+
oracleName: T;
|
|
83
|
+
packageId: string;
|
|
84
|
+
getLstPackages(coinName: SupportedOracleSuiLst): getLstPackagesReturnType<T>;
|
|
85
|
+
getPackages(coinName: string): OraclePackages<T>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface IHasStaticPackages {
|
|
89
|
+
getStaticPackages: Record<string, TransactionArgument | string>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class XOraclePackageRegistry
|
|
93
|
+
implements
|
|
94
|
+
Omit<
|
|
95
|
+
IOraclePackageRegistry,
|
|
96
|
+
'oracleName' | 'packageId' | 'getPackages' | 'getLstPackages'
|
|
97
|
+
>
|
|
98
|
+
{
|
|
99
|
+
constructor(readonly utils: ScallopUtils) {}
|
|
100
|
+
|
|
101
|
+
getAddressPath(path: AddressStringPath) {
|
|
102
|
+
return this.utils.address.get(path);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get getXOraclePackages() {
|
|
106
|
+
return {
|
|
107
|
+
xOraclePackageId: this.getAddressPath('core.packages.xOracle.id'),
|
|
108
|
+
xOracleId: this.getAddressPath('core.oracles.xOracle'),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
abstract class BasePackageRegistry implements IOraclePackageRegistry {
|
|
114
|
+
abstract readonly oracleName: SupportOracleType;
|
|
115
|
+
|
|
116
|
+
constructor(
|
|
117
|
+
protected readonly xOraclePackageRegistry: XOraclePackageRegistry
|
|
118
|
+
) {}
|
|
119
|
+
|
|
120
|
+
abstract getPackages(
|
|
121
|
+
coinName: string
|
|
122
|
+
): OraclePackages<typeof this.oracleName>;
|
|
123
|
+
|
|
124
|
+
abstract getLstPackages(
|
|
125
|
+
coinName: SupportedOracleSuiLst
|
|
126
|
+
): getLstPackagesReturnType<typeof this.oracleName>;
|
|
127
|
+
|
|
128
|
+
get utils() {
|
|
129
|
+
return this.xOraclePackageRegistry.utils;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get packageId() {
|
|
133
|
+
return this.xOraclePackageRegistry.getAddressPath(
|
|
134
|
+
`core.packages.${this.oracleName}.id`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
class PythPackageRegistry
|
|
140
|
+
extends BasePackageRegistry
|
|
141
|
+
implements IHasStaticPackages
|
|
142
|
+
{
|
|
143
|
+
readonly oracleName = 'pyth';
|
|
144
|
+
|
|
145
|
+
constructor(
|
|
146
|
+
protected readonly xOraclePackageRegistry: XOraclePackageRegistry
|
|
147
|
+
) {
|
|
148
|
+
super(xOraclePackageRegistry);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get getStaticPackages() {
|
|
152
|
+
return {
|
|
153
|
+
pythPackageId: this.packageId,
|
|
154
|
+
pythRegistryId: this.xOraclePackageRegistry.getAddressPath(
|
|
155
|
+
'core.oracles.pyth.registry'
|
|
156
|
+
),
|
|
157
|
+
pythStateId: this.xOraclePackageRegistry.getAddressPath(
|
|
158
|
+
'core.oracles.pyth.state'
|
|
159
|
+
),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private getLstOracleConfigPackages(coinName: SupportedOracleSuiLst) {
|
|
164
|
+
const oracleLstConfig = this.xOraclePackageRegistry.getAddressPath(
|
|
165
|
+
`core.oracles.pyth.lst.${coinName}`
|
|
166
|
+
) as OracleLstConfig<typeof coinName>[typeof coinName];
|
|
167
|
+
return oracleLstConfig;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getLstPackages(coinName: SupportedOracleSuiLst) {
|
|
171
|
+
const lstPackages = this.xOraclePackageRegistry.getAddressPath(
|
|
172
|
+
`core.packages.pyth.lst.${coinName}`
|
|
173
|
+
) as BasePackage;
|
|
174
|
+
|
|
175
|
+
// get the oracle config for the coin
|
|
176
|
+
const oracleLstConfig = this.getLstOracleConfigPackages(coinName);
|
|
177
|
+
return {
|
|
178
|
+
[coinName]: {
|
|
179
|
+
...lstPackages,
|
|
180
|
+
...oracleLstConfig,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getPackages(coinName: string): OraclePackages<'pyth'> {
|
|
186
|
+
const lstPackages = this.getLstPackages(coinName as SupportedOracleSuiLst);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
...this.getStaticPackages,
|
|
190
|
+
pythFeedObjectId: this.xOraclePackageRegistry.getAddressPath(
|
|
191
|
+
`core.coins.${coinName}.oracle.pyth.feedObject`
|
|
192
|
+
),
|
|
193
|
+
lst: lstPackages,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
class SupraPackageRegistry extends BasePackageRegistry {
|
|
199
|
+
readonly oracleName = 'supra';
|
|
200
|
+
|
|
201
|
+
constructor(
|
|
202
|
+
protected readonly xOraclePackageRegistry: XOraclePackageRegistry
|
|
203
|
+
) {
|
|
204
|
+
super(xOraclePackageRegistry);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getLstPackages(
|
|
208
|
+
_: SupportedOracleSuiLst
|
|
209
|
+
): getLstPackagesReturnType<typeof this.oracleName> {
|
|
210
|
+
throw new Error('Method not implemented.');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getPackages(_: string) {
|
|
214
|
+
return {
|
|
215
|
+
supraPackageId: this.packageId,
|
|
216
|
+
supraRegistryId: this.xOraclePackageRegistry.getAddressPath(
|
|
217
|
+
'core.oracles.supra.registry'
|
|
218
|
+
),
|
|
219
|
+
supraHolderId: this.xOraclePackageRegistry.getAddressPath(
|
|
220
|
+
'core.oracles.supra.holder'
|
|
221
|
+
),
|
|
222
|
+
} as OraclePackages<typeof this.oracleName>;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
class SwitchboardPackageRegistry
|
|
227
|
+
extends BasePackageRegistry
|
|
228
|
+
implements IHasStaticPackages
|
|
229
|
+
{
|
|
230
|
+
readonly oracleName = 'switchboard';
|
|
231
|
+
|
|
232
|
+
constructor(
|
|
233
|
+
protected readonly xOraclePackageRegistry: XOraclePackageRegistry
|
|
234
|
+
) {
|
|
235
|
+
super(xOraclePackageRegistry);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
getLstPackages(
|
|
239
|
+
_: SupportedOracleSuiLst
|
|
240
|
+
): getLstPackagesReturnType<typeof this.oracleName> {
|
|
241
|
+
throw new Error('Method not implemented.');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
get getStaticPackages() {
|
|
245
|
+
return {
|
|
246
|
+
switchboardPackageId: this.packageId,
|
|
247
|
+
switchboardRegistryId: this.xOraclePackageRegistry.getAddressPath(
|
|
248
|
+
'core.oracles.switchboard.registry'
|
|
249
|
+
),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
getPackages(coinName: string) {
|
|
254
|
+
return {
|
|
255
|
+
...this.getStaticPackages,
|
|
256
|
+
switchboardAggregatorId: this.xOraclePackageRegistry.getAddressPath(
|
|
257
|
+
`core.coins.${coinName}.oracle.switchboard`
|
|
258
|
+
),
|
|
259
|
+
} as OraclePackages<typeof this.oracleName>;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export class OraclePackageRegistry {
|
|
264
|
+
private readonly registryMap = new Map<
|
|
265
|
+
SupportOracleType,
|
|
266
|
+
IOraclePackageRegistry
|
|
267
|
+
>();
|
|
268
|
+
|
|
269
|
+
constructor(readonly xOraclePackageRegistry: XOraclePackageRegistry) {}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Register a new updater (pyth, supra, switchboard)
|
|
273
|
+
*/
|
|
274
|
+
register(
|
|
275
|
+
cb: (
|
|
276
|
+
xOraclePackageRegistry: XOraclePackageRegistry
|
|
277
|
+
) => IOraclePackageRegistry
|
|
278
|
+
): void {
|
|
279
|
+
const registry = cb(this.xOraclePackageRegistry);
|
|
280
|
+
if (this.registryMap.has(registry.oracleName)) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`Updater already registered for oracleKey: ${registry.oracleName}`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
this.registryMap.set(registry.oracleName, registry);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Retrieve the handler by key; throws if missing
|
|
290
|
+
*/
|
|
291
|
+
get(oracleName: SupportOracleType): IOraclePackageRegistry {
|
|
292
|
+
const handler = this.registryMap.get(oracleName);
|
|
293
|
+
if (!handler) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
`No XOraclePriceUpdater registered for oracle: ${oracleName}`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
return handler;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Optional: Check if a handler exists for the given key
|
|
303
|
+
*/
|
|
304
|
+
has(oracleName: SupportOracleType): boolean {
|
|
305
|
+
return this.registryMap.has(oracleName);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export const createPackageRegistry = (
|
|
310
|
+
oracleName: SupportOracleType,
|
|
311
|
+
xOraclePackageRegistry: XOraclePackageRegistry
|
|
312
|
+
): IOraclePackageRegistry => {
|
|
313
|
+
switch (oracleName) {
|
|
314
|
+
case 'pyth':
|
|
315
|
+
return new PythPackageRegistry(xOraclePackageRegistry);
|
|
316
|
+
case 'supra':
|
|
317
|
+
return new SupraPackageRegistry(xOraclePackageRegistry);
|
|
318
|
+
case 'switchboard':
|
|
319
|
+
return new SwitchboardPackageRegistry(xOraclePackageRegistry);
|
|
320
|
+
default:
|
|
321
|
+
throw new UnsupportedOracleError(oracleName);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SuiPriceServiceConnection,
|
|
3
|
+
SuiPythClient,
|
|
4
|
+
} from '@pythnetwork/pyth-sui-js';
|
|
5
|
+
import { SuiTxBlock } from '@scallop-io/sui-kit';
|
|
6
|
+
import { ScallopBuilder } from 'src/models';
|
|
7
|
+
import { SupportOracleType } from 'src/types';
|
|
8
|
+
|
|
9
|
+
type PythPriceFeedUpdateOptions = {
|
|
10
|
+
usePythPullModel: boolean;
|
|
11
|
+
useOnChainXOracleList: boolean;
|
|
12
|
+
pythSponsoredFeeds: string[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type SupraPriceFeedUpdateOptions = {};
|
|
16
|
+
type SwitchboardPriceFeedUpdateOptions = {};
|
|
17
|
+
|
|
18
|
+
export type PriceFeedUpdateOptions = PythPriceFeedUpdateOptions &
|
|
19
|
+
SupraPriceFeedUpdateOptions &
|
|
20
|
+
SwitchboardPriceFeedUpdateOptions;
|
|
21
|
+
|
|
22
|
+
export interface IPriceFeedUpdater {
|
|
23
|
+
oracleName: SupportOracleType;
|
|
24
|
+
updatePriceFeeds(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class PythPriceFeedUpdater implements IPriceFeedUpdater {
|
|
28
|
+
public readonly oracleName: SupportOracleType = 'pyth';
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
public readonly tx: SuiTxBlock,
|
|
32
|
+
private readonly builder: ScallopBuilder,
|
|
33
|
+
private readonly coinNames: string[],
|
|
34
|
+
private readonly options: {
|
|
35
|
+
usePythPullModel: boolean;
|
|
36
|
+
useOnChainXOracleList: boolean;
|
|
37
|
+
pythSponsoredFeeds: string[];
|
|
38
|
+
}
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
private filterSponsoredFeeds() {
|
|
42
|
+
const { usePythPullModel, pythSponsoredFeeds } = this.options;
|
|
43
|
+
const sponsoredFeedsSet = new Set(pythSponsoredFeeds);
|
|
44
|
+
|
|
45
|
+
return this.coinNames.filter((coinName) => {
|
|
46
|
+
const notUsingPullAndNotSponsored =
|
|
47
|
+
!usePythPullModel && !sponsoredFeedsSet.has(coinName);
|
|
48
|
+
return usePythPullModel || notUsingPullAndNotSponsored;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async updatePriceFeeds(): Promise<void> {
|
|
53
|
+
const pythClient = new SuiPythClient(
|
|
54
|
+
this.builder.suiKit.client,
|
|
55
|
+
this.builder.address.get('core.oracles.pyth.state'),
|
|
56
|
+
this.builder.address.get('core.oracles.pyth.wormholeState')
|
|
57
|
+
);
|
|
58
|
+
const filteredCoinNames = this.filterSponsoredFeeds();
|
|
59
|
+
if (filteredCoinNames.length === 0) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const priceIds = filteredCoinNames.map((assetCoinName) =>
|
|
63
|
+
this.builder.address.get(`core.coins.${assetCoinName}.oracle.pyth.feed`)
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// iterate through the endpoints
|
|
67
|
+
const endpoints = this.builder.utils.pythEndpoints ?? [
|
|
68
|
+
...this.builder.constants.whitelist.pythEndpoints,
|
|
69
|
+
];
|
|
70
|
+
for (const endpoint of endpoints) {
|
|
71
|
+
try {
|
|
72
|
+
const pythConnection = new SuiPriceServiceConnection(endpoint);
|
|
73
|
+
const priceUpdateData =
|
|
74
|
+
await pythConnection.getPriceFeedsUpdateData(priceIds);
|
|
75
|
+
await pythClient.updatePriceFeeds(
|
|
76
|
+
this.tx.txBlock,
|
|
77
|
+
priceUpdateData,
|
|
78
|
+
priceIds
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
break;
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.warn(
|
|
84
|
+
`Failed to update price feeds with endpoint ${endpoint}: ${e}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const createPriceFeedUpdater = (
|
|
92
|
+
oracleName: SupportOracleType,
|
|
93
|
+
tx: SuiTxBlock,
|
|
94
|
+
builder: ScallopBuilder,
|
|
95
|
+
coinNames: string[],
|
|
96
|
+
options: {
|
|
97
|
+
usePythPullModel: boolean;
|
|
98
|
+
useOnChainXOracleList: boolean;
|
|
99
|
+
pythSponsoredFeeds: string[];
|
|
100
|
+
}
|
|
101
|
+
) => {
|
|
102
|
+
switch (oracleName) {
|
|
103
|
+
case 'pyth':
|
|
104
|
+
return new PythPriceFeedUpdater(tx, builder, coinNames, options);
|
|
105
|
+
case 'supra':
|
|
106
|
+
throw new Error('Supra price feed updater is not implemented yet.');
|
|
107
|
+
case 'switchboard':
|
|
108
|
+
throw new Error('Switchboard price feed updater is not implemented yet.');
|
|
109
|
+
default:
|
|
110
|
+
throw new Error(`Unsupported oracle type: ${oracleName}`);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SUI_CLOCK_OBJECT_ID,
|
|
3
|
+
SuiTxBlock,
|
|
4
|
+
TransactionArgument,
|
|
5
|
+
} from '@scallop-io/sui-kit';
|
|
6
|
+
import { XOraclePackageRegistry } from './oraclePackageRegistry';
|
|
7
|
+
|
|
8
|
+
interface IPriceUpdateRequester {
|
|
9
|
+
buildRequest(coinName: string): TransactionArgument;
|
|
10
|
+
confirmRequest(coinName: string, request: TransactionArgument): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class PriceUpdateRequester implements IPriceUpdateRequester {
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly txBlock: SuiTxBlock,
|
|
16
|
+
private readonly xOraclePackageRegistry: XOraclePackageRegistry
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
get utils() {
|
|
20
|
+
return this.xOraclePackageRegistry.utils;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
buildRequest(coinName: string): TransactionArgument {
|
|
24
|
+
const { xOraclePackageId, xOracleId } =
|
|
25
|
+
this.xOraclePackageRegistry.getXOraclePackages;
|
|
26
|
+
const target = `${xOraclePackageId}::x_oracle::price_update_request`;
|
|
27
|
+
const typeArgs = [this.utils.parseCoinType(coinName)];
|
|
28
|
+
return this.txBlock.moveCall(target, [xOracleId], typeArgs);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
confirmRequest(coinName: string, request: TransactionArgument): void {
|
|
32
|
+
const { xOraclePackageId, xOracleId } =
|
|
33
|
+
this.xOraclePackageRegistry.getXOraclePackages;
|
|
34
|
+
const target = `${xOraclePackageId}::x_oracle::confirm_price_update_request`;
|
|
35
|
+
const typeArgs = [this.utils.parseCoinType(coinName)];
|
|
36
|
+
this.txBlock.moveCall(
|
|
37
|
+
target,
|
|
38
|
+
[
|
|
39
|
+
xOracleId,
|
|
40
|
+
request,
|
|
41
|
+
this.txBlock.sharedObjectRef({
|
|
42
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
43
|
+
mutable: false,
|
|
44
|
+
initialSharedVersion: '1',
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
typeArgs
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SUI_CLOCK_OBJECT_ID,
|
|
3
|
+
SuiTxBlock,
|
|
4
|
+
TransactionArgument,
|
|
5
|
+
} from '@scallop-io/sui-kit';
|
|
6
|
+
import { IOraclePackageRegistry } from './oraclePackageRegistry';
|
|
7
|
+
import {
|
|
8
|
+
SupportedOracleSuiLst,
|
|
9
|
+
SupportOracleType,
|
|
10
|
+
xOracleRuleType,
|
|
11
|
+
} from 'src/types';
|
|
12
|
+
import { UnsupportedLstOracleError } from './error';
|
|
13
|
+
|
|
14
|
+
export interface IXOracleUpdateStrategy<
|
|
15
|
+
T extends SupportOracleType,
|
|
16
|
+
U extends string = string,
|
|
17
|
+
> {
|
|
18
|
+
oracleType: T;
|
|
19
|
+
updatePrice(
|
|
20
|
+
tx: SuiTxBlock,
|
|
21
|
+
request: TransactionArgument,
|
|
22
|
+
coinName: U,
|
|
23
|
+
rule: xOracleRuleType
|
|
24
|
+
): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
abstract class BaseUpdateStrategy<
|
|
28
|
+
T extends SupportOracleType,
|
|
29
|
+
U extends string = string,
|
|
30
|
+
> implements IXOracleUpdateStrategy<T, U>
|
|
31
|
+
{
|
|
32
|
+
constructor(protected readonly registry: IOraclePackageRegistry<T>) {}
|
|
33
|
+
abstract readonly oracleType: T;
|
|
34
|
+
|
|
35
|
+
protected get clockObject() {
|
|
36
|
+
return {
|
|
37
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
38
|
+
mutable: false,
|
|
39
|
+
initialSharedVersion: '1',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected get utils() {
|
|
44
|
+
return this.registry.utils;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
abstract updatePrice(
|
|
48
|
+
tx: SuiTxBlock,
|
|
49
|
+
request: TransactionArgument,
|
|
50
|
+
coinName: string,
|
|
51
|
+
rule: xOracleRuleType
|
|
52
|
+
): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class PythDefaultUpdateStrategy extends BaseUpdateStrategy<'pyth'> {
|
|
56
|
+
readonly oracleType = 'pyth';
|
|
57
|
+
constructor(protected readonly registry: IOraclePackageRegistry<'pyth'>) {
|
|
58
|
+
super(registry);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
updatePrice(
|
|
62
|
+
tx: SuiTxBlock,
|
|
63
|
+
request: TransactionArgument,
|
|
64
|
+
coinName: string,
|
|
65
|
+
rule: xOracleRuleType
|
|
66
|
+
): void {
|
|
67
|
+
const { pythFeedObjectId, pythRegistryId, pythStateId, pythPackageId } =
|
|
68
|
+
this.registry.getPackages(coinName);
|
|
69
|
+
tx.moveCall(
|
|
70
|
+
`${pythPackageId}::rule::set_price_as_${rule}`,
|
|
71
|
+
[
|
|
72
|
+
request,
|
|
73
|
+
pythStateId,
|
|
74
|
+
pythFeedObjectId,
|
|
75
|
+
pythRegistryId,
|
|
76
|
+
tx.sharedObjectRef({
|
|
77
|
+
objectId: SUI_CLOCK_OBJECT_ID,
|
|
78
|
+
mutable: false,
|
|
79
|
+
initialSharedVersion: '1',
|
|
80
|
+
}),
|
|
81
|
+
],
|
|
82
|
+
[this.utils.parseCoinType(coinName)]
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export class PythSuiLstUpdateStrategy extends BaseUpdateStrategy<
|
|
87
|
+
'pyth',
|
|
88
|
+
SupportedOracleSuiLst
|
|
89
|
+
> {
|
|
90
|
+
readonly oracleType = 'pyth';
|
|
91
|
+
constructor(protected readonly registry: IOraclePackageRegistry<'pyth'>) {
|
|
92
|
+
super(registry);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
updatePrice(
|
|
96
|
+
tx: SuiTxBlock,
|
|
97
|
+
request: TransactionArgument,
|
|
98
|
+
coinName: SupportedOracleSuiLst,
|
|
99
|
+
rule: xOracleRuleType
|
|
100
|
+
): void {
|
|
101
|
+
const { lst, pythFeedObjectId, pythStateId } =
|
|
102
|
+
this.registry.getPackages(coinName);
|
|
103
|
+
if (!lst[coinName]) {
|
|
104
|
+
throw new UnsupportedLstOracleError(coinName, this.oracleType);
|
|
105
|
+
}
|
|
106
|
+
const { id, configId, stakedSuiVaultId, safeId } = lst[coinName];
|
|
107
|
+
tx.moveCall(`${id}::rule::set_price_as_${rule}`, [
|
|
108
|
+
request,
|
|
109
|
+
pythStateId,
|
|
110
|
+
pythFeedObjectId,
|
|
111
|
+
configId,
|
|
112
|
+
stakedSuiVaultId,
|
|
113
|
+
safeId,
|
|
114
|
+
tx.sharedObjectRef(this.clockObject),
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export class SupraDefaultUpdateStrategy extends BaseUpdateStrategy<'supra'> {
|
|
120
|
+
readonly oracleType = 'supra';
|
|
121
|
+
constructor(protected readonly registry: IOraclePackageRegistry<'supra'>) {
|
|
122
|
+
super(registry);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
updatePrice(
|
|
126
|
+
tx: SuiTxBlock,
|
|
127
|
+
request: TransactionArgument,
|
|
128
|
+
coinName: string,
|
|
129
|
+
rule: xOracleRuleType
|
|
130
|
+
): void {
|
|
131
|
+
const { supraPackageId, supraHolderId, supraRegistryId } =
|
|
132
|
+
this.registry.getPackages(coinName);
|
|
133
|
+
|
|
134
|
+
tx.moveCall(
|
|
135
|
+
`${supraPackageId}::rule::set_price_as_${rule}`,
|
|
136
|
+
[
|
|
137
|
+
request,
|
|
138
|
+
supraHolderId,
|
|
139
|
+
supraRegistryId,
|
|
140
|
+
tx.sharedObjectRef(this.clockObject),
|
|
141
|
+
],
|
|
142
|
+
[this.utils.parseCoinType(coinName)]
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class SwitchboardDefaultUpdateStrategy extends BaseUpdateStrategy<'switchboard'> {
|
|
148
|
+
readonly oracleType = 'switchboard';
|
|
149
|
+
constructor(
|
|
150
|
+
protected readonly registry: IOraclePackageRegistry<'switchboard'>
|
|
151
|
+
) {
|
|
152
|
+
super(registry);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
updatePrice(
|
|
156
|
+
tx: SuiTxBlock,
|
|
157
|
+
request: TransactionArgument,
|
|
158
|
+
coinName: string,
|
|
159
|
+
rule: xOracleRuleType
|
|
160
|
+
): void {
|
|
161
|
+
const {
|
|
162
|
+
switchboardPackageId,
|
|
163
|
+
switchboardAggregatorId,
|
|
164
|
+
switchboardRegistryId,
|
|
165
|
+
} = this.registry.getPackages(coinName);
|
|
166
|
+
|
|
167
|
+
tx.moveCall(
|
|
168
|
+
`${switchboardPackageId}::rule::set_price_as_${rule}`,
|
|
169
|
+
[
|
|
170
|
+
request,
|
|
171
|
+
switchboardAggregatorId,
|
|
172
|
+
switchboardRegistryId,
|
|
173
|
+
tx.sharedObjectRef(this.clockObject),
|
|
174
|
+
],
|
|
175
|
+
[this.utils.parseCoinType(coinName)]
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|