@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.
Files changed (109) hide show
  1. package/.claude/settings.local.json +11 -1
  2. package/dist/abstract/BaseDataAPI.cjs +1 -1
  3. package/dist/abstract/BaseDataAPI.cjs.map +1 -1
  4. package/dist/abstract/BaseDataAPI.mjs +1 -1
  5. package/dist/abstract/BaseDataAPI.mjs.map +1 -1
  6. package/dist/consts/deployments-usdz-mainnet.json +1 -31
  7. package/dist/consts/deployments-zo-oracle-mainnet.json +329 -0
  8. package/dist/consts/index.cjs +35 -1
  9. package/dist/consts/index.cjs.map +1 -1
  10. package/dist/consts/index.d.cts +45 -0
  11. package/dist/consts/index.d.cts.map +1 -1
  12. package/dist/consts/index.d.mts +45 -0
  13. package/dist/consts/index.d.mts.map +1 -1
  14. package/dist/consts/index.mjs +31 -0
  15. package/dist/consts/index.mjs.map +1 -1
  16. package/dist/data.cjs +1 -1
  17. package/dist/data.cjs.map +1 -1
  18. package/dist/data.mjs +1 -1
  19. package/dist/data.mjs.map +1 -1
  20. package/dist/implementations/USDZAPI.cjs +426 -78
  21. package/dist/implementations/USDZAPI.cjs.map +1 -1
  22. package/dist/implementations/USDZAPI.d.cts +54 -0
  23. package/dist/implementations/USDZAPI.d.cts.map +1 -1
  24. package/dist/implementations/USDZAPI.d.mts +54 -0
  25. package/dist/implementations/USDZAPI.d.mts.map +1 -1
  26. package/dist/implementations/USDZAPI.mjs +427 -79
  27. package/dist/implementations/USDZAPI.mjs.map +1 -1
  28. package/dist/implementations/USDZDataAPI.cjs +38 -0
  29. package/dist/implementations/USDZDataAPI.cjs.map +1 -1
  30. package/dist/implementations/USDZDataAPI.d.cts +16 -0
  31. package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
  32. package/dist/implementations/USDZDataAPI.d.mts +16 -0
  33. package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
  34. package/dist/implementations/USDZDataAPI.mjs +38 -0
  35. package/dist/implementations/USDZDataAPI.mjs.map +1 -1
  36. package/dist/index.cjs +3 -0
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +3 -0
  39. package/dist/index.d.cts.map +1 -1
  40. package/dist/index.d.mts +3 -0
  41. package/dist/index.d.mts.map +1 -1
  42. package/dist/index.mjs +3 -0
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/interfaces/base.d.cts +19 -1
  45. package/dist/interfaces/base.d.cts.map +1 -1
  46. package/dist/interfaces/base.d.mts +19 -1
  47. package/dist/interfaces/base.d.mts.map +1 -1
  48. package/dist/interfaces/usdz.d.cts +17 -0
  49. package/dist/interfaces/usdz.d.cts.map +1 -1
  50. package/dist/interfaces/usdz.d.mts +17 -0
  51. package/dist/interfaces/usdz.d.mts.map +1 -1
  52. package/dist/oracle.cjs +119 -1
  53. package/dist/oracle.cjs.map +1 -1
  54. package/dist/oracle.d.cts +57 -1
  55. package/dist/oracle.d.cts.map +1 -1
  56. package/dist/oracle.d.mts +57 -1
  57. package/dist/oracle.d.mts.map +1 -1
  58. package/dist/oracle.mjs +120 -2
  59. package/dist/oracle.mjs.map +1 -1
  60. package/dist/oraclePro.cjs +214 -0
  61. package/dist/oraclePro.cjs.map +1 -0
  62. package/dist/oraclePro.d.cts +92 -0
  63. package/dist/oraclePro.d.cts.map +1 -0
  64. package/dist/oraclePro.d.mts +92 -0
  65. package/dist/oraclePro.d.mts.map +1 -0
  66. package/dist/oraclePro.mjs +196 -0
  67. package/dist/oraclePro.mjs.map +1 -0
  68. package/dist/pythProClient.cjs +277 -0
  69. package/dist/pythProClient.cjs.map +1 -0
  70. package/dist/pythProClient.d.cts +143 -0
  71. package/dist/pythProClient.d.cts.map +1 -0
  72. package/dist/pythProClient.d.mts +143 -0
  73. package/dist/pythProClient.d.mts.map +1 -0
  74. package/dist/pythProClient.mjs +269 -0
  75. package/dist/pythProClient.mjs.map +1 -0
  76. package/dist/storkClient.cjs +217 -0
  77. package/dist/storkClient.cjs.map +1 -0
  78. package/dist/storkClient.d.cts +90 -0
  79. package/dist/storkClient.d.cts.map +1 -0
  80. package/dist/storkClient.d.mts +90 -0
  81. package/dist/storkClient.d.mts.map +1 -0
  82. package/dist/storkClient.mjs +208 -0
  83. package/dist/storkClient.mjs.map +1 -0
  84. package/dist/storkOracle.cjs +61 -0
  85. package/dist/storkOracle.cjs.map +1 -0
  86. package/dist/storkOracle.d.cts +21 -0
  87. package/dist/storkOracle.d.cts.map +1 -0
  88. package/dist/storkOracle.d.mts +21 -0
  89. package/dist/storkOracle.d.mts.map +1 -0
  90. package/dist/storkOracle.mjs +56 -0
  91. package/dist/storkOracle.mjs.map +1 -0
  92. package/package.json +1 -1
  93. package/src/abstract/BaseDataAPI.ts +1 -1
  94. package/src/consts/deployments-usdz-mainnet.json +1 -31
  95. package/src/consts/deployments-zo-oracle-mainnet.json +329 -0
  96. package/src/consts/index.ts +80 -0
  97. package/src/data.ts +1 -1
  98. package/src/implementations/USDZAPI.ts +731 -101
  99. package/src/implementations/USDZDataAPI.ts +42 -0
  100. package/src/index.ts +3 -0
  101. package/src/interfaces/base.ts +54 -1
  102. package/src/interfaces/usdz.ts +125 -0
  103. package/src/oracle.ts +222 -1
  104. package/src/oraclePro.ts +312 -0
  105. package/src/pythProClient.ts +406 -0
  106. package/src/storkClient.ts +328 -0
  107. package/src/storkOracle.ts +82 -0
  108. package/tests/pythProClient.test.ts +155 -0
  109. 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
@@ -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
  }
@@ -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 { getConsts, getPriceIdToPythFeeder, getPythFeederToId, getPythFeederToPriceId, getSharedConfig, LPToken } from './consts'
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
  }