@zofai/zo-sdk 0.2.14 → 0.2.16

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 (138) hide show
  1. package/dist/abstract/BaseAPI.cjs +5 -0
  2. package/dist/abstract/BaseAPI.cjs.map +1 -1
  3. package/dist/abstract/BaseAPI.d.cts +2 -1
  4. package/dist/abstract/BaseAPI.d.cts.map +1 -1
  5. package/dist/abstract/BaseAPI.d.mts +2 -1
  6. package/dist/abstract/BaseAPI.d.mts.map +1 -1
  7. package/dist/abstract/BaseAPI.mjs +5 -0
  8. package/dist/abstract/BaseAPI.mjs.map +1 -1
  9. package/dist/abstract/BaseDataAPI.cjs +1 -1
  10. package/dist/abstract/BaseDataAPI.cjs.map +1 -1
  11. package/dist/abstract/BaseDataAPI.mjs +1 -1
  12. package/dist/abstract/BaseDataAPI.mjs.map +1 -1
  13. package/dist/consts/deployments-usdz-mainnet.json +1 -1
  14. package/dist/consts/deployments-zo-oracle-mainnet.json +329 -0
  15. package/dist/consts/index.cjs +35 -1
  16. package/dist/consts/index.cjs.map +1 -1
  17. package/dist/consts/index.d.cts +45 -0
  18. package/dist/consts/index.d.cts.map +1 -1
  19. package/dist/consts/index.d.mts +45 -0
  20. package/dist/consts/index.d.mts.map +1 -1
  21. package/dist/consts/index.mjs +31 -0
  22. package/dist/consts/index.mjs.map +1 -1
  23. package/dist/data.cjs +1 -1
  24. package/dist/data.cjs.map +1 -1
  25. package/dist/data.mjs +1 -1
  26. package/dist/data.mjs.map +1 -1
  27. package/dist/implementations/SLPAPI.cjs +3 -2
  28. package/dist/implementations/SLPAPI.cjs.map +1 -1
  29. package/dist/implementations/SLPAPI.d.cts.map +1 -1
  30. package/dist/implementations/SLPAPI.d.mts.map +1 -1
  31. package/dist/implementations/SLPAPI.mjs +3 -2
  32. package/dist/implementations/SLPAPI.mjs.map +1 -1
  33. package/dist/implementations/USDZAPI.cjs +531 -81
  34. package/dist/implementations/USDZAPI.cjs.map +1 -1
  35. package/dist/implementations/USDZAPI.d.cts +62 -0
  36. package/dist/implementations/USDZAPI.d.cts.map +1 -1
  37. package/dist/implementations/USDZAPI.d.mts +62 -0
  38. package/dist/implementations/USDZAPI.d.mts.map +1 -1
  39. package/dist/implementations/USDZAPI.mjs +532 -82
  40. package/dist/implementations/USDZAPI.mjs.map +1 -1
  41. package/dist/implementations/USDZDataAPI.cjs +38 -0
  42. package/dist/implementations/USDZDataAPI.cjs.map +1 -1
  43. package/dist/implementations/USDZDataAPI.d.cts +16 -0
  44. package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
  45. package/dist/implementations/USDZDataAPI.d.mts +16 -0
  46. package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
  47. package/dist/implementations/USDZDataAPI.mjs +38 -0
  48. package/dist/implementations/USDZDataAPI.mjs.map +1 -1
  49. package/dist/implementations/ZBTCVCAPI.cjs +3 -1
  50. package/dist/implementations/ZBTCVCAPI.cjs.map +1 -1
  51. package/dist/implementations/ZBTCVCAPI.d.cts.map +1 -1
  52. package/dist/implementations/ZBTCVCAPI.d.mts.map +1 -1
  53. package/dist/implementations/ZBTCVCAPI.mjs +3 -1
  54. package/dist/implementations/ZBTCVCAPI.mjs.map +1 -1
  55. package/dist/implementations/ZLPAPI.cjs +3 -2
  56. package/dist/implementations/ZLPAPI.cjs.map +1 -1
  57. package/dist/implementations/ZLPAPI.d.cts.map +1 -1
  58. package/dist/implementations/ZLPAPI.d.mts.map +1 -1
  59. package/dist/implementations/ZLPAPI.mjs +3 -2
  60. package/dist/implementations/ZLPAPI.mjs.map +1 -1
  61. package/dist/index.cjs +3 -0
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +3 -0
  64. package/dist/index.d.cts.map +1 -1
  65. package/dist/index.d.mts +3 -0
  66. package/dist/index.d.mts.map +1 -1
  67. package/dist/index.mjs +3 -0
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/interfaces/base.d.cts +20 -2
  70. package/dist/interfaces/base.d.cts.map +1 -1
  71. package/dist/interfaces/base.d.mts +20 -2
  72. package/dist/interfaces/base.d.mts.map +1 -1
  73. package/dist/interfaces/usdz.d.cts +19 -0
  74. package/dist/interfaces/usdz.d.cts.map +1 -1
  75. package/dist/interfaces/usdz.d.mts +19 -0
  76. package/dist/interfaces/usdz.d.mts.map +1 -1
  77. package/dist/oracle.cjs +119 -1
  78. package/dist/oracle.cjs.map +1 -1
  79. package/dist/oracle.d.cts +57 -1
  80. package/dist/oracle.d.cts.map +1 -1
  81. package/dist/oracle.d.mts +57 -1
  82. package/dist/oracle.d.mts.map +1 -1
  83. package/dist/oracle.mjs +120 -2
  84. package/dist/oracle.mjs.map +1 -1
  85. package/dist/oraclePro.cjs +211 -0
  86. package/dist/oraclePro.cjs.map +1 -0
  87. package/dist/oraclePro.d.cts +90 -0
  88. package/dist/oraclePro.d.cts.map +1 -0
  89. package/dist/oraclePro.d.mts +90 -0
  90. package/dist/oraclePro.d.mts.map +1 -0
  91. package/dist/oraclePro.mjs +194 -0
  92. package/dist/oraclePro.mjs.map +1 -0
  93. package/dist/pythProClient.cjs +277 -0
  94. package/dist/pythProClient.cjs.map +1 -0
  95. package/dist/pythProClient.d.cts +143 -0
  96. package/dist/pythProClient.d.cts.map +1 -0
  97. package/dist/pythProClient.d.mts +143 -0
  98. package/dist/pythProClient.d.mts.map +1 -0
  99. package/dist/pythProClient.mjs +269 -0
  100. package/dist/pythProClient.mjs.map +1 -0
  101. package/dist/storkClient.cjs +217 -0
  102. package/dist/storkClient.cjs.map +1 -0
  103. package/dist/storkClient.d.cts +90 -0
  104. package/dist/storkClient.d.cts.map +1 -0
  105. package/dist/storkClient.d.mts +90 -0
  106. package/dist/storkClient.d.mts.map +1 -0
  107. package/dist/storkClient.mjs +208 -0
  108. package/dist/storkClient.mjs.map +1 -0
  109. package/dist/storkOracle.cjs +61 -0
  110. package/dist/storkOracle.cjs.map +1 -0
  111. package/dist/storkOracle.d.cts +21 -0
  112. package/dist/storkOracle.d.cts.map +1 -0
  113. package/dist/storkOracle.d.mts +21 -0
  114. package/dist/storkOracle.d.mts.map +1 -0
  115. package/dist/storkOracle.mjs +56 -0
  116. package/dist/storkOracle.mjs.map +1 -0
  117. package/package.json +1 -1
  118. package/src/abstract/BaseAPI.ts +11 -0
  119. package/src/abstract/BaseDataAPI.ts +1 -1
  120. package/src/consts/deployments-usdz-mainnet.json +1 -1
  121. package/src/consts/deployments-zo-oracle-mainnet.json +329 -0
  122. package/src/consts/index.ts +80 -0
  123. package/src/data.ts +1 -1
  124. package/src/implementations/SLPAPI.ts +5 -5
  125. package/src/implementations/USDZAPI.ts +906 -107
  126. package/src/implementations/USDZDataAPI.ts +42 -0
  127. package/src/implementations/ZBTCVCAPI.ts +6 -4
  128. package/src/implementations/ZLPAPI.ts +6 -5
  129. package/src/index.ts +3 -0
  130. package/src/interfaces/base.ts +55 -1
  131. package/src/interfaces/usdz.ts +170 -0
  132. package/src/oracle.ts +222 -1
  133. package/src/oraclePro.ts +309 -0
  134. package/src/pythProClient.ts +406 -0
  135. package/src/storkClient.ts +328 -0
  136. package/src/storkOracle.ts +82 -0
  137. package/tests/pythProClient.test.ts +155 -0
  138. 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
  */
@@ -1107,13 +1107,12 @@ export class ZBTCVCAPI extends BaseAPI implements IZBTCVCAPI {
1107
1107
  }
1108
1108
 
1109
1109
  // Process coin splitting
1110
- const [depositObject] = this.processCoinSplitting(
1110
+ const depositObject = await this.resolveSplitCoinObject(
1111
1111
  tx,
1112
1112
  collateralToken,
1113
+ BigInt(amount),
1113
1114
  coinObjects,
1114
- [tx.pure.u64(amount)],
1115
- sponsoredTx,
1116
- suiCoinObject,
1115
+ { sponsoredTx, suiCoinObject, sender },
1117
1116
  )
1118
1117
 
1119
1118
  tx.moveCall({
@@ -1126,6 +1125,8 @@ export class ZBTCVCAPI extends BaseAPI implements IZBTCVCAPI {
1126
1125
  ],
1127
1126
  arguments: [tx.object(this.consts.zoCore.market), tx.object(pcpId), depositObject],
1128
1127
  })
1128
+
1129
+ this.returnUnusedSuiCoin(tx, suiCoinObject, sender)
1129
1130
  return tx
1130
1131
  }
1131
1132
 
@@ -1174,6 +1175,7 @@ export class ZBTCVCAPI extends BaseAPI implements IZBTCVCAPI {
1174
1175
  ],
1175
1176
  })
1176
1177
 
1178
+ this.returnUnusedSuiCoin(tx, suiCoinObject, sender)
1177
1179
  return tx
1178
1180
  }
1179
1181
 
@@ -2392,14 +2392,12 @@ export class ZLPAPI extends BaseAPI implements IZLPAPI {
2392
2392
  tx = (await this.initOracleTxb([collateralToken, indexToken], tx)).tx
2393
2393
  }
2394
2394
 
2395
- // Process coin splitting
2396
- const [depositObject] = this.processCoinSplitting(
2395
+ const depositObject = await this.resolveSplitCoinObject(
2397
2396
  tx,
2398
2397
  collateralToken,
2398
+ BigInt(amount),
2399
2399
  coinObjects,
2400
- [tx.pure.u64(amount)],
2401
- sponsoredTx,
2402
- suiCoinObject,
2400
+ { sponsoredTx, suiCoinObject, sender },
2403
2401
  )
2404
2402
 
2405
2403
  tx.moveCall({
@@ -2412,6 +2410,8 @@ export class ZLPAPI extends BaseAPI implements IZLPAPI {
2412
2410
  ],
2413
2411
  arguments: [tx.object(this.consts.zoCore.market), tx.object(pcpId), depositObject],
2414
2412
  })
2413
+
2414
+ this.returnUnusedSuiCoin(tx, suiCoinObject, sender)
2415
2415
  return tx
2416
2416
  }
2417
2417
 
@@ -2460,6 +2460,7 @@ export class ZLPAPI extends BaseAPI implements IZLPAPI {
2460
2460
  ],
2461
2461
  })
2462
2462
 
2463
+ this.returnUnusedSuiCoin(tx, suiCoinObject, sender)
2463
2464
  return tx
2464
2465
  }
2465
2466
 
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
  }
@@ -531,6 +584,7 @@ export interface IBaseAPI {
531
584
  amount: number,
532
585
  long: boolean,
533
586
  sponsoredTx?: boolean,
587
+ sender?: string,
534
588
  ) => Promise<Transaction>
535
589
 
536
590
  cancelOrder: (
@@ -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,170 @@ 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
+ openPositionWithCoinV3: (
275
+ collateralToken: string,
276
+ indexToken: string,
277
+ size: bigint,
278
+ coinObj: import('@mysten/sui/transactions').TransactionObjectArgument,
279
+ long: boolean,
280
+ reserveAmount: bigint,
281
+ indexPrice: number,
282
+ collateralPrice: number,
283
+ pythProUpdateBytes: Uint8Array | number[],
284
+ isLimitOrder?: boolean,
285
+ isIocOrder?: boolean,
286
+ pricesSlippage?: number,
287
+ collateralSlippage?: number,
288
+ relayerFee?: bigint,
289
+ referralAddress?: string,
290
+ sender?: string,
291
+ tx?: import('@mysten/sui/transactions').Transaction,
292
+ sponsoredTx?: boolean,
293
+ ) => Promise<Transaction>
294
+
295
+ openPositionWithCoinAndSCardV3: (
296
+ collateralToken: string,
297
+ indexToken: string,
298
+ size: bigint,
299
+ coinObj: import('@mysten/sui/transactions').TransactionObjectArgument,
300
+ long: boolean,
301
+ reserveAmount: bigint,
302
+ indexPrice: number,
303
+ collateralPrice: number,
304
+ kioskClient: import('@mysten/kiosk').KioskClient,
305
+ kioskCap: import('@mysten/kiosk').KioskOwnerCap,
306
+ scard: string,
307
+ pythProUpdateBytes: Uint8Array | number[],
308
+ isLimitOrder?: boolean,
309
+ isIocOrder?: boolean,
310
+ pricesSlippage?: number,
311
+ collateralSlippage?: number,
312
+ relayerFee?: bigint,
313
+ referralAddress?: string,
314
+ sender?: string,
315
+ tx?: import('@mysten/sui/transactions').Transaction,
316
+ sponsoredTx?: boolean,
317
+ ) => Promise<Transaction>
318
+
319
+ decreasePositionV3: (
320
+ pcpId: string,
321
+ collateralToken: string,
322
+ indexToken: string,
323
+ amount: bigint,
324
+ long: boolean,
325
+ indexPrice: number,
326
+ collateralPrice: number,
327
+ pythProUpdateBytes: Uint8Array | number[],
328
+ isTriggerOrder?: boolean,
329
+ isTakeProfitOrder?: boolean,
330
+ isIocOrder?: boolean,
331
+ pricesSlippage?: number,
332
+ collateralSlippage?: number,
333
+ relayerFee?: bigint,
334
+ coinObjects?: string[],
335
+ sponsoredTx?: boolean,
336
+ sender?: string,
337
+ ) => Promise<Transaction>
338
+
339
+ decreasePositionWithSCardV3: (
340
+ pcpId: string,
341
+ collateralToken: string,
342
+ indexToken: string,
343
+ amount: bigint,
344
+ long: boolean,
345
+ indexPrice: number,
346
+ collateralPrice: number,
347
+ kioskClient: import('@mysten/kiosk').KioskClient,
348
+ kioskCap: import('@mysten/kiosk').KioskOwnerCap,
349
+ scard: string,
350
+ pythProUpdateBytes: Uint8Array | number[],
351
+ isTriggerOrder?: boolean,
352
+ isTakeProfitOrder?: boolean,
353
+ isIocOrder?: boolean,
354
+ pricesSlippage?: number,
355
+ collateralSlippage?: number,
356
+ relayerFee?: bigint,
357
+ coinObjects?: string[],
358
+ sponsoredTx?: boolean,
359
+ sender?: string,
360
+ ) => Promise<Transaction>
361
+
362
+ /** Pyth Pro path (not legacy feeder v2). */
363
+ redeemFromPositionV2: (
364
+ pcpId: string,
365
+ collateralToken: string,
366
+ indexToken: string,
367
+ amount: number,
368
+ long: boolean,
369
+ pythProUpdateBytes: Uint8Array | number[],
370
+ tx?: Transaction,
371
+ ) => Promise<Transaction>
202
372
  }
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
  }