@zofai/zo-sdk 0.2.13 → 0.2.15
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/.claude/settings.local.json +11 -1
- package/dist/abstract/BaseDataAPI.cjs +1 -1
- package/dist/abstract/BaseDataAPI.cjs.map +1 -1
- package/dist/abstract/BaseDataAPI.mjs +1 -1
- package/dist/abstract/BaseDataAPI.mjs.map +1 -1
- package/dist/consts/deployments-usdz-mainnet.json +1 -31
- package/dist/consts/deployments-zo-oracle-mainnet.json +329 -0
- package/dist/consts/index.cjs +35 -1
- package/dist/consts/index.cjs.map +1 -1
- package/dist/consts/index.d.cts +45 -0
- package/dist/consts/index.d.cts.map +1 -1
- package/dist/consts/index.d.mts +45 -0
- package/dist/consts/index.d.mts.map +1 -1
- package/dist/consts/index.mjs +31 -0
- package/dist/consts/index.mjs.map +1 -1
- package/dist/data.cjs +1 -1
- package/dist/data.cjs.map +1 -1
- package/dist/data.mjs +1 -1
- package/dist/data.mjs.map +1 -1
- package/dist/implementations/USDZAPI.cjs +426 -78
- package/dist/implementations/USDZAPI.cjs.map +1 -1
- package/dist/implementations/USDZAPI.d.cts +54 -0
- package/dist/implementations/USDZAPI.d.cts.map +1 -1
- package/dist/implementations/USDZAPI.d.mts +54 -0
- package/dist/implementations/USDZAPI.d.mts.map +1 -1
- package/dist/implementations/USDZAPI.mjs +427 -79
- package/dist/implementations/USDZAPI.mjs.map +1 -1
- package/dist/implementations/USDZDataAPI.cjs +38 -0
- package/dist/implementations/USDZDataAPI.cjs.map +1 -1
- package/dist/implementations/USDZDataAPI.d.cts +16 -0
- package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
- package/dist/implementations/USDZDataAPI.d.mts +16 -0
- package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
- package/dist/implementations/USDZDataAPI.mjs +38 -0
- package/dist/implementations/USDZDataAPI.mjs.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/interfaces/base.d.cts +19 -1
- package/dist/interfaces/base.d.cts.map +1 -1
- package/dist/interfaces/base.d.mts +19 -1
- package/dist/interfaces/base.d.mts.map +1 -1
- package/dist/interfaces/usdz.d.cts +17 -0
- package/dist/interfaces/usdz.d.cts.map +1 -1
- package/dist/interfaces/usdz.d.mts +17 -0
- package/dist/interfaces/usdz.d.mts.map +1 -1
- package/dist/oracle.cjs +119 -1
- package/dist/oracle.cjs.map +1 -1
- package/dist/oracle.d.cts +57 -1
- package/dist/oracle.d.cts.map +1 -1
- package/dist/oracle.d.mts +57 -1
- package/dist/oracle.d.mts.map +1 -1
- package/dist/oracle.mjs +120 -2
- package/dist/oracle.mjs.map +1 -1
- package/dist/oraclePro.cjs +214 -0
- package/dist/oraclePro.cjs.map +1 -0
- package/dist/oraclePro.d.cts +92 -0
- package/dist/oraclePro.d.cts.map +1 -0
- package/dist/oraclePro.d.mts +92 -0
- package/dist/oraclePro.d.mts.map +1 -0
- package/dist/oraclePro.mjs +196 -0
- package/dist/oraclePro.mjs.map +1 -0
- package/dist/pythProClient.cjs +277 -0
- package/dist/pythProClient.cjs.map +1 -0
- package/dist/pythProClient.d.cts +143 -0
- package/dist/pythProClient.d.cts.map +1 -0
- package/dist/pythProClient.d.mts +143 -0
- package/dist/pythProClient.d.mts.map +1 -0
- package/dist/pythProClient.mjs +269 -0
- package/dist/pythProClient.mjs.map +1 -0
- package/dist/storkClient.cjs +217 -0
- package/dist/storkClient.cjs.map +1 -0
- package/dist/storkClient.d.cts +90 -0
- package/dist/storkClient.d.cts.map +1 -0
- package/dist/storkClient.d.mts +90 -0
- package/dist/storkClient.d.mts.map +1 -0
- package/dist/storkClient.mjs +208 -0
- package/dist/storkClient.mjs.map +1 -0
- package/dist/storkOracle.cjs +61 -0
- package/dist/storkOracle.cjs.map +1 -0
- package/dist/storkOracle.d.cts +21 -0
- package/dist/storkOracle.d.cts.map +1 -0
- package/dist/storkOracle.d.mts +21 -0
- package/dist/storkOracle.d.mts.map +1 -0
- package/dist/storkOracle.mjs +56 -0
- package/dist/storkOracle.mjs.map +1 -0
- package/package.json +1 -1
- package/src/abstract/BaseDataAPI.ts +1 -1
- package/src/consts/deployments-usdz-mainnet.json +1 -31
- package/src/consts/deployments-zo-oracle-mainnet.json +329 -0
- package/src/consts/index.ts +80 -0
- package/src/data.ts +1 -1
- package/src/implementations/USDZAPI.ts +731 -101
- package/src/implementations/USDZDataAPI.ts +42 -0
- package/src/index.ts +3 -0
- package/src/interfaces/base.ts +54 -1
- package/src/interfaces/usdz.ts +125 -0
- package/src/oracle.ts +222 -1
- package/src/oraclePro.ts +312 -0
- package/src/pythProClient.ts +406 -0
- package/src/storkClient.ts +328 -0
- package/src/storkOracle.ts +82 -0
- package/tests/pythProClient.test.ts +155 -0
- package/tests/storkClient.test.ts +316 -0
|
@@ -10,6 +10,8 @@ import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils'
|
|
|
10
10
|
|
|
11
11
|
import { BaseDataAPI } from '../abstract'
|
|
12
12
|
import type { Network } from '../consts'
|
|
13
|
+
import type { OracleInputs } from '../oraclePro'
|
|
14
|
+
import { valuateSymbolsV2, valuateVaultsV2 } from '../oraclePro'
|
|
13
15
|
import { LPToken, SECONDS_PER_EIGHT_HOUR, USDZ_TOKEN_DECIMALS } from '../consts'
|
|
14
16
|
import type {
|
|
15
17
|
IBaseHistoryResponse,
|
|
@@ -203,6 +205,46 @@ export class USDZDataAPI extends BaseDataAPI implements IUSDZDataAPI {
|
|
|
203
205
|
return { vaultsValuation, symbolsValuation }
|
|
204
206
|
}
|
|
205
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Creates vaults valuation using valuate_vault_v2 (Pyth Pro + Stork).
|
|
210
|
+
*/
|
|
211
|
+
public valuateVaultsV2(tx: Transaction, oracle: OracleInputs) {
|
|
212
|
+
return valuateVaultsV2({
|
|
213
|
+
tx,
|
|
214
|
+
upgradedPackage: this.consts.zoCore.upgradedPackage,
|
|
215
|
+
lpType: `${this.consts.zoCore.package}::usdz::USDZ`,
|
|
216
|
+
market: this.consts.zoCore.market,
|
|
217
|
+
vaults: this.consts.zoCore.vaults,
|
|
218
|
+
coinModules: this.consts.coins,
|
|
219
|
+
oracle,
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Creates symbols valuation using valuate_symbol_v2 (Pyth Pro + Stork).
|
|
225
|
+
*/
|
|
226
|
+
public valuateSymbolsV2(tx: Transaction, oracle: OracleInputs) {
|
|
227
|
+
return valuateSymbolsV2({
|
|
228
|
+
tx,
|
|
229
|
+
upgradedPackage: this.consts.zoCore.upgradedPackage,
|
|
230
|
+
marketPackage: this.consts.zoCore.package,
|
|
231
|
+
lpType: `${this.consts.zoCore.package}::usdz::USDZ`,
|
|
232
|
+
market: this.consts.zoCore.market,
|
|
233
|
+
symbols: this.consts.zoCore.symbols,
|
|
234
|
+
coinModules: this.consts.coins,
|
|
235
|
+
oracle,
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Creates both vaults and symbols valuation (Pyth Pro + Stork).
|
|
241
|
+
*/
|
|
242
|
+
public valuateV2(tx: Transaction, oracle: OracleInputs) {
|
|
243
|
+
const vaultsValuation = this.valuateVaultsV2(tx, oracle)
|
|
244
|
+
const symbolsValuation = this.valuateSymbolsV2(tx, oracle)
|
|
245
|
+
return { vaultsValuation, symbolsValuation }
|
|
246
|
+
}
|
|
247
|
+
|
|
206
248
|
/**
|
|
207
249
|
* Valuates the USDZ market
|
|
208
250
|
*/
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,9 @@ export * from './coins'
|
|
|
29
29
|
export * from './consts'
|
|
30
30
|
export * from './data'
|
|
31
31
|
export * from './oracle'
|
|
32
|
+
export * from './oraclePro'
|
|
33
|
+
export * from './storkClient'
|
|
34
|
+
export * from './storkOracle'
|
|
32
35
|
export * from './utils'
|
|
33
36
|
|
|
34
37
|
// Re-export commonly used types from Sui SDK
|
package/src/interfaces/base.ts
CHANGED
|
@@ -8,7 +8,15 @@ import type { Transaction, TransactionObjectArgument } from '@mysten/sui/transac
|
|
|
8
8
|
import type { PriceFeed } from '@pythnetwork/pyth-sui-js'
|
|
9
9
|
|
|
10
10
|
import type { IConsts, LPToken, Network } from '../consts'
|
|
11
|
-
import type { IInitOracleTxbResult } from '../oracle'
|
|
11
|
+
import type { IInitOracleTxbResult, IInitPythProOracleOptions } from '../oracle'
|
|
12
|
+
import type { IInitPythProOracleTxbResult } from '../oraclePro'
|
|
13
|
+
import type {
|
|
14
|
+
IGetLatestPythProPricesOptions,
|
|
15
|
+
IPythProStreamSubscription,
|
|
16
|
+
PythProLatestPriceData,
|
|
17
|
+
PythProStreamClient,
|
|
18
|
+
PythProStreamUpdate,
|
|
19
|
+
} from '../pythProClient'
|
|
12
20
|
import type { SuiClient } from '../suiClient'
|
|
13
21
|
|
|
14
22
|
// Common data interfaces
|
|
@@ -301,6 +309,51 @@ export interface IBaseDataAPI {
|
|
|
301
309
|
sponsorOptions?: { sender: string, additionalSuiAmount?: bigint },
|
|
302
310
|
) => Promise<IInitOracleTxbResult>
|
|
303
311
|
|
|
312
|
+
/** Pyth Pro + Stork: Stork updates + parse_and_verify_le_ecdsa_update_v2 PTB prelude. */
|
|
313
|
+
initV3OracleTxb: (
|
|
314
|
+
tokens: string[],
|
|
315
|
+
tx?: Transaction,
|
|
316
|
+
options?: IInitPythProOracleOptions,
|
|
317
|
+
) => Promise<IInitPythProOracleTxbResult>
|
|
318
|
+
|
|
319
|
+
/** @deprecated Alias for {@link initV3OracleTxb}. */
|
|
320
|
+
initPythProOracleTxb: (
|
|
321
|
+
tokens: string[],
|
|
322
|
+
tx?: Transaction,
|
|
323
|
+
options?: IInitPythProOracleOptions,
|
|
324
|
+
) => Promise<IInitPythProOracleTxbResult>
|
|
325
|
+
|
|
326
|
+
resolveStorkAssetsForTokens: (tokens: string[]) => string[]
|
|
327
|
+
|
|
328
|
+
fetchStorkUpdateDataForTokens: (tokens: string[]) => Promise<import('../storkClient').IStorkUpdateData[]>
|
|
329
|
+
|
|
330
|
+
estimateStorkUpdateFeeForTokens: (tokens: string[]) => bigint
|
|
331
|
+
|
|
332
|
+
fetchPythProUpdateBytesForTokens: (
|
|
333
|
+
tokens: string[],
|
|
334
|
+
options?: IInitPythProOracleOptions,
|
|
335
|
+
) => Promise<Uint8Array>
|
|
336
|
+
|
|
337
|
+
/** Resolve SDK token ids to Pyth Lazer numeric feed ids. */
|
|
338
|
+
resolveLazerFeedIdsForTokens: (tokens: string[]) => number[]
|
|
339
|
+
|
|
340
|
+
/** Latest Pyth Pro snapshot via kronos REST. Requires apiEndpoint. */
|
|
341
|
+
getLatestPythProPricesForTokens: (
|
|
342
|
+
tokens: string[],
|
|
343
|
+
options?: Omit<IGetLatestPythProPricesOptions, 'priceFeedIds'>,
|
|
344
|
+
) => Promise<PythProLatestPriceData>
|
|
345
|
+
|
|
346
|
+
/** kronos WebSocket client for `/pyth-pro/stream`. Requires apiEndpoint. */
|
|
347
|
+
createPythProStreamClient: () => PythProStreamClient
|
|
348
|
+
|
|
349
|
+
/** Live Pyth Pro prices via kronos WebSocket. Requires apiEndpoint. */
|
|
350
|
+
subPythProPricesForTokens: (
|
|
351
|
+
tokens: string[],
|
|
352
|
+
onUpdate: (update: PythProStreamUpdate) => void,
|
|
353
|
+
options?: Omit<IPythProStreamSubscription, 'subscriptionId' | 'priceFeedIds'>,
|
|
354
|
+
subscriptionId?: number,
|
|
355
|
+
) => Promise<() => void>
|
|
356
|
+
|
|
304
357
|
// Utility methods
|
|
305
358
|
validateCache: () => void
|
|
306
359
|
}
|
package/src/interfaces/usdz.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions'
|
|
7
7
|
|
|
8
|
+
import type { OracleInputs } from '../oraclePro'
|
|
8
9
|
import type {
|
|
9
10
|
IBaseAPI,
|
|
10
11
|
IBaseCredential,
|
|
@@ -139,6 +140,9 @@ export interface IUSDZDataAPI extends IBaseDataAPI {
|
|
|
139
140
|
getSymbolConfig: (indexToken: string, long: boolean) => Promise<IUSDZSymbolConfig | null>
|
|
140
141
|
getPriceImpactConfig: (indexToken: string) => Promise<IUSDZPriceImpactConfig | null>
|
|
141
142
|
calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
|
|
143
|
+
valuateVaultsV2: (tx: Transaction, oracle: OracleInputs) => TransactionObjectArgument
|
|
144
|
+
valuateSymbolsV2: (tx: Transaction, oracle: OracleInputs) => TransactionObjectArgument
|
|
145
|
+
valuateV2: (tx: Transaction, oracle: OracleInputs) => { vaultsValuation: TransactionObjectArgument, symbolsValuation: TransactionObjectArgument }
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
// USDZ-specific API interface
|
|
@@ -199,4 +203,125 @@ export interface IUSDZAPI extends IBaseAPI {
|
|
|
199
203
|
minAmountOut?: number,
|
|
200
204
|
tx?: Transaction,
|
|
201
205
|
) => Promise<TransactionObjectArgument>
|
|
206
|
+
|
|
207
|
+
/** Pyth Pro + Stork swap (transfers output). */
|
|
208
|
+
swapV3: (
|
|
209
|
+
fromToken: string,
|
|
210
|
+
toToken: string,
|
|
211
|
+
fromAmount: bigint,
|
|
212
|
+
fromCoinObjects: string[],
|
|
213
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
214
|
+
minAmountOut?: number,
|
|
215
|
+
tx?: Transaction,
|
|
216
|
+
) => Promise<Transaction>
|
|
217
|
+
|
|
218
|
+
/** Pyth Pro + Stork swap PTB (returns output coin). */
|
|
219
|
+
swapV3Ptb: (
|
|
220
|
+
fromToken: string,
|
|
221
|
+
toToken: string,
|
|
222
|
+
fromAmount: bigint,
|
|
223
|
+
fromCoinObjects: string[],
|
|
224
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
225
|
+
minAmountOut?: number,
|
|
226
|
+
tx?: Transaction,
|
|
227
|
+
) => Promise<TransactionObjectArgument>
|
|
228
|
+
|
|
229
|
+
openPositionV3: (
|
|
230
|
+
collateralToken: string,
|
|
231
|
+
indexToken: string,
|
|
232
|
+
size: bigint,
|
|
233
|
+
collateralAmount: bigint,
|
|
234
|
+
coinObjects: string[],
|
|
235
|
+
long: boolean,
|
|
236
|
+
reserveAmount: bigint,
|
|
237
|
+
indexPrice: number,
|
|
238
|
+
collateralPrice: number,
|
|
239
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
240
|
+
isLimitOrder?: boolean,
|
|
241
|
+
isIocOrder?: boolean,
|
|
242
|
+
pricesSlippage?: number,
|
|
243
|
+
collateralSlippage?: number,
|
|
244
|
+
relayerFee?: bigint,
|
|
245
|
+
referralAddress?: string,
|
|
246
|
+
sender?: string,
|
|
247
|
+
sponsoredTx?: boolean,
|
|
248
|
+
) => Promise<Transaction>
|
|
249
|
+
|
|
250
|
+
openPositionWithSCardV3: (
|
|
251
|
+
collateralToken: string,
|
|
252
|
+
indexToken: string,
|
|
253
|
+
size: bigint,
|
|
254
|
+
collateralAmount: bigint,
|
|
255
|
+
coinObjects: string[],
|
|
256
|
+
long: boolean,
|
|
257
|
+
reserveAmount: bigint,
|
|
258
|
+
indexPrice: number,
|
|
259
|
+
collateralPrice: number,
|
|
260
|
+
kioskClient: import('@mysten/kiosk').KioskClient,
|
|
261
|
+
kioskCap: import('@mysten/kiosk').KioskOwnerCap,
|
|
262
|
+
scard: string,
|
|
263
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
264
|
+
isLimitOrder?: boolean,
|
|
265
|
+
isIocOrder?: boolean,
|
|
266
|
+
pricesSlippage?: number,
|
|
267
|
+
collateralSlippage?: number,
|
|
268
|
+
relayerFee?: bigint,
|
|
269
|
+
referralAddress?: string,
|
|
270
|
+
sender?: string,
|
|
271
|
+
sponsoredTx?: boolean,
|
|
272
|
+
) => Promise<Transaction>
|
|
273
|
+
|
|
274
|
+
decreasePositionV3: (
|
|
275
|
+
pcpId: string,
|
|
276
|
+
collateralToken: string,
|
|
277
|
+
indexToken: string,
|
|
278
|
+
amount: bigint,
|
|
279
|
+
long: boolean,
|
|
280
|
+
indexPrice: number,
|
|
281
|
+
collateralPrice: number,
|
|
282
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
283
|
+
isTriggerOrder?: boolean,
|
|
284
|
+
isTakeProfitOrder?: boolean,
|
|
285
|
+
isIocOrder?: boolean,
|
|
286
|
+
pricesSlippage?: number,
|
|
287
|
+
collateralSlippage?: number,
|
|
288
|
+
relayerFee?: bigint,
|
|
289
|
+
coinObjects?: string[],
|
|
290
|
+
sponsoredTx?: boolean,
|
|
291
|
+
sender?: string,
|
|
292
|
+
) => Promise<Transaction>
|
|
293
|
+
|
|
294
|
+
decreasePositionWithSCardV3: (
|
|
295
|
+
pcpId: string,
|
|
296
|
+
collateralToken: string,
|
|
297
|
+
indexToken: string,
|
|
298
|
+
amount: bigint,
|
|
299
|
+
long: boolean,
|
|
300
|
+
indexPrice: number,
|
|
301
|
+
collateralPrice: number,
|
|
302
|
+
kioskClient: import('@mysten/kiosk').KioskClient,
|
|
303
|
+
kioskCap: import('@mysten/kiosk').KioskOwnerCap,
|
|
304
|
+
scard: string,
|
|
305
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
306
|
+
isTriggerOrder?: boolean,
|
|
307
|
+
isTakeProfitOrder?: boolean,
|
|
308
|
+
isIocOrder?: boolean,
|
|
309
|
+
pricesSlippage?: number,
|
|
310
|
+
collateralSlippage?: number,
|
|
311
|
+
relayerFee?: bigint,
|
|
312
|
+
coinObjects?: string[],
|
|
313
|
+
sponsoredTx?: boolean,
|
|
314
|
+
sender?: string,
|
|
315
|
+
) => Promise<Transaction>
|
|
316
|
+
|
|
317
|
+
/** Pyth Pro path (not legacy feeder v2). */
|
|
318
|
+
redeemFromPositionV2: (
|
|
319
|
+
pcpId: string,
|
|
320
|
+
collateralToken: string,
|
|
321
|
+
indexToken: string,
|
|
322
|
+
amount: number,
|
|
323
|
+
long: boolean,
|
|
324
|
+
pythProUpdateBytes: Uint8Array | number[],
|
|
325
|
+
tx?: Transaction,
|
|
326
|
+
) => Promise<Transaction>
|
|
202
327
|
}
|
package/src/oracle.ts
CHANGED
|
@@ -5,7 +5,47 @@ import { SuiPriceServiceConnection, SuiPythClient } from '@pythnetwork/pyth-sui-
|
|
|
5
5
|
|
|
6
6
|
import { resolveSpendableSuiCoin } from './coins'
|
|
7
7
|
import type { IConsts, Network } from './consts'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
buildOracleProConfig,
|
|
10
|
+
DEFAULT_API_ENDPOINT,
|
|
11
|
+
getConsts,
|
|
12
|
+
getPriceIdToPythFeeder,
|
|
13
|
+
getPythFeederToId,
|
|
14
|
+
getPythFeederToPriceId,
|
|
15
|
+
getSharedConfig,
|
|
16
|
+
getZoOracleConfig,
|
|
17
|
+
LPToken,
|
|
18
|
+
} from './consts'
|
|
19
|
+
import type {
|
|
20
|
+
IFetchPythProUpdateOptions,
|
|
21
|
+
IInitPythProOracleTxbResult,
|
|
22
|
+
OracleInputs,
|
|
23
|
+
} from './oraclePro'
|
|
24
|
+
import {
|
|
25
|
+
buildOracleInputs,
|
|
26
|
+
buildStorkAssetIdMap,
|
|
27
|
+
fetchPythProUpdateBytes,
|
|
28
|
+
parseAndVerifyPythProUpdate,
|
|
29
|
+
resolveLazerFeedIds,
|
|
30
|
+
resolveStorkAssetsForTokens,
|
|
31
|
+
} from './oraclePro'
|
|
32
|
+
import type {
|
|
33
|
+
IGetLatestPythProPricesOptions,
|
|
34
|
+
IPythProStreamSubscription,
|
|
35
|
+
PythProChannel,
|
|
36
|
+
PythProLatestPriceData,
|
|
37
|
+
PythProStreamUpdate,
|
|
38
|
+
} from './pythProClient'
|
|
39
|
+
import {
|
|
40
|
+
getLatestPythProPrices,
|
|
41
|
+
PythProStreamClient,
|
|
42
|
+
} from './pythProClient'
|
|
43
|
+
import type { IStorkUpdateData } from './storkClient'
|
|
44
|
+
import { fetchStorkUpdateDataFromKronos } from './storkClient'
|
|
45
|
+
import {
|
|
46
|
+
appendStorkUpdatesToTransaction,
|
|
47
|
+
estimateStorkUpdateFeeMist,
|
|
48
|
+
} from './storkOracle'
|
|
9
49
|
import type { SuiClient } from './suiClient'
|
|
10
50
|
import { createJsonRpcProvider } from './utils'
|
|
11
51
|
|
|
@@ -15,6 +55,17 @@ export interface IInitOracleSponsorOptions {
|
|
|
15
55
|
additionalSuiAmount?: bigint
|
|
16
56
|
}
|
|
17
57
|
|
|
58
|
+
export interface IInitPythProOracleOptions extends IFetchPythProUpdateOptions {
|
|
59
|
+
/** Pre-fetched leEcdsa update bytes. When omitted, bytes are fetched via kronos REST. */
|
|
60
|
+
rawUpdateBytes?: Uint8Array | number[]
|
|
61
|
+
/** Pre-fetched Stork update payloads. When omitted, fetched via kronos REST when needed. */
|
|
62
|
+
storkUpdateData?: IStorkUpdateData[]
|
|
63
|
+
/** Skip Stork on-chain updates even when assets are configured. */
|
|
64
|
+
skipStork?: boolean
|
|
65
|
+
/** Coin to split Stork update fees from (defaults to gas coin). */
|
|
66
|
+
storkFeeSource?: TransactionObjectArgument
|
|
67
|
+
}
|
|
68
|
+
|
|
18
69
|
export interface IInitOracleTxbResult {
|
|
19
70
|
tx: Transaction
|
|
20
71
|
/** Remaining SUI coin after Pyth fee splits; present when sponsored and SUI was resolved. */
|
|
@@ -26,6 +77,8 @@ export class OracleAPI {
|
|
|
26
77
|
consts: IConsts
|
|
27
78
|
sharedConfig: IConsts
|
|
28
79
|
connectionURL: string
|
|
80
|
+
/** Kronos REST base URL for Pyth Pro proxy. Defaults to `DEFAULT_API_ENDPOINT`. */
|
|
81
|
+
apiEndpoint: string
|
|
29
82
|
PythFeederToPriceId: Record<string, string>
|
|
30
83
|
PythFeederToId: Record<string, string>
|
|
31
84
|
provider: SuiClient
|
|
@@ -39,11 +92,13 @@ export class OracleAPI {
|
|
|
39
92
|
// todo 需要从配置文件中获取
|
|
40
93
|
connectionURL: string,
|
|
41
94
|
lpToken: LPToken = LPToken.ZLP,
|
|
95
|
+
apiEndpoint: string = DEFAULT_API_ENDPOINT,
|
|
42
96
|
) {
|
|
43
97
|
this.network = network
|
|
44
98
|
this.consts = getConsts(network, lpToken)
|
|
45
99
|
this.sharedConfig = getSharedConfig(network)
|
|
46
100
|
this.connectionURL = connectionURL
|
|
101
|
+
this.apiEndpoint = apiEndpoint
|
|
47
102
|
this.PythFeederToPriceId = getPythFeederToPriceId(network)
|
|
48
103
|
this.PythFeederToId = getPythFeederToId(network)
|
|
49
104
|
this.provider = provider || createJsonRpcProvider(network)
|
|
@@ -190,4 +245,170 @@ export class OracleAPI {
|
|
|
190
245
|
async getBaseUpdateFee(): Promise<number> {
|
|
191
246
|
return await this.client.getBaseUpdateFee()
|
|
192
247
|
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Resolve SDK token ids (e.g. `sui`, `btc`) to Pyth Lazer numeric feed ids.
|
|
251
|
+
*/
|
|
252
|
+
resolveLazerFeedIdsForTokens(tokens: string[]): number[] {
|
|
253
|
+
const zoOracle = getZoOracleConfig(this.network)
|
|
254
|
+
return resolveLazerFeedIds(
|
|
255
|
+
zoOracle,
|
|
256
|
+
this.consts.coins,
|
|
257
|
+
tokens,
|
|
258
|
+
this.network,
|
|
259
|
+
this.consts.pythFeeder.feeder,
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Map SDK token ids to kronos Stork asset ids (e.g. `BTCUSD`). */
|
|
264
|
+
resolveStorkAssetsForTokens(tokens: string[]): string[] {
|
|
265
|
+
const zoOracle = getZoOracleConfig(this.network)
|
|
266
|
+
return resolveStorkAssetsForTokens(zoOracle, this.consts.coins, tokens)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Fetch Stork on-chain update payloads via kronos REST. */
|
|
270
|
+
async fetchStorkUpdateDataForTokens(tokens: string[]): Promise<IStorkUpdateData[]> {
|
|
271
|
+
const zoOracle = getZoOracleConfig(this.network)
|
|
272
|
+
const assets = this.resolveStorkAssetsForTokens(tokens)
|
|
273
|
+
if (assets.length === 0) {
|
|
274
|
+
return []
|
|
275
|
+
}
|
|
276
|
+
return await fetchStorkUpdateDataFromKronos(
|
|
277
|
+
this.resolveKronosUrl(),
|
|
278
|
+
assets,
|
|
279
|
+
buildStorkAssetIdMap(zoOracle),
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** Estimated Stork update fee in MIST for the given SDK tokens. */
|
|
284
|
+
estimateStorkUpdateFeeForTokens(tokens: string[]): bigint {
|
|
285
|
+
return estimateStorkUpdateFeeMist(this.resolveStorkAssetsForTokens(tokens).length)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Kronos REST base URL used for Pyth Pro / Stork (`options.kronosUrl` overrides per call). */
|
|
289
|
+
protected resolveKronosUrl(kronosUrl?: string): string {
|
|
290
|
+
return kronosUrl ?? this.apiEndpoint
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* V3 oracle PTB prelude: Stork on-chain updates → Pyth Pro verify → OracleInputs.
|
|
295
|
+
* Order: (1) Stork update, (2) parse_and_verify_le_ecdsa_update_v2, (3) ready for market op.
|
|
296
|
+
*/
|
|
297
|
+
async initV3OracleTxb(
|
|
298
|
+
tokens: string[],
|
|
299
|
+
tx?: Transaction,
|
|
300
|
+
options?: IInitPythProOracleOptions,
|
|
301
|
+
): Promise<IInitPythProOracleTxbResult> {
|
|
302
|
+
const tx_ = tx ?? new Transaction()
|
|
303
|
+
const config = this.getOracleProConfig()
|
|
304
|
+
|
|
305
|
+
if (!options?.skipStork) {
|
|
306
|
+
const storkAssets = this.resolveStorkAssetsForTokens(tokens)
|
|
307
|
+
if (storkAssets.length > 0) {
|
|
308
|
+
let storkUpdates = options?.storkUpdateData
|
|
309
|
+
if (!storkUpdates) {
|
|
310
|
+
const zoOracle = getZoOracleConfig(this.network)
|
|
311
|
+
storkUpdates = await fetchStorkUpdateDataFromKronos(
|
|
312
|
+
this.resolveKronosUrl(options?.kronosUrl),
|
|
313
|
+
storkAssets,
|
|
314
|
+
buildStorkAssetIdMap(zoOracle),
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
appendStorkUpdatesToTransaction(tx_, config, storkUpdates, {
|
|
318
|
+
feeSource: options?.storkFeeSource,
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let rawBytes = options?.rawUpdateBytes
|
|
324
|
+
if (!rawBytes) {
|
|
325
|
+
rawBytes = await this.fetchPythProUpdateBytesForTokens(tokens, options)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const pythProUpdate = parseAndVerifyPythProUpdate(tx_, config, rawBytes)
|
|
329
|
+
const oracle = buildOracleInputs(tx_, config, pythProUpdate)
|
|
330
|
+
|
|
331
|
+
return { tx: tx_, oracle }
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Latest Pyth Pro prices via kronos REST (`/pyth-pro/latest-price`).
|
|
336
|
+
*/
|
|
337
|
+
async getLatestPythProPricesForTokens(
|
|
338
|
+
tokens: string[],
|
|
339
|
+
options?: Omit<IGetLatestPythProPricesOptions, 'priceFeedIds'>,
|
|
340
|
+
): Promise<PythProLatestPriceData> {
|
|
341
|
+
const priceFeedIds = this.resolveLazerFeedIdsForTokens(tokens)
|
|
342
|
+
return getLatestPythProPrices(this.resolveKronosUrl(options?.kronosUrl), {
|
|
343
|
+
priceFeedIds,
|
|
344
|
+
channel: options?.channel,
|
|
345
|
+
includeEmaPrice: options?.includeEmaPrice,
|
|
346
|
+
includeUpdateBytes: options?.includeUpdateBytes,
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** WebSocket client for kronos `/pyth-pro/stream`. */
|
|
351
|
+
createPythProStreamClient(kronosUrl?: string): PythProStreamClient {
|
|
352
|
+
return new PythProStreamClient(this.resolveKronosUrl(kronosUrl))
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Subscribe to live Pyth Pro prices for SDK tokens via kronos WebSocket.
|
|
357
|
+
* Returns unsubscribe (closes subscription; disconnect the client separately if unused).
|
|
358
|
+
*/
|
|
359
|
+
async subPythProPricesForTokens(
|
|
360
|
+
tokens: string[],
|
|
361
|
+
onUpdate: (update: PythProStreamUpdate) => void,
|
|
362
|
+
options?: Omit<IPythProStreamSubscription, 'subscriptionId' | 'priceFeedIds'>,
|
|
363
|
+
subscriptionId = 1,
|
|
364
|
+
): Promise<() => void> {
|
|
365
|
+
const client = this.createPythProStreamClient()
|
|
366
|
+
const priceFeedIds = this.resolveLazerFeedIdsForTokens(tokens)
|
|
367
|
+
await client.connect()
|
|
368
|
+
return client.subscribe(
|
|
369
|
+
{
|
|
370
|
+
subscriptionId,
|
|
371
|
+
priceFeedIds,
|
|
372
|
+
...options,
|
|
373
|
+
},
|
|
374
|
+
onUpdate,
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Fetch leEcdsa update bytes covering all tokens' Pyth Lazer feed ids via kronos REST.
|
|
380
|
+
*/
|
|
381
|
+
async fetchPythProUpdateBytesForTokens(
|
|
382
|
+
tokens: string[],
|
|
383
|
+
options?: IFetchPythProUpdateOptions,
|
|
384
|
+
): Promise<Uint8Array> {
|
|
385
|
+
const config = this.getOracleProConfig()
|
|
386
|
+
const feedIds = this.resolveLazerFeedIdsForTokens(tokens)
|
|
387
|
+
return await fetchPythProUpdateBytes(this.resolveKronosUrl(options?.kronosUrl), feedIds, {
|
|
388
|
+
channel: options?.channel ?? (config.lazerChannel as PythProChannel),
|
|
389
|
+
includeEmaPrice: options?.includeEmaPrice,
|
|
390
|
+
})
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
protected getOracleProConfig() {
|
|
394
|
+
return buildOracleProConfig(getZoOracleConfig(this.network))
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* PTB step for Pyth Pro paths: Stork updates (when configured) + parse_and_verify_le_ecdsa_update_v2.
|
|
399
|
+
* @deprecated Alias for {@link initV3OracleTxb}.
|
|
400
|
+
*/
|
|
401
|
+
async initPythProOracleTxb(
|
|
402
|
+
tokens: string[],
|
|
403
|
+
tx?: Transaction,
|
|
404
|
+
options?: IInitPythProOracleOptions,
|
|
405
|
+
): Promise<IInitPythProOracleTxbResult> {
|
|
406
|
+
return this.initV3OracleTxb(tokens, tx, options)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** Re-use an already-verified Update object (composed PTBs). */
|
|
410
|
+
buildOracleInputsFromUpdate(tx: Transaction, pythProUpdate: TransactionObjectArgument): OracleInputs {
|
|
411
|
+
const config = this.getOracleProConfig()
|
|
412
|
+
return buildOracleInputs(tx, config, pythProUpdate)
|
|
413
|
+
}
|
|
193
414
|
}
|