@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,7 @@ import { Transaction } from '@mysten/sui/transactions'
10
10
  import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils'
11
11
 
12
12
  import { BaseAPI } from '../abstract'
13
+ import { resolveSpendableSuiCoin } from '../coins'
13
14
  import type { Network } from '../consts'
14
15
  import { ALLOW_TRADE_CAN_TRADE, ALLOW_TRADE_MUST_TRADE, ALLOW_TRADE_NO_TRADE, LPToken } from '../consts'
15
16
  import type {
@@ -17,8 +18,11 @@ import type {
17
18
  IUSDZAPI,
18
19
  IUSDZCredential,
19
20
  } from '../interfaces'
21
+ import type { IInitPythProOracleOptions } from '../oracle'
22
+ import type { OracleInputs, OracleInputsAlt } from '../oraclePro'
23
+ import { buildOracleInputsAlt, oracleArgsAlt, oracleArgsStandard, oracleArgsWithClock } from '../oraclePro'
20
24
  import type { SuiClient } from '../suiClient'
21
- import { joinSymbol } from '../utils'
25
+ import { joinSymbol, parseSymbolKey } from '../utils'
22
26
  import { USDZDataAPI } from './USDZDataAPI'
23
27
 
24
28
  export class USDZAPI extends BaseAPI implements IUSDZAPI {
@@ -34,6 +38,85 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
34
38
  this.dataAPI = new USDZDataAPI(network, provider, apiEndpoint, connectionURL)
35
39
  }
36
40
 
41
+ private usdzLpType(): string {
42
+ return `${this.consts.zoCore.package}::usdz::USDZ`
43
+ }
44
+
45
+ private positionTypeArgs(collateralToken: string, indexToken: string, long: boolean): string[] {
46
+ return [
47
+ this.usdzLpType(),
48
+ this.consts.coins[collateralToken].module,
49
+ this.consts.coins[indexToken].module,
50
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
51
+ this.consts.coins[collateralToken].module,
52
+ ]
53
+ }
54
+
55
+ private redeemTypeArgs(collateralToken: string, indexToken: string, long: boolean): string[] {
56
+ return [
57
+ this.usdzLpType(),
58
+ this.consts.coins[collateralToken].module,
59
+ this.consts.coins[indexToken].module,
60
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
61
+ ]
62
+ }
63
+
64
+ private async initV3OracleForTokens(
65
+ tokens: string[],
66
+ tx: Transaction,
67
+ pythProUpdateBytes: Uint8Array | number[],
68
+ includeEmaPrice?: boolean,
69
+ options?: Pick<IInitPythProOracleOptions, 'storkUpdateData' | 'skipStork' | 'storkFeeSource' | 'kronosUrl'>,
70
+ ): Promise<{ tx: Transaction, oracle: OracleInputs }> {
71
+ const result = await this.initV3OracleTxb(tokens, tx, {
72
+ rawUpdateBytes: pythProUpdateBytes,
73
+ includeEmaPrice,
74
+ ...options,
75
+ })
76
+ return { tx: result.tx, oracle: result.oracle }
77
+ }
78
+
79
+ /** Vault + symbol index tokens required for valuate_vault_v2 / valuate_symbol_v2. */
80
+ private getValuationOracleTokens(): string[] {
81
+ const tokens = new Set(Object.keys(this.consts.zoCore.vaults))
82
+ for (const key of Object.keys(this.consts.zoCore.symbols)) {
83
+ const [, token] = parseSymbolKey(key)
84
+ tokens.add(token)
85
+ }
86
+ return [...tokens]
87
+ }
88
+
89
+ /** Pyth Pro oracle init for deposit / withdraw market valuation. */
90
+ private async initValuationOracle(
91
+ tx: Transaction,
92
+ ): Promise<{ tx: Transaction, oracle: OracleInputs }> {
93
+ const tokens = this.getValuationOracleTokens()
94
+ const pythProUpdateBytes = await this.fetchPythProUpdateBytesForTokens(tokens)
95
+ return this.initV3OracleForTokens(tokens, tx, pythProUpdateBytes)
96
+ }
97
+
98
+ private async resolveSponsoredSui(
99
+ tx: Transaction,
100
+ collateralToken: string,
101
+ relayerFee: bigint,
102
+ sponsoredTx?: boolean,
103
+ sender?: string,
104
+ ): Promise<TransactionObjectArgument | undefined> {
105
+ if (!sponsoredTx) {
106
+ return undefined
107
+ }
108
+ const additional = collateralToken === 'sui' ? relayerFee : 0n
109
+ if (additional === 0n) {
110
+ return undefined
111
+ }
112
+ return resolveSpendableSuiCoin(
113
+ tx,
114
+ this.provider,
115
+ this.requireSenderForSponsored(sender),
116
+ additional,
117
+ )
118
+ }
119
+
37
120
  public calcPositionReserveFeeAmount(_position: IBasePositionInfo): Promise<number> {
38
121
  throw new Error(`Method not implemented in ${this.constructor.name}.`)
39
122
  }
@@ -1059,53 +1142,18 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
1059
1142
  tx = await this.addReferral(referralAddress, tx)
1060
1143
  }
1061
1144
 
1062
- // Initialize oracle transaction
1063
- const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
1064
-
1065
- // Handle sponsored transaction case
1066
- if (sponsoredTx) {
1067
- const oracle = await this.initOracleTxb(pythFeederKeys, tx, true, {
1068
- sender: this.requireSenderForSponsored(sender),
1069
- additionalSuiAmount: coin === 'sui' ? BigInt(amount) : 0n,
1070
- })
1071
- tx = oracle.tx
1072
-
1073
- const depositObject = await this.resolveSplitCoinObject(
1074
- tx,
1075
- coin,
1076
- BigInt(amount),
1077
- coinObjects,
1078
- { sponsoredTx: true, suiCoinObject: oracle.suiCoinObject, sender },
1079
- )
1080
-
1081
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1082
-
1083
- tx.moveCall({
1084
- target: `${this.consts.zoCore.upgradedPackage}::market::deposit`,
1085
- typeArguments: [`${this.consts.zoCore.package}::usdz::USDZ`, this.consts.coins[coin].module],
1086
- arguments: [
1087
- tx.object(this.consts.zoCore.market),
1088
- tx.object(this.consts.zoCore.rebaseFeeModel),
1089
- depositObject,
1090
- tx.pure.u64(minAmountOut),
1091
- vaultsValuation,
1092
- symbolsValuation,
1093
- ],
1094
- })
1095
- return tx
1096
- }
1145
+ const { tx: txWithOracle, oracle: oracleBundle } = await this.initValuationOracle(tx)
1146
+ tx = txWithOracle
1097
1147
 
1098
- // Handle non-sponsored transaction case
1099
- tx = (await this.initOracleTxb(pythFeederKeys, tx)).tx
1100
1148
  const depositObject = await this.resolveSplitCoinObject(
1101
1149
  tx,
1102
1150
  coin,
1103
1151
  BigInt(amount),
1104
1152
  coinObjects,
1105
- { sender },
1153
+ { sponsoredTx, sender },
1106
1154
  )
1107
1155
 
1108
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1156
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuateV2(tx, oracleBundle)
1109
1157
 
1110
1158
  tx.moveCall({
1111
1159
  target: `${this.consts.zoCore.upgradedPackage}::market::deposit`,
@@ -1147,53 +1195,18 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
1147
1195
  tx = await this.addReferral(referralAddress, tx)
1148
1196
  }
1149
1197
 
1150
- // Initialize oracle transaction
1151
- const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
1152
-
1153
- // Handle sponsored transaction case
1154
- if (sponsoredTx) {
1155
- const oracle = await this.initOracleTxb(pythFeederKeys, tx, true, {
1156
- sender: this.requireSenderForSponsored(sender),
1157
- additionalSuiAmount: coin === 'sui' ? BigInt(amount) : 0n,
1158
- })
1159
- tx = oracle.tx
1160
-
1161
- const depositObject = await this.resolveSplitCoinObject(
1162
- tx,
1163
- coin,
1164
- BigInt(amount),
1165
- coinObjects,
1166
- { sponsoredTx: true, suiCoinObject: oracle.suiCoinObject, sender },
1167
- )
1168
-
1169
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1170
-
1171
- const [mintedCoin] = tx.moveCall({
1172
- target: `${this.consts.zoCore.upgradedPackage}::market::deposit_ptb`,
1173
- typeArguments: [`${this.consts.zoCore.package}::usdz::USDZ`, this.consts.coins[coin].module],
1174
- arguments: [
1175
- tx.object(this.consts.zoCore.market),
1176
- tx.object(this.consts.zoCore.rebaseFeeModel),
1177
- depositObject,
1178
- tx.pure.u64(minAmountOut),
1179
- vaultsValuation,
1180
- symbolsValuation,
1181
- ],
1182
- })
1183
- return mintedCoin
1184
- }
1198
+ const { tx: txWithOracle, oracle: oracleBundle } = await this.initValuationOracle(tx)
1199
+ tx = txWithOracle
1185
1200
 
1186
- // Handle non-sponsored transaction case
1187
- tx = (await this.initOracleTxb(pythFeederKeys, tx)).tx
1188
1201
  const depositObject = await this.resolveSplitCoinObject(
1189
1202
  tx,
1190
1203
  coin,
1191
1204
  BigInt(amount),
1192
1205
  coinObjects,
1193
- { sender },
1206
+ { sponsoredTx, sender },
1194
1207
  )
1195
1208
 
1196
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1209
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuateV2(tx, oracleBundle)
1197
1210
 
1198
1211
  const [mintedCoin] = tx.moveCall({
1199
1212
  target: `${this.consts.zoCore.upgradedPackage}::market::deposit_ptb`,
@@ -1231,30 +1244,17 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
1231
1244
 
1232
1245
  let tx = new Transaction()
1233
1246
 
1234
- // Initialize oracle transaction
1235
- const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
1236
-
1237
- let suiCoinObject
1238
- if (sponsoredTx) {
1239
- const oracle = await this.initOracleTxb(pythFeederKeys, tx, true, {
1240
- sender: this.requireSenderForSponsored(sender),
1241
- additionalSuiAmount: 0n,
1242
- })
1243
- tx = oracle.tx
1244
- suiCoinObject = oracle.suiCoinObject
1245
- }
1246
- else {
1247
- tx = (await this.initOracleTxb(pythFeederKeys, tx)).tx
1248
- }
1247
+ const { tx: txWithOracle, oracle: oracleBundle } = await this.initValuationOracle(tx)
1248
+ tx = txWithOracle
1249
1249
 
1250
1250
  const withdrawObject = await this.resolveSplitCoinObject(
1251
1251
  tx,
1252
1252
  'usdz',
1253
1253
  BigInt(amount),
1254
1254
  lpCoinObjects,
1255
- { sponsoredTx, suiCoinObject, sender },
1255
+ { sponsoredTx, sender },
1256
1256
  )
1257
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1257
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuateV2(tx, oracleBundle)
1258
1258
 
1259
1259
  tx.moveCall({
1260
1260
  target: `${this.consts.zoCore.upgradedPackage}::market::withdraw`,
@@ -1287,11 +1287,9 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
1287
1287
  tx = new Transaction()
1288
1288
  }
1289
1289
 
1290
- // Initialize oracle transaction
1291
- const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
1292
-
1293
- tx = (await this.initOracleTxb(pythFeederKeys, tx)).tx
1294
- const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
1290
+ const { tx: txWithOracle, oracle: oracleBundle } = await this.initValuationOracle(tx)
1291
+ tx = txWithOracle
1292
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuateV2(tx, oracleBundle)
1295
1293
 
1296
1294
  tx.moveCall({
1297
1295
  target: `${this.consts.zoCore.upgradedPackage}::market::withdraw`,
@@ -2639,4 +2637,636 @@ export class USDZAPI extends BaseAPI implements IUSDZAPI {
2639
2637
  ],
2640
2638
  })
2641
2639
  }
2640
+
2641
+ // --- Pyth Pro + Stork (v3) ---
2642
+
2643
+ /**
2644
+ * Swaps tokens using swap_v3 (Pyth Pro + Stork). Transfers output to sender.
2645
+ */
2646
+ public async swapV3(
2647
+ fromToken: string,
2648
+ toToken: string,
2649
+ fromAmount: bigint,
2650
+ fromCoinObjects: string[],
2651
+ pythProUpdateBytes: Uint8Array | number[],
2652
+ minAmountOut?: number,
2653
+ tx?: Transaction,
2654
+ ): Promise<Transaction> {
2655
+ if (!tx) {
2656
+ tx = new Transaction()
2657
+ }
2658
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
2659
+ Object.keys(this.consts.zoCore.vaults),
2660
+ tx,
2661
+ pythProUpdateBytes,
2662
+ true,
2663
+ )
2664
+ const fromCoinObject = this.processCoins(tx_, fromToken, fromCoinObjects)
2665
+ const [fromDepositObject] = tx_.splitCoins(fromCoinObject, [tx_.pure.u64(fromAmount)])
2666
+ const vaultsValuation = this.dataAPI.valuateVaultsV2(tx_, oracle)
2667
+
2668
+ tx_.moveCall({
2669
+ target: `${this.consts.zoCore.upgradedPackage}::market::swap_v3`,
2670
+ typeArguments: [
2671
+ this.usdzLpType(),
2672
+ this.consts.coins[fromToken].module,
2673
+ this.consts.coins[toToken].module,
2674
+ ],
2675
+ arguments: [
2676
+ tx_.object(this.consts.zoCore.market),
2677
+ tx_.object(this.consts.zoCore.rebaseFeeModel),
2678
+ fromDepositObject,
2679
+ tx_.pure.u64(minAmountOut || 0),
2680
+ vaultsValuation,
2681
+ ...oracleArgsWithClock(oracle),
2682
+ ],
2683
+ })
2684
+ return tx_
2685
+ }
2686
+
2687
+ /**
2688
+ * Swaps tokens and returns the output coin (swap_v3_ptb).
2689
+ */
2690
+ public async swapV3Ptb(
2691
+ fromToken: string,
2692
+ toToken: string,
2693
+ fromAmount: bigint,
2694
+ fromCoinObjects: string[],
2695
+ pythProUpdateBytes: Uint8Array | number[],
2696
+ minAmountOut?: number,
2697
+ tx?: Transaction,
2698
+ ): Promise<TransactionObjectArgument> {
2699
+ if (!tx) {
2700
+ tx = new Transaction()
2701
+ }
2702
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
2703
+ Object.keys(this.consts.zoCore.vaults),
2704
+ tx,
2705
+ pythProUpdateBytes,
2706
+ true,
2707
+ )
2708
+ const fromCoinObject = this.processCoins(tx_, fromToken, fromCoinObjects)
2709
+ const [fromDepositObject] = tx_.splitCoins(fromCoinObject, [tx_.pure.u64(fromAmount)])
2710
+ const vaultsValuation = this.dataAPI.valuateVaultsV2(tx_, oracle)
2711
+
2712
+ const [outputCoin] = tx_.moveCall({
2713
+ target: `${this.consts.zoCore.upgradedPackage}::market::swap_v3_ptb`,
2714
+ typeArguments: [
2715
+ this.usdzLpType(),
2716
+ this.consts.coins[fromToken].module,
2717
+ this.consts.coins[toToken].module,
2718
+ ],
2719
+ arguments: [
2720
+ tx_.object(this.consts.zoCore.market),
2721
+ tx_.object(this.consts.zoCore.rebaseFeeModel),
2722
+ fromDepositObject,
2723
+ tx_.pure.u64(minAmountOut || 0),
2724
+ vaultsValuation,
2725
+ ...oracleArgsWithClock(oracle),
2726
+ ],
2727
+ })
2728
+ return outputCoin
2729
+ }
2730
+
2731
+ /**
2732
+ * Opens a position using open_position_v3 (Pyth Pro + Stork).
2733
+ */
2734
+ public async openPositionV3(
2735
+ collateralToken: string,
2736
+ indexToken: string,
2737
+ size: bigint,
2738
+ collateralAmount: bigint,
2739
+ coinObjects: string[],
2740
+ long: boolean,
2741
+ reserveAmount: bigint,
2742
+ indexPrice: number,
2743
+ collateralPrice: number,
2744
+ pythProUpdateBytes: Uint8Array | number[],
2745
+ isLimitOrder?: boolean,
2746
+ isIocOrder?: boolean,
2747
+ pricesSlippage = 0.003,
2748
+ collateralSlippage = 0.5,
2749
+ relayerFee = BigInt(0.5),
2750
+ referralAddress?: string,
2751
+ sender?: string,
2752
+ sponsoredTx?: boolean,
2753
+ ): Promise<Transaction> {
2754
+ let tx = new Transaction()
2755
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
2756
+ tx = await this.addReferral(referralAddress, tx)
2757
+ }
2758
+
2759
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2760
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
2761
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2762
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2763
+
2764
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2765
+ if (isLimitOrder) {
2766
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2767
+ }
2768
+
2769
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
2770
+ [collateralToken, indexToken],
2771
+ tx,
2772
+ pythProUpdateBytes,
2773
+ )
2774
+ tx = tx_
2775
+
2776
+ const suiCoinObject = await this.resolveSponsoredSui(tx, collateralToken, relayerFee, sponsoredTx, sender)
2777
+ const [depositObject, feeObject] = this.processCoinSplitting(
2778
+ tx,
2779
+ collateralToken,
2780
+ coinObjects,
2781
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
2782
+ sponsoredTx,
2783
+ suiCoinObject,
2784
+ )
2785
+
2786
+ tx.moveCall({
2787
+ target: `${this.consts.zoCore.upgradedPackage}::market::open_position_v3`,
2788
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
2789
+ arguments: [
2790
+ tx.object(SUI_CLOCK_OBJECT_ID),
2791
+ tx.object(this.consts.zoCore.market),
2792
+ tx.object(this.consts.zoCore.symbols[symbol].positionConfig),
2793
+ ...oracleArgsStandard(oracle),
2794
+ depositObject,
2795
+ feeObject,
2796
+ tx.pure.u8(allowTrade),
2797
+ tx.pure.u64(size),
2798
+ tx.pure.u64(reserveAmount),
2799
+ tx.pure.u256(adjustCollateralPrice),
2800
+ tx.pure.u256(adjustPrice),
2801
+ tx.pure.u256(indexPriceThreshold),
2802
+ ],
2803
+ })
2804
+
2805
+ return tx
2806
+ }
2807
+
2808
+ /**
2809
+ * Opens a position with S Card using open_position_with_scard_v3.
2810
+ */
2811
+ public async openPositionWithSCardV3(
2812
+ collateralToken: string,
2813
+ indexToken: string,
2814
+ size: bigint,
2815
+ collateralAmount: bigint,
2816
+ coinObjects: string[],
2817
+ long: boolean,
2818
+ reserveAmount: bigint,
2819
+ indexPrice: number,
2820
+ collateralPrice: number,
2821
+ kioskClient: KioskClient,
2822
+ kioskCap: KioskOwnerCap,
2823
+ scard: string,
2824
+ pythProUpdateBytes: Uint8Array | number[],
2825
+ isLimitOrder?: boolean,
2826
+ isIocOrder?: boolean,
2827
+ pricesSlippage = 0.003,
2828
+ collateralSlippage = 0.5,
2829
+ relayerFee = BigInt(0.5),
2830
+ referralAddress?: string,
2831
+ sender?: string,
2832
+ sponsoredTx?: boolean,
2833
+ ): Promise<Transaction> {
2834
+ let tx = new Transaction()
2835
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
2836
+ tx = await this.addReferral(referralAddress, tx)
2837
+ }
2838
+
2839
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2840
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
2841
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2842
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2843
+
2844
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2845
+ if (isLimitOrder) {
2846
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2847
+ }
2848
+
2849
+ const kioskTx = new KioskTransaction({
2850
+ transaction: tx,
2851
+ kioskClient,
2852
+ cap: kioskCap,
2853
+ })
2854
+
2855
+ const [sudoCard, promise] = kioskTx.borrow({
2856
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
2857
+ itemId: scard,
2858
+ })
2859
+
2860
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
2861
+ [collateralToken, indexToken],
2862
+ tx,
2863
+ pythProUpdateBytes,
2864
+ )
2865
+ tx = tx_
2866
+
2867
+ const suiCoinObject = await this.resolveSponsoredSui(tx, collateralToken, relayerFee, sponsoredTx, sender)
2868
+ const [depositObject, feeObject] = this.processCoinSplitting(
2869
+ tx,
2870
+ collateralToken,
2871
+ coinObjects,
2872
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
2873
+ sponsoredTx,
2874
+ suiCoinObject,
2875
+ )
2876
+
2877
+ tx.moveCall({
2878
+ target: `${this.consts.zoCore.upgradedPackage}::market::open_position_with_scard_v3`,
2879
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
2880
+ arguments: [
2881
+ tx.object(SUI_CLOCK_OBJECT_ID),
2882
+ tx.object(this.consts.zoCore.market),
2883
+ tx.object(this.consts.zoCore.symbols[symbol].positionConfig),
2884
+ ...oracleArgsStandard(oracle),
2885
+ depositObject,
2886
+ feeObject,
2887
+ tx.pure.u8(allowTrade),
2888
+ tx.pure.u64(size),
2889
+ tx.pure.u64(reserveAmount),
2890
+ tx.pure.u256(adjustCollateralPrice),
2891
+ tx.pure.u256(adjustPrice),
2892
+ tx.pure.u256(indexPriceThreshold),
2893
+ sudoCard,
2894
+ ],
2895
+ })
2896
+
2897
+ kioskTx
2898
+ .return({
2899
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
2900
+ item: sudoCard,
2901
+ promise,
2902
+ })
2903
+ .finalize()
2904
+
2905
+ return tx
2906
+ }
2907
+
2908
+ /**
2909
+ * Decreases a position using decrease_position_v3.
2910
+ */
2911
+ public async decreasePositionV3(
2912
+ pcpId: string,
2913
+ collateralToken: string,
2914
+ indexToken: string,
2915
+ amount: bigint,
2916
+ long: boolean,
2917
+ indexPrice: number,
2918
+ collateralPrice: number,
2919
+ pythProUpdateBytes: Uint8Array | number[],
2920
+ isTriggerOrder = false,
2921
+ isTakeProfitOrder = true,
2922
+ isIocOrder = false,
2923
+ pricesSlippage = 0.003,
2924
+ collateralSlippage = 0.5,
2925
+ relayerFee = BigInt(0.5),
2926
+ coinObjects?: string[],
2927
+ sponsoredTx?: boolean,
2928
+ sender?: string,
2929
+ ): Promise<Transaction> {
2930
+ if (!coinObjects?.length && !sender) {
2931
+ throw new Error(`${this.constructor.name}: coinObjects or sender is required`)
2932
+ }
2933
+
2934
+ let tx = new Transaction()
2935
+
2936
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
2937
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2938
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2939
+
2940
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2941
+ if (isTriggerOrder) {
2942
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2943
+ }
2944
+ else {
2945
+ isTakeProfitOrder = true
2946
+ }
2947
+
2948
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
2949
+ [collateralToken, indexToken],
2950
+ tx,
2951
+ pythProUpdateBytes,
2952
+ )
2953
+ tx = tx_
2954
+
2955
+ const suiCoinObject = await this.resolveSponsoredSui(tx, collateralToken, relayerFee, sponsoredTx, sender)
2956
+ const feeObject = await this.resolveRelayerFeeObject(
2957
+ tx,
2958
+ collateralToken,
2959
+ coinObjects ?? [],
2960
+ relayerFee,
2961
+ sponsoredTx,
2962
+ suiCoinObject,
2963
+ sender,
2964
+ )
2965
+
2966
+ tx.moveCall({
2967
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position_v3`,
2968
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
2969
+ arguments: [
2970
+ tx.object(SUI_CLOCK_OBJECT_ID),
2971
+ tx.object(this.consts.zoCore.market),
2972
+ tx.object(pcpId),
2973
+ ...oracleArgsStandard(oracle),
2974
+ feeObject,
2975
+ tx.pure.u8(allowTrade),
2976
+ tx.pure.bool(isTakeProfitOrder),
2977
+ tx.pure.u64(amount),
2978
+ tx.pure.u256(adjustCollateralPrice),
2979
+ tx.pure.u256(adjustPrice),
2980
+ tx.pure.u256(indexPriceThreshold),
2981
+ ],
2982
+ })
2983
+
2984
+ return tx
2985
+ }
2986
+
2987
+ /**
2988
+ * Decreases a position with S Card using decrease_position_with_scard_v3.
2989
+ */
2990
+ public async decreasePositionWithSCardV3(
2991
+ pcpId: string,
2992
+ collateralToken: string,
2993
+ indexToken: string,
2994
+ amount: bigint,
2995
+ long: boolean,
2996
+ indexPrice: number,
2997
+ collateralPrice: number,
2998
+ kioskClient: KioskClient,
2999
+ kioskCap: KioskOwnerCap,
3000
+ scard: string,
3001
+ pythProUpdateBytes: Uint8Array | number[],
3002
+ isTriggerOrder = false,
3003
+ isTakeProfitOrder = true,
3004
+ isIocOrder = false,
3005
+ pricesSlippage = 0.003,
3006
+ collateralSlippage = 0.5,
3007
+ relayerFee = BigInt(0.5),
3008
+ coinObjects?: string[],
3009
+ sponsoredTx?: boolean,
3010
+ sender?: string,
3011
+ ): Promise<Transaction> {
3012
+ if (!coinObjects?.length && !sender) {
3013
+ throw new Error(`${this.constructor.name}: coinObjects or sender is required`)
3014
+ }
3015
+
3016
+ let tx = new Transaction()
3017
+
3018
+ const kioskTx = new KioskTransaction({
3019
+ transaction: tx,
3020
+ kioskClient,
3021
+ cap: kioskCap,
3022
+ })
3023
+
3024
+ const [sudoCard, promise] = kioskTx.borrow({
3025
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
3026
+ itemId: scard,
3027
+ })
3028
+
3029
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
3030
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
3031
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
3032
+
3033
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
3034
+ if (isTriggerOrder) {
3035
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
3036
+ }
3037
+ else {
3038
+ isTakeProfitOrder = true
3039
+ }
3040
+
3041
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
3042
+ [collateralToken, indexToken],
3043
+ tx,
3044
+ pythProUpdateBytes,
3045
+ )
3046
+ tx = tx_
3047
+
3048
+ const suiCoinObject = await this.resolveSponsoredSui(tx, collateralToken, relayerFee, sponsoredTx, sender)
3049
+ const feeObject = await this.resolveRelayerFeeObject(
3050
+ tx,
3051
+ collateralToken,
3052
+ coinObjects ?? [],
3053
+ relayerFee,
3054
+ sponsoredTx,
3055
+ suiCoinObject,
3056
+ sender,
3057
+ )
3058
+
3059
+ tx.moveCall({
3060
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position_with_scard_v3`,
3061
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
3062
+ arguments: [
3063
+ tx.object(SUI_CLOCK_OBJECT_ID),
3064
+ tx.object(this.consts.zoCore.market),
3065
+ tx.object(pcpId),
3066
+ ...oracleArgsStandard(oracle),
3067
+ feeObject,
3068
+ tx.pure.u8(allowTrade),
3069
+ tx.pure.bool(isTakeProfitOrder),
3070
+ tx.pure.u64(amount),
3071
+ tx.pure.u256(adjustCollateralPrice),
3072
+ tx.pure.u256(adjustPrice),
3073
+ tx.pure.u256(indexPriceThreshold),
3074
+ sudoCard,
3075
+ ],
3076
+ })
3077
+
3078
+ kioskTx
3079
+ .return({
3080
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
3081
+ item: sudoCard,
3082
+ promise,
3083
+ })
3084
+ .finalize()
3085
+ return tx
3086
+ }
3087
+
3088
+ /**
3089
+ * Redeems collateral from a position via redeem_from_position_v2 (Pyth Pro path).
3090
+ */
3091
+ public async redeemFromPositionV2(
3092
+ pcpId: string,
3093
+ collateralToken: string,
3094
+ indexToken: string,
3095
+ amount: number,
3096
+ long: boolean,
3097
+ pythProUpdateBytes: Uint8Array | number[],
3098
+ tx?: Transaction,
3099
+ ): Promise<Transaction> {
3100
+ if (!tx) {
3101
+ tx = new Transaction()
3102
+ }
3103
+
3104
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
3105
+ [collateralToken, indexToken],
3106
+ tx,
3107
+ pythProUpdateBytes,
3108
+ )
3109
+
3110
+ tx_.moveCall({
3111
+ target: `${this.consts.zoCore.upgradedPackage}::market::redeem_from_position_v2`,
3112
+ typeArguments: this.redeemTypeArgs(collateralToken, indexToken, long),
3113
+ arguments: [
3114
+ tx_.object(SUI_CLOCK_OBJECT_ID),
3115
+ tx_.object(this.consts.zoCore.market),
3116
+ tx_.object(pcpId),
3117
+ ...oracleArgsStandard(oracle),
3118
+ tx_.pure.u64(amount),
3119
+ ],
3120
+ })
3121
+
3122
+ return tx_
3123
+ }
3124
+
3125
+ /**
3126
+ * Liquidates a position (PTB-only public fun). Use liquidate_position_v3_1, not v3.
3127
+ */
3128
+ public liquidatePositionV3_1(
3129
+ tx: Transaction,
3130
+ owner: string,
3131
+ positionId: string,
3132
+ collateralToken: string,
3133
+ indexToken: string,
3134
+ long: boolean,
3135
+ oracle: OracleInputsAlt,
3136
+ ): void {
3137
+ tx.moveCall({
3138
+ target: `${this.consts.zoCore.upgradedPackage}::market::liquidate_position_v3_1`,
3139
+ typeArguments: this.redeemTypeArgs(collateralToken, indexToken, long),
3140
+ arguments: [
3141
+ tx.object(this.consts.zoCore.market),
3142
+ ...oracleArgsAlt(oracle),
3143
+ tx.object(owner),
3144
+ tx.object(positionId),
3145
+ ],
3146
+ })
3147
+ }
3148
+
3149
+ /**
3150
+ * Builds a full liquidate PTB including Pyth Pro verification.
3151
+ */
3152
+ public async liquidatePositionV3_1Tx(
3153
+ owner: string,
3154
+ positionId: string,
3155
+ collateralToken: string,
3156
+ indexToken: string,
3157
+ long: boolean,
3158
+ pythProUpdateBytes: Uint8Array | number[],
3159
+ tx?: Transaction,
3160
+ ): Promise<Transaction> {
3161
+ if (!tx) {
3162
+ tx = new Transaction()
3163
+ }
3164
+ const { tx: tx_, oracle } = await this.initV3OracleForTokens(
3165
+ [collateralToken, indexToken],
3166
+ tx,
3167
+ pythProUpdateBytes,
3168
+ )
3169
+ this.liquidatePositionV3_1(
3170
+ tx_,
3171
+ owner,
3172
+ positionId,
3173
+ collateralToken,
3174
+ indexToken,
3175
+ long,
3176
+ buildOracleInputsAlt(oracle),
3177
+ )
3178
+ return tx_
3179
+ }
3180
+
3181
+ /** Keeper/bot: execute_open_position_order_v3_1 (compose in PTB). */
3182
+ public executeOpenPositionOrderV3_1(
3183
+ tx: Transaction,
3184
+ owner: string,
3185
+ orderId: string,
3186
+ collateralToken: string,
3187
+ indexToken: string,
3188
+ long: boolean,
3189
+ oracle: OracleInputsAlt,
3190
+ ): void {
3191
+ tx.moveCall({
3192
+ target: `${this.consts.zoCore.upgradedPackage}::market::execute_open_position_order_v3_1`,
3193
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
3194
+ arguments: [
3195
+ tx.object(this.consts.zoCore.market),
3196
+ ...oracleArgsAlt(oracle),
3197
+ tx.object(owner),
3198
+ tx.object(orderId),
3199
+ ],
3200
+ })
3201
+ }
3202
+
3203
+ /** Keeper/bot: execute_open_market_order_v3_1. */
3204
+ public executeOpenMarketOrderV3_1(
3205
+ tx: Transaction,
3206
+ owner: string,
3207
+ orderId: string,
3208
+ collateralToken: string,
3209
+ indexToken: string,
3210
+ long: boolean,
3211
+ oracle: OracleInputsAlt,
3212
+ ): void {
3213
+ tx.moveCall({
3214
+ target: `${this.consts.zoCore.upgradedPackage}::market::execute_open_market_order_v3_1`,
3215
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
3216
+ arguments: [
3217
+ tx.object(this.consts.zoCore.market),
3218
+ ...oracleArgsAlt(oracle),
3219
+ tx.object(owner),
3220
+ tx.object(orderId),
3221
+ ],
3222
+ })
3223
+ }
3224
+
3225
+ /** Keeper/bot: execute_decrease_market_order_v3_1. */
3226
+ public executeDecreaseMarketOrderV3_1(
3227
+ tx: Transaction,
3228
+ owner: string,
3229
+ orderId: string,
3230
+ positionId: string,
3231
+ collateralToken: string,
3232
+ indexToken: string,
3233
+ long: boolean,
3234
+ oracle: OracleInputsAlt,
3235
+ ): void {
3236
+ tx.moveCall({
3237
+ target: `${this.consts.zoCore.upgradedPackage}::market::execute_decrease_market_order_v3_1`,
3238
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
3239
+ arguments: [
3240
+ tx.object(this.consts.zoCore.market),
3241
+ ...oracleArgsAlt(oracle),
3242
+ tx.object(owner),
3243
+ tx.object(orderId),
3244
+ tx.object(positionId),
3245
+ ],
3246
+ })
3247
+ }
3248
+
3249
+ /** Keeper/bot: execute_decrease_position_order_v3_1. */
3250
+ public executeDecreasePositionOrderV3_1(
3251
+ tx: Transaction,
3252
+ owner: string,
3253
+ orderId: string,
3254
+ positionId: string,
3255
+ collateralToken: string,
3256
+ indexToken: string,
3257
+ long: boolean,
3258
+ oracle: OracleInputsAlt,
3259
+ ): void {
3260
+ tx.moveCall({
3261
+ target: `${this.consts.zoCore.upgradedPackage}::market::execute_decrease_position_order_v3_1`,
3262
+ typeArguments: this.positionTypeArgs(collateralToken, indexToken, long),
3263
+ arguments: [
3264
+ tx.object(this.consts.zoCore.market),
3265
+ ...oracleArgsAlt(oracle),
3266
+ tx.object(owner),
3267
+ tx.object(orderId),
3268
+ tx.object(positionId),
3269
+ ],
3270
+ })
3271
+ }
2642
3272
  }