zo-sdk 0.1.21 → 0.1.23

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 (94) hide show
  1. package/dist/abstract/BaseDataAPI.d.cts +2 -2
  2. package/dist/abstract/BaseDataAPI.d.cts.map +1 -1
  3. package/dist/abstract/BaseDataAPI.d.mts +2 -2
  4. package/dist/abstract/BaseDataAPI.d.mts.map +1 -1
  5. package/dist/consts/deployments-zbtcvc-mainnet.json +180 -0
  6. package/dist/consts/index.cjs +27 -20
  7. package/dist/consts/index.cjs.map +1 -1
  8. package/dist/consts/index.d.cts +5 -17
  9. package/dist/consts/index.d.cts.map +1 -1
  10. package/dist/consts/index.d.mts +5 -17
  11. package/dist/consts/index.d.mts.map +1 -1
  12. package/dist/consts/index.mjs +26 -19
  13. package/dist/consts/index.mjs.map +1 -1
  14. package/dist/factory/SDKFactory.cjs +36 -0
  15. package/dist/factory/SDKFactory.cjs.map +1 -1
  16. package/dist/factory/SDKFactory.d.cts +11 -1
  17. package/dist/factory/SDKFactory.d.cts.map +1 -1
  18. package/dist/factory/SDKFactory.d.mts +11 -1
  19. package/dist/factory/SDKFactory.d.mts.map +1 -1
  20. package/dist/factory/SDKFactory.mjs +36 -0
  21. package/dist/factory/SDKFactory.mjs.map +1 -1
  22. package/dist/implementations/SLPDataAPI.cjs +54 -32
  23. package/dist/implementations/SLPDataAPI.cjs.map +1 -1
  24. package/dist/implementations/SLPDataAPI.d.cts +2 -2
  25. package/dist/implementations/SLPDataAPI.d.cts.map +1 -1
  26. package/dist/implementations/SLPDataAPI.d.mts +2 -2
  27. package/dist/implementations/SLPDataAPI.d.mts.map +1 -1
  28. package/dist/implementations/SLPDataAPI.mjs +54 -32
  29. package/dist/implementations/SLPDataAPI.mjs.map +1 -1
  30. package/dist/implementations/USDZAPI.cjs +1 -1
  31. package/dist/implementations/USDZAPI.cjs.map +1 -1
  32. package/dist/implementations/USDZAPI.d.cts +1 -1
  33. package/dist/implementations/USDZAPI.d.cts.map +1 -1
  34. package/dist/implementations/USDZAPI.d.mts +1 -1
  35. package/dist/implementations/USDZAPI.d.mts.map +1 -1
  36. package/dist/implementations/USDZAPI.mjs +1 -1
  37. package/dist/implementations/USDZAPI.mjs.map +1 -1
  38. package/dist/implementations/ZBTCVCAPI.cjs +984 -0
  39. package/dist/implementations/ZBTCVCAPI.cjs.map +1 -0
  40. package/dist/implementations/ZBTCVCAPI.d.cts +133 -0
  41. package/dist/implementations/ZBTCVCAPI.d.cts.map +1 -0
  42. package/dist/implementations/ZBTCVCAPI.d.mts +133 -0
  43. package/dist/implementations/ZBTCVCAPI.d.mts.map +1 -0
  44. package/dist/implementations/ZBTCVCAPI.mjs +980 -0
  45. package/dist/implementations/ZBTCVCAPI.mjs.map +1 -0
  46. package/dist/implementations/ZBTCVCDataAPI.cjs +824 -0
  47. package/dist/implementations/ZBTCVCDataAPI.cjs.map +1 -0
  48. package/dist/implementations/ZBTCVCDataAPI.d.cts +94 -0
  49. package/dist/implementations/ZBTCVCDataAPI.d.cts.map +1 -0
  50. package/dist/implementations/ZBTCVCDataAPI.d.mts +94 -0
  51. package/dist/implementations/ZBTCVCDataAPI.d.mts.map +1 -0
  52. package/dist/implementations/ZBTCVCDataAPI.mjs +820 -0
  53. package/dist/implementations/ZBTCVCDataAPI.mjs.map +1 -0
  54. package/dist/implementations/index.cjs +5 -1
  55. package/dist/implementations/index.cjs.map +1 -1
  56. package/dist/implementations/index.d.cts +2 -0
  57. package/dist/implementations/index.d.cts.map +1 -1
  58. package/dist/implementations/index.d.mts +2 -0
  59. package/dist/implementations/index.d.mts.map +1 -1
  60. package/dist/implementations/index.mjs +2 -0
  61. package/dist/implementations/index.mjs.map +1 -1
  62. package/dist/interfaces/base.d.cts +2 -2
  63. package/dist/interfaces/base.d.cts.map +1 -1
  64. package/dist/interfaces/base.d.mts +2 -2
  65. package/dist/interfaces/base.d.mts.map +1 -1
  66. package/dist/interfaces/index.cjs +2 -0
  67. package/dist/interfaces/index.cjs.map +1 -1
  68. package/dist/interfaces/index.d.cts +2 -0
  69. package/dist/interfaces/index.d.cts.map +1 -1
  70. package/dist/interfaces/index.d.mts +2 -0
  71. package/dist/interfaces/index.d.mts.map +1 -1
  72. package/dist/interfaces/index.mjs +2 -0
  73. package/dist/interfaces/index.mjs.map +1 -1
  74. package/dist/interfaces/zbtcvc.cjs +7 -0
  75. package/dist/interfaces/zbtcvc.cjs.map +1 -0
  76. package/dist/interfaces/zbtcvc.d.cts +64 -0
  77. package/dist/interfaces/zbtcvc.d.cts.map +1 -0
  78. package/dist/interfaces/zbtcvc.d.mts +64 -0
  79. package/dist/interfaces/zbtcvc.d.mts.map +1 -0
  80. package/dist/interfaces/zbtcvc.mjs +6 -0
  81. package/dist/interfaces/zbtcvc.mjs.map +1 -0
  82. package/package.json +8 -8
  83. package/src/abstract/BaseDataAPI.ts +2 -2
  84. package/src/consts/deployments-zbtcvc-mainnet.json +180 -0
  85. package/src/consts/index.ts +28 -35
  86. package/src/factory/SDKFactory.ts +50 -0
  87. package/src/implementations/SLPDataAPI.ts +71 -41
  88. package/src/implementations/USDZAPI.ts +1 -1
  89. package/src/implementations/ZBTCVCAPI.ts +1453 -0
  90. package/src/implementations/ZBTCVCDataAPI.ts +985 -0
  91. package/src/implementations/index.ts +2 -0
  92. package/src/interfaces/base.ts +2 -2
  93. package/src/interfaces/index.ts +8 -0
  94. package/src/interfaces/zbtcvc.ts +115 -0
@@ -0,0 +1,1453 @@
1
+ /**
2
+ * ZBTCVC API implementation
3
+ * Implements ZBTCVC-specific trading and transaction methods
4
+ */
5
+
6
+ import type { KioskClient, KioskOwnerCap } from '@mysten/kiosk'
7
+ import { KioskTransaction } from '@mysten/kiosk'
8
+ import type { SuiClient } from '@mysten/sui/client'
9
+ import { Transaction } from '@mysten/sui/transactions'
10
+ import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils'
11
+
12
+ import { BaseAPI } from '../abstract'
13
+ import type { Network } from '../consts'
14
+ import { ALLOW_TRADE_CAN_TRADE, ALLOW_TRADE_MUST_TRADE, ALLOW_TRADE_NO_TRADE, LPToken } from '../consts'
15
+ import type {
16
+ IBaseHistoryResponse,
17
+ IBaseMarketInfo,
18
+ IBaseMarketValuationInfo,
19
+ IBaseOrderCapInfo,
20
+ IBaseOrderInfo,
21
+ IBasePositionCapInfo,
22
+ IBasePositionConfig,
23
+ IBasePositionInfo,
24
+ IBaseRebaseFeeModel,
25
+ IBaseStaked,
26
+ IBaseStakePool,
27
+ IBaseSymbolInfo,
28
+ IBaseVaultInfo,
29
+ IZBTCVCAPI,
30
+ IZBTCVCCredential,
31
+ } from '../interfaces'
32
+ import { joinSymbol } from '../utils'
33
+ import { ZBTCVCDataAPI } from './ZBTCVCDataAPI'
34
+
35
+ export class ZBTCVCAPI extends BaseAPI implements IZBTCVCAPI {
36
+ public dataAPI: ZBTCVCDataAPI
37
+
38
+ constructor(
39
+ network: Network,
40
+ provider: SuiClient,
41
+ apiEndpoint: string,
42
+ connectionURL: string,
43
+ ) {
44
+ super(network, provider, apiEndpoint, connectionURL, LPToken.ZBTCVC)
45
+ this.dataAPI = new ZBTCVCDataAPI(network, provider, apiEndpoint, connectionURL)
46
+ }
47
+
48
+ public claimTokenFromSCard(_token: string, _coinObjects: string[], _kioskClient: KioskClient, _kioskCap: KioskOwnerCap, _scard: string): Transaction {
49
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
50
+ }
51
+
52
+ public valuateVaults(_tx: Transaction) {
53
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
54
+ }
55
+
56
+ public valuateSymbols(_tx: Transaction) {
57
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
58
+ }
59
+
60
+ public valuate(_tx: Transaction): { vaultsValuation: any, symbolsValuation: any } {
61
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
62
+ }
63
+
64
+ public valuateMarket(): Promise<IBaseMarketValuationInfo> {
65
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
66
+ }
67
+
68
+ public fundingFeeRate(_indexToken: string, _long: boolean): Promise<number> {
69
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
70
+ }
71
+
72
+ public rebaseFeeRate(_collateralToken: string, _increase: boolean, _amount: number): Promise<number> {
73
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
74
+ }
75
+
76
+ public reservingFeeRate(_collateralToken: string, _amount: number): Promise<number> {
77
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
78
+ }
79
+
80
+ public calcPositionReserveFeeAmount(_position: IBasePositionInfo): Promise<number> {
81
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
82
+ }
83
+
84
+ public calcPositionFundingFeeValue(_position: IBasePositionInfo): Promise<number> {
85
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
86
+ }
87
+
88
+ public getMarketInfo(): Promise<IBaseMarketInfo> {
89
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
90
+ }
91
+
92
+ public getVaultInfo(_vault: string): Promise<IBaseVaultInfo> {
93
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
94
+ }
95
+
96
+ public getSymbolInfo(_tokenId: string, _long: boolean): Promise<IBaseSymbolInfo> {
97
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
98
+ }
99
+
100
+ public getPositionConfig(_indexToken: string, _long: boolean): Promise<IBasePositionConfig> {
101
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
102
+ }
103
+
104
+ public getRebaseFeeModel(): Promise<IBaseRebaseFeeModel> {
105
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
106
+ }
107
+
108
+ public getOpenPositions(): Promise<IBasePositionInfo[]> {
109
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
110
+ }
111
+
112
+ public getPositionCapInfoList(_owner: string): Promise<IBasePositionCapInfo[]> {
113
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
114
+ }
115
+
116
+ public getPositionInfoList(_positionCapInfoList: IBasePositionCapInfo[], _owner: string, _batchSize?: number): Promise<IBasePositionInfo[]> {
117
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
118
+ }
119
+
120
+ public getOrderCapInfoList(_owner: string): Promise<IBaseOrderCapInfo[]> {
121
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
122
+ }
123
+
124
+ public getOrderInfoList(_orderCapInfoList: IBaseOrderCapInfo[], _owner: string): Promise<IBaseOrderInfo[]> {
125
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
126
+ }
127
+
128
+ public getHistory(_trader: string, _page: number, _limit: number, _orderType?: string, _symbol?: string): Promise<IBaseHistoryResponse> {
129
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
130
+ }
131
+
132
+ public getStaked(_owner: string): Promise<IBaseStaked> {
133
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
134
+ }
135
+
136
+ public getStakePool(): Promise<IBaseStakePool> {
137
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
138
+ }
139
+
140
+ public hasReferral(_referree: string): Promise<boolean> {
141
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
142
+ }
143
+
144
+ public getReferralData(_referree: string): Promise<any> {
145
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
146
+ }
147
+
148
+ public clearClosedPosition(pcpId: string, collateralToken: string, indexToken: string, long: boolean, tx: Transaction): void {
149
+ tx.moveCall({
150
+ target: `${this.consts.zoCore.upgradedPackage}::market::clear_closed_position`,
151
+ typeArguments: [
152
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
153
+ this.consts.coins[collateralToken].module,
154
+ this.consts.coins[indexToken].module,
155
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
156
+ ],
157
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(pcpId)],
158
+ })
159
+ }
160
+
161
+ public clearOpenPositionOrder(orderCapId: string, collateralToken: string, indexToken: string, long: boolean, tx: Transaction, isV11Order?: boolean): void {
162
+ const funcName = isV11Order ? 'clear_open_position_order' : 'clear_open_position_order'
163
+ tx.moveCall({
164
+ target: `${this.consts.zoCore.upgradedPackage}::market::${funcName}`,
165
+ typeArguments: [
166
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
167
+ this.consts.coins[collateralToken].module,
168
+ this.consts.coins[indexToken].module,
169
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
170
+ this.consts.coins[collateralToken].module,
171
+ ],
172
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(orderCapId)],
173
+ })
174
+ }
175
+
176
+ public clearDecreasePositionOrder(orderCapId: string, collateralToken: string, indexToken: string, long: boolean, tx: Transaction, isV11Order?: boolean): void {
177
+ const funcName = isV11Order ? 'clear_decrease_position_order' : 'clear_decrease_position_order'
178
+ tx.moveCall({
179
+ target: `${this.consts.zoCore.upgradedPackage}::market::${funcName}`,
180
+ typeArguments: [
181
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
182
+ this.consts.coins[collateralToken].module,
183
+ this.consts.coins[indexToken].module,
184
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
185
+ this.consts.coins[collateralToken].module,
186
+ ],
187
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(orderCapId)],
188
+ })
189
+ }
190
+
191
+ public async openPositionWithSCard(
192
+ collateralToken: string,
193
+ indexToken: string,
194
+ size: bigint,
195
+ collateralAmount: bigint,
196
+ coinObjects: string[],
197
+ long: boolean,
198
+ reserveAmount: bigint,
199
+ indexPrice: number,
200
+ collateralPrice: number,
201
+ kioskClient: KioskClient,
202
+ kioskCap: KioskOwnerCap,
203
+ scard: string,
204
+ isLimitOrder?: boolean,
205
+ isIocOrder?: boolean,
206
+ pricesSlippage = 0.003,
207
+ collateralSlippage = 0.5,
208
+ relayerFee = BigInt(0.5),
209
+ referralAddress?: string,
210
+ sender?: string,
211
+ sponsoredTx?: boolean,
212
+ suiCoinObjectsForPythUpdate?: string[],
213
+ ): Promise<Transaction> {
214
+ let tx = new Transaction()
215
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
216
+ tx = await this.addReferral(referralAddress, tx)
217
+ }
218
+
219
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
220
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
221
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
222
+
223
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
224
+ if (isLimitOrder) {
225
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
226
+ }
227
+
228
+ const kioskTx = new KioskTransaction({
229
+ transaction: tx,
230
+ kioskClient,
231
+ cap: kioskCap,
232
+ })
233
+
234
+ const [sudoCard, promise] = kioskTx.borrow({
235
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
236
+ itemId: scard,
237
+ })
238
+
239
+ // Handle oracle initialization and coin processing
240
+ let suiCoinObject
241
+ if (sponsoredTx) {
242
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
243
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
244
+ }
245
+ else {
246
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
247
+ }
248
+
249
+ // Process coin splitting
250
+ const [depositObject, feeObject] = this.processCoinSplitting(
251
+ tx,
252
+ collateralToken,
253
+ coinObjects,
254
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
255
+ sponsoredTx,
256
+ suiCoinObject,
257
+ )
258
+
259
+ tx.moveCall({
260
+ target: `${this.consts.zoCore.upgradedPackage}::market::open_position_with_scard`,
261
+ typeArguments: [
262
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
263
+ this.consts.coins[collateralToken].module,
264
+ this.consts.coins[indexToken].module,
265
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
266
+ this.consts.coins[collateralToken].module,
267
+ ],
268
+ arguments: [
269
+ tx.object(SUI_CLOCK_OBJECT_ID),
270
+ tx.object(this.consts.zoCore.market),
271
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
272
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
273
+ tx.object(this.consts.zoCore.symbols[symbol].positionConfig),
274
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
275
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
276
+ depositObject,
277
+ feeObject,
278
+ tx.pure.u8(allowTrade),
279
+ tx.pure.u64(size),
280
+ tx.pure.u64(reserveAmount),
281
+ tx.pure.u256(adjustCollateralPrice),
282
+ tx.pure.u256(adjustPrice),
283
+ sudoCard,
284
+ ],
285
+ })
286
+
287
+ kioskTx
288
+ .return({
289
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
290
+ item: sudoCard,
291
+ promise,
292
+ })
293
+ .finalize()
294
+ return tx
295
+ }
296
+
297
+ public async decreasePositionWithSCard(
298
+ pcpId: string,
299
+ collateralToken: string,
300
+ indexToken: string,
301
+ amount: bigint,
302
+ long: boolean,
303
+ indexPrice: number,
304
+ collateralPrice: number,
305
+ kioskClient: KioskClient,
306
+ kioskCap: KioskOwnerCap,
307
+ scard: string,
308
+ isTriggerOrder = false,
309
+ isTakeProfitOrder = true,
310
+ isIocOrder = false,
311
+ pricesSlippage = 0.003,
312
+ collateralSlippage = 0.5,
313
+ relayerFee = BigInt(0.5),
314
+ coinObjects?: string[],
315
+ sponsoredTx?: boolean,
316
+ suiCoinObjectsForPythUpdate?: string[],
317
+ ): Promise<Transaction> {
318
+ if (!coinObjects) {
319
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
320
+ }
321
+
322
+ let tx = new Transaction()
323
+
324
+ const kioskTx = new KioskTransaction({
325
+ transaction: tx,
326
+ kioskClient,
327
+ cap: kioskCap,
328
+ })
329
+
330
+ const [sudoCard, promise] = kioskTx.borrow({
331
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
332
+ itemId: scard,
333
+ })
334
+
335
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
336
+
337
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
338
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
339
+
340
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
341
+ if (isTriggerOrder) {
342
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
343
+ }
344
+ else {
345
+ isTakeProfitOrder = true
346
+ }
347
+
348
+ // Handle oracle initialization and coin processing
349
+ let suiCoinObject
350
+ if (sponsoredTx) {
351
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
352
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
353
+ }
354
+ else {
355
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
356
+ }
357
+
358
+ // Process coin splitting
359
+ const [feeObject] = this.processCoinSplitting(
360
+ tx,
361
+ collateralToken,
362
+ coinObjects,
363
+ [tx.pure.u64(relayerFee)],
364
+ sponsoredTx,
365
+ suiCoinObject,
366
+ )
367
+
368
+ tx.moveCall({
369
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position_with_scard`,
370
+ typeArguments: [
371
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
372
+ this.consts.coins[collateralToken].module,
373
+ this.consts.coins[indexToken].module,
374
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
375
+ this.consts.coins[collateralToken].module,
376
+ ],
377
+ arguments: [
378
+ tx.object(SUI_CLOCK_OBJECT_ID),
379
+ tx.object(this.consts.zoCore.market),
380
+ tx.object(pcpId),
381
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
382
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
383
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
384
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
385
+ feeObject,
386
+ tx.pure.u8(allowTrade),
387
+ tx.pure.bool(isTakeProfitOrder),
388
+ tx.pure.u64(amount),
389
+ tx.pure.u256(adjustCollateralPrice),
390
+ tx.pure.u256(adjustPrice),
391
+ sudoCard,
392
+ ],
393
+ })
394
+
395
+ kioskTx
396
+ .return({
397
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
398
+ item: sudoCard,
399
+ promise,
400
+ })
401
+ .finalize()
402
+ return tx
403
+ }
404
+
405
+ public async decreaseMultiPositionsWithSCard(
406
+ positions: Array<{
407
+ pcpId: string
408
+ collateralToken: string
409
+ indexToken: string
410
+ amount: bigint
411
+ long: boolean
412
+ indexPrice: number
413
+ collateralPrice: number
414
+ isTriggerOrder?: boolean
415
+ isTakeProfitOrder?: boolean
416
+ isIocOrder?: boolean
417
+ pricesSlippage?: number
418
+ collateralSlippage?: number
419
+ relayerFee?: bigint
420
+ coinObjects?: string[]
421
+ }>,
422
+ kioskClient: KioskClient,
423
+ kioskCap: KioskOwnerCap,
424
+ scard: string,
425
+ tx?: Transaction,
426
+ sponsoredTx?: boolean,
427
+ suiCoinObjectsForPythUpdate?: string[],
428
+ ): Promise<Transaction> {
429
+ if (!tx) {
430
+ tx = new Transaction()
431
+ }
432
+
433
+ // Handle oracle initialization and coin processing
434
+ let suiCoinObject
435
+ if (sponsoredTx) {
436
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
437
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx, true, suiCoinObject)
438
+ }
439
+ else {
440
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx)
441
+ }
442
+
443
+ const kioskTx = new KioskTransaction({
444
+ transaction: tx,
445
+ kioskClient,
446
+ cap: kioskCap,
447
+ })
448
+
449
+ const [sudoCard, promise] = kioskTx.borrow({
450
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
451
+ itemId: scard,
452
+ })
453
+
454
+ for (const position of positions) {
455
+ const {
456
+ pcpId,
457
+ collateralToken,
458
+ coinObjects = [],
459
+ indexToken,
460
+ amount,
461
+ long,
462
+ indexPrice,
463
+ collateralPrice,
464
+ isTriggerOrder = false,
465
+ isTakeProfitOrder = true,
466
+ isIocOrder = false,
467
+ pricesSlippage = 0.003,
468
+ collateralSlippage = 0.5,
469
+ relayerFee = BigInt(0.5),
470
+ } = position
471
+ let innerIsTakeProfitOrder = isTakeProfitOrder
472
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
473
+
474
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
475
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
476
+
477
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
478
+ if (isTriggerOrder) {
479
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
480
+ }
481
+ else {
482
+ innerIsTakeProfitOrder = true
483
+ }
484
+
485
+ // Process coin splitting
486
+ const [feeObject] = this.processCoinSplitting(
487
+ tx,
488
+ collateralToken,
489
+ coinObjects,
490
+ [tx.pure.u64(relayerFee)],
491
+ sponsoredTx,
492
+ suiCoinObject,
493
+ )
494
+
495
+ tx.moveCall({
496
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position_with_scard`,
497
+ typeArguments: [
498
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
499
+ this.consts.coins[collateralToken].module,
500
+ this.consts.coins[indexToken].module,
501
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
502
+ this.consts.coins[collateralToken].module,
503
+ ],
504
+ arguments: [
505
+ tx.object(SUI_CLOCK_OBJECT_ID),
506
+ tx.object(this.consts.zoCore.market),
507
+ tx.object(pcpId),
508
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
509
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
510
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
511
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
512
+ feeObject,
513
+ tx.pure.u8(allowTrade),
514
+ tx.pure.bool(innerIsTakeProfitOrder),
515
+ tx.pure.u64(amount),
516
+ tx.pure.u256(adjustCollateralPrice),
517
+ tx.pure.u256(adjustPrice),
518
+ sudoCard,
519
+ ],
520
+ })
521
+ }
522
+
523
+ kioskTx
524
+ .return({
525
+ itemType: `0xe7e651e4974fe367aa2837712d68081efb299c470242a15e2b9c26ea326159ec::card::SudoCard`,
526
+ item: sudoCard,
527
+ promise,
528
+ })
529
+ .finalize()
530
+ return tx
531
+ }
532
+
533
+ /**
534
+ * Deposits collateral into ZBTCVC vault
535
+ */
536
+ public async deposit(
537
+ coin: string,
538
+ coinObjects: string[],
539
+ amount: number,
540
+ minAmountOut = 0,
541
+ referralAddress?: string,
542
+ sender?: string,
543
+ sponsoredTx?: boolean,
544
+ suiCoinObjectsForPythUpdate?: string[],
545
+ ): Promise<Transaction> {
546
+ let tx = new Transaction()
547
+
548
+ // Add referral if needed
549
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
550
+ tx = await this.addReferral(referralAddress, tx)
551
+ }
552
+
553
+ // Initialize oracle transaction
554
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
555
+
556
+ // Handle sponsored transaction case
557
+ if (sponsoredTx) {
558
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
559
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
560
+
561
+ // Process deposit coins
562
+ const depositObject = coin === 'sui'
563
+ ? tx.splitCoins(suiCoinObject, [tx.pure.u64(amount)])[0]
564
+ : tx.splitCoins(this.processCoins(tx, coin, coinObjects, true), [tx.pure.u64(amount)])[0]
565
+
566
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
567
+
568
+ tx.moveCall({
569
+ target: `${this.consts.zoCore.upgradedPackage}::market::deposit`,
570
+ typeArguments: [`${this.consts.zoCore.package}::zbtcvc::ZBTCVC`, this.consts.coins[coin].module],
571
+ arguments: [
572
+ tx.object(this.consts.zoCore.market),
573
+ tx.object(this.consts.zoCore.rebaseFeeModel),
574
+ depositObject,
575
+ tx.pure.u64(minAmountOut),
576
+ vaultsValuation,
577
+ symbolsValuation,
578
+ ],
579
+ })
580
+ return tx
581
+ }
582
+
583
+ // Handle non-sponsored transaction case
584
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
585
+ const depositObject = tx.splitCoins(
586
+ this.processCoins(tx, coin, coinObjects, false),
587
+ [tx.pure.u64(amount)],
588
+ )[0]
589
+
590
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
591
+
592
+ tx.moveCall({
593
+ target: `${this.consts.zoCore.upgradedPackage}::market::deposit`,
594
+ typeArguments: [
595
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
596
+ this.consts.coins[coin].module,
597
+ ],
598
+ arguments: [
599
+ tx.object(this.consts.zoCore.market),
600
+ tx.object(this.consts.zoCore.rebaseFeeModel),
601
+ depositObject,
602
+ tx.pure.u64(minAmountOut),
603
+ vaultsValuation,
604
+ symbolsValuation,
605
+ ],
606
+ })
607
+ return tx
608
+ }
609
+
610
+ /**
611
+ * Deposits collateral into ZBTCVC vault
612
+ */
613
+ public async depositPtb(
614
+ coin: string,
615
+ coinObjects: string[],
616
+ amount: number,
617
+ minAmountOut = 0,
618
+ referralAddress?: string,
619
+ sender?: string,
620
+ tx?: Transaction,
621
+ sponsoredTx?: boolean,
622
+ suiCoinObjectsForPythUpdate?: string[],
623
+ ): Promise<any> {
624
+ if (!tx) {
625
+ tx = new Transaction()
626
+ }
627
+
628
+ // Add referral if needed
629
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
630
+ tx = await this.addReferral(referralAddress, tx)
631
+ }
632
+
633
+ // Initialize oracle transaction
634
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
635
+
636
+ // Handle sponsored transaction case
637
+ if (sponsoredTx) {
638
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
639
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
640
+
641
+ // Process deposit coins
642
+ const depositObject = coin === 'sui'
643
+ ? tx.splitCoins(suiCoinObject, [tx.pure.u64(amount)])[0]
644
+ : tx.splitCoins(this.processCoins(tx, coin, coinObjects, true), [tx.pure.u64(amount)])[0]
645
+
646
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
647
+
648
+ const [mintedCoin] = tx.moveCall({
649
+ target: `${this.consts.zoCore.upgradedPackage}::market::deposit_ptb`,
650
+ typeArguments: [`${this.consts.zoCore.package}::zbtcvc::ZBTCVC`, this.consts.coins[coin].module],
651
+ arguments: [
652
+ tx.object(this.consts.zoCore.market),
653
+ tx.object(this.consts.zoCore.rebaseFeeModel),
654
+ depositObject,
655
+ tx.pure.u64(minAmountOut),
656
+ vaultsValuation,
657
+ symbolsValuation,
658
+ ],
659
+ })
660
+ return mintedCoin
661
+ }
662
+
663
+ // Handle non-sponsored transaction case
664
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
665
+ const depositObject = tx.splitCoins(
666
+ this.processCoins(tx, coin, coinObjects, false),
667
+ [tx.pure.u64(amount)],
668
+ )[0]
669
+
670
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
671
+
672
+ const [mintedCoin] = tx.moveCall({
673
+ target: `${this.consts.zoCore.upgradedPackage}::market::deposit_ptb`,
674
+ typeArguments: [
675
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
676
+ this.consts.coins[coin].module,
677
+ ],
678
+ arguments: [
679
+ tx.object(this.consts.zoCore.market),
680
+ tx.object(this.consts.zoCore.rebaseFeeModel),
681
+ depositObject,
682
+ tx.pure.u64(minAmountOut),
683
+ vaultsValuation,
684
+ symbolsValuation,
685
+ ],
686
+ })
687
+
688
+ return mintedCoin
689
+ }
690
+
691
+ /**
692
+ * Withdraws collateral from ZBTCVC vault
693
+ */
694
+ public async withdraw(
695
+ coin: string,
696
+ lpCoinObjects: string[],
697
+ amount: number,
698
+ minAmountOut = 0,
699
+ sponsoredTx?: boolean,
700
+ suiCoinObjectsForPythUpdate?: string[],
701
+ ): Promise<Transaction> {
702
+ let tx = new Transaction()
703
+
704
+ // Initialize oracle transaction
705
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
706
+
707
+ if (sponsoredTx) {
708
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
709
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
710
+ }
711
+ else {
712
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
713
+ }
714
+ const zbtcvcCoinObject = this.processCoins(tx, 'zbtcvc', lpCoinObjects, false)
715
+ const [withdrawObject] = tx.splitCoins(zbtcvcCoinObject, [tx.pure.u64(amount)])
716
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
717
+
718
+ tx.moveCall({
719
+ target: `${this.consts.zoCore.upgradedPackage}::market::withdraw`,
720
+ typeArguments: [
721
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
722
+ this.consts.coins[coin].module,
723
+ ],
724
+ arguments: [
725
+ tx.object(this.consts.zoCore.market),
726
+ tx.object(this.consts.zoCore.rebaseFeeModel),
727
+ withdrawObject,
728
+ tx.pure.u64(minAmountOut),
729
+ vaultsValuation,
730
+ symbolsValuation,
731
+ ],
732
+ })
733
+ return tx
734
+ }
735
+
736
+ /**
737
+ * Stakes ZBTCVC tokens in ZO staking pools
738
+ */
739
+ public stake(
740
+ lpCoinObjects: string[],
741
+ amount: bigint,
742
+ pool: string,
743
+ tx?: Transaction,
744
+ ): Transaction {
745
+ if (!this.consts.zoStaking) {
746
+ throw new Error('ZO staking configuration not found')
747
+ }
748
+
749
+ if (!tx) {
750
+ tx = new Transaction()
751
+ }
752
+
753
+ const coinObject = this.processCoins(tx, 'zbtcvc', lpCoinObjects)
754
+ const [depositObject] = tx.splitCoins(coinObject, [tx.pure.u64(amount)])
755
+
756
+ tx.moveCall({
757
+ target: `${this.consts.zoStaking.package}::pool::deposit`,
758
+ typeArguments: [
759
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
760
+ `${this.consts.coins.sui.module}`,
761
+ ],
762
+ arguments: [
763
+ tx.object(pool),
764
+ tx.object(SUI_CLOCK_OBJECT_ID),
765
+ depositObject,
766
+ ],
767
+ })
768
+ return tx
769
+ }
770
+
771
+ /**
772
+ * Stakes ZBTCVC tokens using coin object only (PTB)
773
+ */
774
+ public stakeCoinObject(
775
+ coinObject: any,
776
+ pool: string,
777
+ tx?: Transaction,
778
+ ): Transaction {
779
+ if (!this.consts.zoStaking) {
780
+ throw new Error('ZO staking configuration not found')
781
+ }
782
+
783
+ if (!tx) {
784
+ tx = new Transaction()
785
+ }
786
+
787
+ tx.moveCall({
788
+ target: `${this.consts.zoStaking.package}::pool::deposit`,
789
+ typeArguments: [
790
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
791
+ `${this.consts.coins.sui.module}`,
792
+ ],
793
+ arguments: [
794
+ tx.object(pool),
795
+ tx.object(SUI_CLOCK_OBJECT_ID),
796
+ coinObject,
797
+ ],
798
+ })
799
+ return tx
800
+ }
801
+
802
+ /**
803
+ * Unstakes ZBTCVC tokens from ZO staking pools
804
+ */
805
+ public unstake(
806
+ credentials: IZBTCVCCredential[],
807
+ amount: bigint,
808
+ pool: string,
809
+ tx?: Transaction,
810
+ ): Transaction {
811
+ if (!this.consts.zoStaking) {
812
+ throw new Error('ZO staking configuration not found')
813
+ }
814
+
815
+ let unstakeAmount = amount
816
+ if (!tx) {
817
+ tx = new Transaction()
818
+ }
819
+ for (const credential of credentials) {
820
+ const withdrawAmount = (() => {
821
+ const min = (a: bigint, b: bigint) => a < b ? a : b
822
+ return min(unstakeAmount, credential.amount)
823
+ })()
824
+ unstakeAmount -= withdrawAmount
825
+ tx.moveCall({
826
+ target: `${this.consts.zoStaking.package}::pool::withdraw`,
827
+ typeArguments: [
828
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
829
+ `${this.consts.coins.sui.module}`,
830
+ ],
831
+ arguments: [
832
+ tx.object(pool),
833
+ tx.object(SUI_CLOCK_OBJECT_ID),
834
+ tx.object(credential.id),
835
+ tx.pure.u64(withdrawAmount),
836
+ ],
837
+ })
838
+ if (credential.amount === BigInt(0)) {
839
+ tx.moveCall({
840
+ target: `${this.consts.zoStaking.package}::pool::clear_empty_credential`,
841
+ typeArguments: [
842
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
843
+ `${this.consts.coins.sui.module}`,
844
+ ],
845
+ arguments: [tx.object(credential.id)],
846
+ })
847
+ }
848
+ }
849
+ return tx
850
+ }
851
+
852
+ public async swap(
853
+ fromToken: string,
854
+ toToken: string,
855
+ fromAmount: bigint,
856
+ fromCoinObjects: string[],
857
+ minAmountOut?: number,
858
+ ): Promise<Transaction> {
859
+ const tx = await this.initOracleTxb(Object.keys(this.consts.zoCore.vaults))
860
+ const fromCoinObject = this.processCoins(tx, fromToken, fromCoinObjects)
861
+ const [fromDepositObject] = tx.splitCoins(fromCoinObject, [tx.pure.u64(fromAmount)])
862
+ const vaultsValuation = this.dataAPI.valuateVaults(tx)
863
+
864
+ tx.moveCall({
865
+ target: `${this.consts.zoCore.upgradedPackage}::market::swap`,
866
+ typeArguments: [
867
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
868
+ this.consts.coins[fromToken].module,
869
+ this.consts.coins[toToken].module,
870
+ ],
871
+ arguments: [
872
+ tx.object(this.consts.zoCore.market),
873
+ tx.object(this.consts.zoCore.rebaseFeeModel),
874
+ fromDepositObject,
875
+ tx.pure.u64(minAmountOut || 0),
876
+ vaultsValuation,
877
+ ],
878
+ })
879
+ return tx
880
+ }
881
+
882
+ /**
883
+ * Opens a new position in ZBTCVC
884
+ */
885
+ public async openPosition(
886
+ collateralToken: string,
887
+ indexToken: string,
888
+ size: bigint,
889
+ collateralAmount: bigint,
890
+ coinObjects: string[],
891
+ long: boolean,
892
+ reserveAmount: bigint,
893
+ indexPrice: number,
894
+ collateralPrice: number,
895
+ isLimitOrder?: boolean,
896
+ isIocOrder?: boolean,
897
+ pricesSlippage = 0.003,
898
+ collateralSlippage = 0.5,
899
+ relayerFee = BigInt(0.5),
900
+ referralAddress?: string,
901
+ sender?: string,
902
+ sponsoredTx?: boolean,
903
+ suiCoinObjectsForPythUpdate?: string[],
904
+ ): Promise<Transaction> {
905
+ let tx = new Transaction()
906
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
907
+ tx = await this.addReferral(referralAddress, tx)
908
+ }
909
+
910
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
911
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
912
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
913
+
914
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
915
+ if (isLimitOrder) {
916
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
917
+ }
918
+
919
+ // Handle oracle initialization and coin processing
920
+ let suiCoinObject
921
+ if (sponsoredTx) {
922
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
923
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
924
+ }
925
+ else {
926
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
927
+ }
928
+
929
+ // Process coin splitting
930
+ const [depositObject, feeObject] = this.processCoinSplitting(
931
+ tx,
932
+ collateralToken,
933
+ coinObjects,
934
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
935
+ sponsoredTx,
936
+ suiCoinObject,
937
+ )
938
+
939
+ tx.moveCall({
940
+ target: `${this.consts.zoCore.upgradedPackage}::market::open_position`,
941
+ typeArguments: [
942
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
943
+ this.consts.coins[collateralToken].module,
944
+ this.consts.coins[indexToken].module,
945
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
946
+ this.consts.coins[collateralToken].module,
947
+ ],
948
+ arguments: [
949
+ tx.object(SUI_CLOCK_OBJECT_ID),
950
+ tx.object(this.consts.zoCore.market),
951
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
952
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
953
+ tx.object(this.consts.zoCore.symbols[symbol].positionConfig),
954
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
955
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
956
+ depositObject,
957
+ feeObject,
958
+ tx.pure.u8(allowTrade),
959
+ tx.pure.u64(size),
960
+ tx.pure.u64(reserveAmount),
961
+ tx.pure.u256(adjustCollateralPrice),
962
+ tx.pure.u256(adjustPrice),
963
+ ],
964
+ })
965
+ return tx
966
+ }
967
+
968
+ /**
969
+ * Decreases an existing position in ZBTCVC
970
+ */
971
+ public async decreasePosition(
972
+ pcpId: string,
973
+ collateralToken: string,
974
+ indexToken: string,
975
+ amount: bigint,
976
+ long: boolean,
977
+ indexPrice: number,
978
+ collateralPrice: number,
979
+ isTriggerOrder = false,
980
+ isTakeProfitOrder = true,
981
+ isIocOrder = false,
982
+ pricesSlippage = 0.003,
983
+ collateralSlippage = 0.5,
984
+ relayerFee = BigInt(0.5),
985
+ coinObjects?: string[],
986
+ sponsoredTx?: boolean,
987
+ suiCoinObjectsForPythUpdate?: string[],
988
+ ): Promise<Transaction> {
989
+ if (!coinObjects) {
990
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
991
+ }
992
+ let tx = new Transaction()
993
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
994
+
995
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
996
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
997
+
998
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
999
+ if (isTriggerOrder) {
1000
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1001
+ }
1002
+ else {
1003
+ isTakeProfitOrder = true
1004
+ }
1005
+
1006
+ // Handle oracle initialization and coin processing
1007
+ let suiCoinObject
1008
+ if (sponsoredTx) {
1009
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1010
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1011
+ }
1012
+ else {
1013
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1014
+ }
1015
+
1016
+ // Process coin splitting
1017
+ const [feeObject] = this.processCoinSplitting(
1018
+ tx,
1019
+ collateralToken,
1020
+ coinObjects,
1021
+ [tx.pure.u64(relayerFee)],
1022
+ sponsoredTx,
1023
+ suiCoinObject,
1024
+ )
1025
+
1026
+ tx.moveCall({
1027
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position`,
1028
+ typeArguments: [
1029
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1030
+ this.consts.coins[collateralToken].module,
1031
+ this.consts.coins[indexToken].module,
1032
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1033
+ this.consts.coins[collateralToken].module,
1034
+ ],
1035
+ arguments: [
1036
+ tx.object(SUI_CLOCK_OBJECT_ID),
1037
+ tx.object(this.consts.zoCore.market),
1038
+ tx.object(pcpId),
1039
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
1040
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
1041
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1042
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1043
+ feeObject,
1044
+ tx.pure.u8(allowTrade),
1045
+ tx.pure.bool(isTakeProfitOrder),
1046
+ tx.pure.u64(amount),
1047
+ tx.pure.u256(adjustCollateralPrice),
1048
+ tx.pure.u256(adjustPrice),
1049
+ ],
1050
+ })
1051
+
1052
+ return tx
1053
+ }
1054
+
1055
+ public async decreaseMultiPositions(positions: Array<{
1056
+ pcpId: string
1057
+ collateralToken: string
1058
+ indexToken: string
1059
+ amount: bigint
1060
+ long: boolean
1061
+ indexPrice: number
1062
+ collateralPrice: number
1063
+ isTriggerOrder?: boolean
1064
+ isTakeProfitOrder?: boolean
1065
+ isIocOrder?: boolean
1066
+ pricesSlippage?: number
1067
+ collateralSlippage?: number
1068
+ relayerFee?: bigint
1069
+ coinObjects?: string[]
1070
+ }>, tx?: Transaction, sponsoredTx?: boolean, suiCoinObjectsForPythUpdate?: string[]): Promise<Transaction> {
1071
+ if (!tx) {
1072
+ tx = new Transaction()
1073
+ }
1074
+
1075
+ // Handle oracle initialization and coin processing
1076
+ let suiCoinObject
1077
+ if (sponsoredTx) {
1078
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1079
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx, true, suiCoinObject)
1080
+ }
1081
+ else {
1082
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx)
1083
+ }
1084
+
1085
+ for (const position of positions) {
1086
+ const {
1087
+ pcpId,
1088
+ collateralToken,
1089
+ coinObjects = [],
1090
+ indexToken,
1091
+ amount,
1092
+ long,
1093
+ indexPrice,
1094
+ collateralPrice,
1095
+ isTriggerOrder = false,
1096
+ isTakeProfitOrder = true,
1097
+ isIocOrder = false,
1098
+ pricesSlippage = 0.003,
1099
+ collateralSlippage = 0.5,
1100
+ relayerFee = BigInt(0.5),
1101
+ } = position
1102
+ let innerIsTakeProfitOrder = isTakeProfitOrder
1103
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1104
+
1105
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
1106
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
1107
+
1108
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1109
+ if (isTriggerOrder) {
1110
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1111
+ }
1112
+ else {
1113
+ innerIsTakeProfitOrder = true
1114
+ }
1115
+
1116
+ // Process coin splitting
1117
+ const [feeObject] = this.processCoinSplitting(
1118
+ tx,
1119
+ collateralToken,
1120
+ coinObjects,
1121
+ [tx.pure.u64(relayerFee)],
1122
+ sponsoredTx,
1123
+ suiCoinObject,
1124
+ )
1125
+
1126
+ tx.moveCall({
1127
+ target: `${this.consts.zoCore.upgradedPackage}::market::decrease_position`,
1128
+ typeArguments: [
1129
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1130
+ this.consts.coins[collateralToken].module,
1131
+ this.consts.coins[indexToken].module,
1132
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1133
+ this.consts.coins[collateralToken].module,
1134
+ ],
1135
+ arguments: [
1136
+ tx.object(SUI_CLOCK_OBJECT_ID),
1137
+ tx.object(this.consts.zoCore.market),
1138
+ tx.object(pcpId),
1139
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
1140
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
1141
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1142
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1143
+ feeObject,
1144
+ tx.pure.u8(allowTrade),
1145
+ tx.pure.bool(innerIsTakeProfitOrder),
1146
+ tx.pure.u64(amount),
1147
+ tx.pure.u256(adjustCollateralPrice),
1148
+ tx.pure.u256(adjustPrice),
1149
+ ],
1150
+ })
1151
+ }
1152
+ return tx
1153
+ }
1154
+
1155
+ /**
1156
+ * Pledges in position (ZBTCVC-specific functionality)
1157
+ */
1158
+ public async pledgeInPosition(
1159
+ pcpId: string,
1160
+ collateralToken: string,
1161
+ indexToken: string,
1162
+ amount: number,
1163
+ coinObjects: string[],
1164
+ long: boolean,
1165
+ sponsoredTx?: boolean,
1166
+ suiCoinObjectsForPythUpdate?: string[],
1167
+ ): Promise<Transaction> {
1168
+ let tx = new Transaction()
1169
+ // Handle oracle initialization and coin processing
1170
+ let suiCoinObject
1171
+ if (sponsoredTx) {
1172
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1173
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1174
+ }
1175
+ else {
1176
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1177
+ }
1178
+
1179
+ // Process coin splitting
1180
+ const [depositObject] = this.processCoinSplitting(
1181
+ tx,
1182
+ collateralToken,
1183
+ coinObjects,
1184
+ [tx.pure.u64(amount)],
1185
+ sponsoredTx,
1186
+ suiCoinObject,
1187
+ )
1188
+
1189
+ tx.moveCall({
1190
+ target: `${this.consts.zoCore.upgradedPackage}::market::pledge_in_position`,
1191
+ typeArguments: [
1192
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1193
+ this.consts.coins[collateralToken].module,
1194
+ this.consts.coins[indexToken].module,
1195
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1196
+ ],
1197
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(pcpId), depositObject],
1198
+ })
1199
+ return tx
1200
+ }
1201
+
1202
+ public async redeemFromPosition(
1203
+ pcpId: string,
1204
+ collateralToken: string,
1205
+ indexToken: string,
1206
+ amount: number,
1207
+ long: boolean,
1208
+ sponsoredTx?: boolean,
1209
+ suiCoinObjectsForPythUpdate?: string[],
1210
+ ): Promise<Transaction> {
1211
+ let tx = new Transaction()
1212
+ // Handle oracle initialization and coin processing
1213
+ let suiCoinObject
1214
+ if (sponsoredTx) {
1215
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1216
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1217
+ }
1218
+ else {
1219
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1220
+ }
1221
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1222
+
1223
+ tx.moveCall({
1224
+ target: `${this.consts.zoCore.upgradedPackage}::market::redeem_from_position`,
1225
+ typeArguments: [
1226
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1227
+ this.consts.coins[collateralToken].module,
1228
+ this.consts.coins[indexToken].module,
1229
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1230
+ ],
1231
+ arguments: [
1232
+ tx.object(SUI_CLOCK_OBJECT_ID),
1233
+ tx.object(this.consts.zoCore.market),
1234
+ tx.object(pcpId),
1235
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
1236
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
1237
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1238
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1239
+ tx.pure.u64(amount),
1240
+ ],
1241
+ })
1242
+
1243
+ return tx
1244
+ }
1245
+
1246
+ public cancelOrder(
1247
+ orderCapId: string,
1248
+ collateralToken: string,
1249
+ indexToken: string,
1250
+ long: boolean,
1251
+ type: string,
1252
+ isV11Order?: boolean,
1253
+ ): Transaction {
1254
+ const tx = new Transaction()
1255
+ let functionName = ''
1256
+ switch (type) {
1257
+ case 'OPEN_POSITION': {
1258
+ functionName = isV11Order ? 'clear_open_position_order' : 'clear_open_position_order'
1259
+ break
1260
+ }
1261
+ case 'DECREASE_POSITION': {
1262
+ functionName = isV11Order
1263
+ ? 'clear_decrease_position_order'
1264
+ : 'clear_decrease_position_order'
1265
+ break
1266
+ }
1267
+ default: {
1268
+ throw new Error('invalid order type')
1269
+ }
1270
+ }
1271
+ tx.moveCall({
1272
+ target: `${this.consts.zoCore.upgradedPackage}::market::${functionName}`,
1273
+ typeArguments: [
1274
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1275
+ this.consts.coins[collateralToken].module,
1276
+ this.consts.coins[indexToken].module,
1277
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1278
+ this.consts.coins[collateralToken].module,
1279
+ ],
1280
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(orderCapId)],
1281
+ })
1282
+ return tx
1283
+ }
1284
+
1285
+ public cancelMultiOrders(
1286
+ orders: Array<{
1287
+ orderCapId: string
1288
+ collateralToken: string
1289
+ indexToken: string
1290
+ long: boolean
1291
+ type: string
1292
+ isV11Order?: boolean
1293
+ }>,
1294
+ tx?: Transaction,
1295
+ ): Transaction {
1296
+ if (!tx) {
1297
+ tx = new Transaction()
1298
+ }
1299
+
1300
+ for (const order of orders) {
1301
+ const { orderCapId, collateralToken, indexToken, long, type, isV11Order } = order
1302
+ let functionName = ''
1303
+ switch (type) {
1304
+ case 'OPEN_POSITION': {
1305
+ functionName = isV11Order ? 'clear_open_position_order' : 'clear_open_position_order'
1306
+ break
1307
+ }
1308
+ case 'DECREASE_POSITION': {
1309
+ functionName = isV11Order
1310
+ ? 'clear_decrease_position_order'
1311
+ : 'clear_decrease_position_order'
1312
+ break
1313
+ }
1314
+ default: {
1315
+ throw new Error('invalid order type')
1316
+ }
1317
+ }
1318
+
1319
+ tx.moveCall({
1320
+ target: `${this.consts.zoCore.upgradedPackage}::market::${functionName}`,
1321
+ typeArguments: [
1322
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1323
+ this.consts.coins[collateralToken].module,
1324
+ this.consts.coins[indexToken].module,
1325
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1326
+ this.consts.coins[collateralToken].module,
1327
+ ],
1328
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(orderCapId)],
1329
+ })
1330
+ }
1331
+ return tx
1332
+ }
1333
+
1334
+ public addReferral(
1335
+ referralAddress: string,
1336
+ tx?: Transaction,
1337
+ ): Transaction {
1338
+ if (!tx) {
1339
+ tx = new Transaction()
1340
+ }
1341
+ tx.moveCall({
1342
+ target: `${this.consts.zoCore.upgradedPackage}::market::add_new_referral`,
1343
+ typeArguments: [`${this.consts.zoCore.package}::zbtcvc::ZBTCVC`],
1344
+ arguments: [tx.object(this.consts.zoCore.market), tx.object(referralAddress)],
1345
+ })
1346
+
1347
+ return tx
1348
+ }
1349
+
1350
+ public async adminUpdatePriceFeed(
1351
+ collateralToken: string,
1352
+ indexToken: string,
1353
+ ): Promise<Transaction> {
1354
+ const tx = await this.initOracleTxb([collateralToken, indexToken])
1355
+ return tx
1356
+ }
1357
+
1358
+ public adminSettlePosition(
1359
+ positionId: string,
1360
+ owner: string,
1361
+ collateralToken: string,
1362
+ indexToken: string,
1363
+ long: boolean,
1364
+ ): Transaction {
1365
+ const tx = new Transaction()
1366
+
1367
+ tx.moveCall({
1368
+ target: `${this.consts.zoCore.upgradedPackage}::market::force_settle_position`,
1369
+ typeArguments: [
1370
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1371
+ this.consts.coins[collateralToken].module,
1372
+ this.consts.coins[indexToken].module,
1373
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1374
+ ],
1375
+ arguments: [
1376
+ tx.object(this.consts.zoCore.adminCap),
1377
+ tx.object(SUI_CLOCK_OBJECT_ID),
1378
+ tx.object(this.consts.zoCore.market),
1379
+ tx.object(owner),
1380
+ tx.object(positionId),
1381
+ ],
1382
+ })
1383
+
1384
+ this.adminClearClosedPosition(positionId, owner, collateralToken, indexToken, long, tx)
1385
+
1386
+ return tx
1387
+ }
1388
+
1389
+ public adminDecreasePosition(
1390
+ positionId: string,
1391
+ owner: string,
1392
+ collateralToken: string,
1393
+ indexToken: string,
1394
+ positionAmount: number,
1395
+ amount: bigint,
1396
+ long: boolean,
1397
+ ): Transaction {
1398
+ const tx = new Transaction()
1399
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1400
+
1401
+ tx.moveCall({
1402
+ target: `${this.consts.zoCore.upgradedPackage}::market::force_close_position`,
1403
+ typeArguments: [
1404
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1405
+ this.consts.coins[collateralToken].module,
1406
+ this.consts.coins[indexToken].module,
1407
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1408
+ ],
1409
+ arguments: [
1410
+ tx.object(this.consts.zoCore.adminCap),
1411
+ tx.object(SUI_CLOCK_OBJECT_ID),
1412
+ tx.object(this.consts.zoCore.market),
1413
+ tx.object(this.consts.zoCore.vaults[collateralToken].reservingFeeModel),
1414
+ tx.object(this.consts.zoCore.symbols[symbol].fundingFeeModel),
1415
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1416
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1417
+ tx.object(owner),
1418
+ tx.object(positionId),
1419
+ ],
1420
+ })
1421
+
1422
+ if (amount === BigInt(positionAmount)) {
1423
+ this.adminClearClosedPosition(positionId, owner, collateralToken, indexToken, long, tx)
1424
+ }
1425
+
1426
+ return tx
1427
+ }
1428
+
1429
+ public adminClearClosedPosition(
1430
+ positionId: string,
1431
+ owner: string,
1432
+ collateralToken: string,
1433
+ indexToken: string,
1434
+ long: boolean,
1435
+ tx: Transaction,
1436
+ ): void {
1437
+ tx.moveCall({
1438
+ target: `${this.consts.zoCore.upgradedPackage}::market::force_clear_closed_position`,
1439
+ typeArguments: [
1440
+ `${this.consts.zoCore.package}::zbtcvc::ZBTCVC`,
1441
+ this.consts.coins[collateralToken].module,
1442
+ this.consts.coins[indexToken].module,
1443
+ `${this.consts.zoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1444
+ ],
1445
+ arguments: [
1446
+ tx.object(this.consts.zoCore.adminCap),
1447
+ tx.object(this.consts.zoCore.market),
1448
+ tx.object(positionId),
1449
+ tx.object(owner),
1450
+ ],
1451
+ })
1452
+ }
1453
+ }