@zofai/zo-sdk 0.1.92

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 (275) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.gitattributes +4 -0
  3. package/.prettierrc.js +9 -0
  4. package/README.md +28 -0
  5. package/dist/abstract/BaseAPI.cjs +206 -0
  6. package/dist/abstract/BaseAPI.cjs.map +1 -0
  7. package/dist/abstract/BaseAPI.d.cts +172 -0
  8. package/dist/abstract/BaseAPI.d.cts.map +1 -0
  9. package/dist/abstract/BaseAPI.d.mts +172 -0
  10. package/dist/abstract/BaseAPI.d.mts.map +1 -0
  11. package/dist/abstract/BaseAPI.mjs +202 -0
  12. package/dist/abstract/BaseAPI.mjs.map +1 -0
  13. package/dist/abstract/BaseDataAPI.cjs +140 -0
  14. package/dist/abstract/BaseDataAPI.cjs.map +1 -0
  15. package/dist/abstract/BaseDataAPI.d.cts +89 -0
  16. package/dist/abstract/BaseDataAPI.d.cts.map +1 -0
  17. package/dist/abstract/BaseDataAPI.d.mts +89 -0
  18. package/dist/abstract/BaseDataAPI.d.mts.map +1 -0
  19. package/dist/abstract/BaseDataAPI.mjs +136 -0
  20. package/dist/abstract/BaseDataAPI.mjs.map +1 -0
  21. package/dist/abstract/index.cjs +12 -0
  22. package/dist/abstract/index.cjs.map +1 -0
  23. package/dist/abstract/index.d.cts +7 -0
  24. package/dist/abstract/index.d.cts.map +1 -0
  25. package/dist/abstract/index.d.mts +7 -0
  26. package/dist/abstract/index.d.mts.map +1 -0
  27. package/dist/abstract/index.mjs +7 -0
  28. package/dist/abstract/index.mjs.map +1 -0
  29. package/dist/api.cjs +779 -0
  30. package/dist/api.cjs.map +1 -0
  31. package/dist/api.d.cts +75 -0
  32. package/dist/api.d.cts.map +1 -0
  33. package/dist/api.d.mts +75 -0
  34. package/dist/api.d.mts.map +1 -0
  35. package/dist/api.mjs +775 -0
  36. package/dist/api.mjs.map +1 -0
  37. package/dist/bcs.cjs +42 -0
  38. package/dist/bcs.cjs.map +1 -0
  39. package/dist/bcs.d.cts +91 -0
  40. package/dist/bcs.d.cts.map +1 -0
  41. package/dist/bcs.d.mts +91 -0
  42. package/dist/bcs.d.mts.map +1 -0
  43. package/dist/bcs.mjs +39 -0
  44. package/dist/bcs.mjs.map +1 -0
  45. package/dist/consts/deployments-shared-mainnet.json +50 -0
  46. package/dist/consts/deployments-shared-testnet.json +45 -0
  47. package/dist/consts/deployments-slp-mainnet.json +600 -0
  48. package/dist/consts/deployments-slp-testnet.json +87 -0
  49. package/dist/consts/deployments-usdz-mainnet.json +494 -0
  50. package/dist/consts/deployments-usdz-testnet.json +98 -0
  51. package/dist/consts/deployments-zbtcvc-mainnet.json +180 -0
  52. package/dist/consts/deployments-zlp-mainnet.json +791 -0
  53. package/dist/consts/deployments-zlp-testnet.json +76 -0
  54. package/dist/consts/index.cjs +200 -0
  55. package/dist/consts/index.cjs.map +1 -0
  56. package/dist/consts/index.d.cts +157 -0
  57. package/dist/consts/index.d.cts.map +1 -0
  58. package/dist/consts/index.d.mts +157 -0
  59. package/dist/consts/index.d.mts.map +1 -0
  60. package/dist/consts/index.mjs +189 -0
  61. package/dist/consts/index.mjs.map +1 -0
  62. package/dist/consts/price_id_to_object_id.mainnet.json +56 -0
  63. package/dist/consts/price_id_to_object_id.testnet.json +17 -0
  64. package/dist/data.cjs +919 -0
  65. package/dist/data.cjs.map +1 -0
  66. package/dist/data.d.cts +235 -0
  67. package/dist/data.d.cts.map +1 -0
  68. package/dist/data.d.mts +235 -0
  69. package/dist/data.d.mts.map +1 -0
  70. package/dist/data.mjs +915 -0
  71. package/dist/data.mjs.map +1 -0
  72. package/dist/factory/SDKFactory.cjs +228 -0
  73. package/dist/factory/SDKFactory.cjs.map +1 -0
  74. package/dist/factory/SDKFactory.d.cts +84 -0
  75. package/dist/factory/SDKFactory.d.cts.map +1 -0
  76. package/dist/factory/SDKFactory.d.mts +84 -0
  77. package/dist/factory/SDKFactory.d.mts.map +1 -0
  78. package/dist/factory/SDKFactory.mjs +222 -0
  79. package/dist/factory/SDKFactory.mjs.map +1 -0
  80. package/dist/implementations/SLPAPI.cjs +1794 -0
  81. package/dist/implementations/SLPAPI.cjs.map +1 -0
  82. package/dist/implementations/SLPAPI.d.cts +183 -0
  83. package/dist/implementations/SLPAPI.d.cts.map +1 -0
  84. package/dist/implementations/SLPAPI.d.mts +183 -0
  85. package/dist/implementations/SLPAPI.d.mts.map +1 -0
  86. package/dist/implementations/SLPAPI.mjs +1790 -0
  87. package/dist/implementations/SLPAPI.mjs.map +1 -0
  88. package/dist/implementations/SLPDataAPI.cjs +1384 -0
  89. package/dist/implementations/SLPDataAPI.cjs.map +1 -0
  90. package/dist/implementations/SLPDataAPI.d.cts +158 -0
  91. package/dist/implementations/SLPDataAPI.d.cts.map +1 -0
  92. package/dist/implementations/SLPDataAPI.d.mts +158 -0
  93. package/dist/implementations/SLPDataAPI.d.mts.map +1 -0
  94. package/dist/implementations/SLPDataAPI.mjs +1380 -0
  95. package/dist/implementations/SLPDataAPI.mjs.map +1 -0
  96. package/dist/implementations/USDZAPI.cjs +1676 -0
  97. package/dist/implementations/USDZAPI.cjs.map +1 -0
  98. package/dist/implementations/USDZAPI.d.cts +180 -0
  99. package/dist/implementations/USDZAPI.d.cts.map +1 -0
  100. package/dist/implementations/USDZAPI.d.mts +180 -0
  101. package/dist/implementations/USDZAPI.d.mts.map +1 -0
  102. package/dist/implementations/USDZAPI.mjs +1672 -0
  103. package/dist/implementations/USDZAPI.mjs.map +1 -0
  104. package/dist/implementations/USDZDataAPI.cjs +1209 -0
  105. package/dist/implementations/USDZDataAPI.cjs.map +1 -0
  106. package/dist/implementations/USDZDataAPI.d.cts +191 -0
  107. package/dist/implementations/USDZDataAPI.d.cts.map +1 -0
  108. package/dist/implementations/USDZDataAPI.d.mts +191 -0
  109. package/dist/implementations/USDZDataAPI.d.mts.map +1 -0
  110. package/dist/implementations/USDZDataAPI.mjs +1205 -0
  111. package/dist/implementations/USDZDataAPI.mjs.map +1 -0
  112. package/dist/implementations/ZBTCVCAPI.cjs +906 -0
  113. package/dist/implementations/ZBTCVCAPI.cjs.map +1 -0
  114. package/dist/implementations/ZBTCVCAPI.d.cts +107 -0
  115. package/dist/implementations/ZBTCVCAPI.d.cts.map +1 -0
  116. package/dist/implementations/ZBTCVCAPI.d.mts +107 -0
  117. package/dist/implementations/ZBTCVCAPI.d.mts.map +1 -0
  118. package/dist/implementations/ZBTCVCAPI.mjs +902 -0
  119. package/dist/implementations/ZBTCVCAPI.mjs.map +1 -0
  120. package/dist/implementations/ZBTCVCDataAPI.cjs +829 -0
  121. package/dist/implementations/ZBTCVCDataAPI.cjs.map +1 -0
  122. package/dist/implementations/ZBTCVCDataAPI.d.cts +94 -0
  123. package/dist/implementations/ZBTCVCDataAPI.d.cts.map +1 -0
  124. package/dist/implementations/ZBTCVCDataAPI.d.mts +94 -0
  125. package/dist/implementations/ZBTCVCDataAPI.d.mts.map +1 -0
  126. package/dist/implementations/ZBTCVCDataAPI.mjs +825 -0
  127. package/dist/implementations/ZBTCVCDataAPI.mjs.map +1 -0
  128. package/dist/implementations/ZLPAPI.cjs +1948 -0
  129. package/dist/implementations/ZLPAPI.cjs.map +1 -0
  130. package/dist/implementations/ZLPAPI.d.cts +192 -0
  131. package/dist/implementations/ZLPAPI.d.cts.map +1 -0
  132. package/dist/implementations/ZLPAPI.d.mts +192 -0
  133. package/dist/implementations/ZLPAPI.d.mts.map +1 -0
  134. package/dist/implementations/ZLPAPI.mjs +1944 -0
  135. package/dist/implementations/ZLPAPI.mjs.map +1 -0
  136. package/dist/implementations/ZLPDataAPI.cjs +1267 -0
  137. package/dist/implementations/ZLPDataAPI.cjs.map +1 -0
  138. package/dist/implementations/ZLPDataAPI.d.cts +193 -0
  139. package/dist/implementations/ZLPDataAPI.d.cts.map +1 -0
  140. package/dist/implementations/ZLPDataAPI.d.mts +193 -0
  141. package/dist/implementations/ZLPDataAPI.d.mts.map +1 -0
  142. package/dist/implementations/ZLPDataAPI.mjs +1263 -0
  143. package/dist/implementations/ZLPDataAPI.mjs.map +1 -0
  144. package/dist/implementations/index.cjs +26 -0
  145. package/dist/implementations/index.cjs.map +1 -0
  146. package/dist/implementations/index.d.cts +13 -0
  147. package/dist/implementations/index.d.cts.map +1 -0
  148. package/dist/implementations/index.d.mts +13 -0
  149. package/dist/implementations/index.d.mts.map +1 -0
  150. package/dist/implementations/index.mjs +15 -0
  151. package/dist/implementations/index.mjs.map +1 -0
  152. package/dist/index.cjs +69 -0
  153. package/dist/index.cjs.map +1 -0
  154. package/dist/index.d.cts +51 -0
  155. package/dist/index.d.cts.map +1 -0
  156. package/dist/index.d.mts +51 -0
  157. package/dist/index.d.mts.map +1 -0
  158. package/dist/index.mjs +51 -0
  159. package/dist/index.mjs.map +1 -0
  160. package/dist/interfaces/base.cjs +7 -0
  161. package/dist/interfaces/base.cjs.map +1 -0
  162. package/dist/interfaces/base.d.cts +346 -0
  163. package/dist/interfaces/base.d.cts.map +1 -0
  164. package/dist/interfaces/base.d.mts +346 -0
  165. package/dist/interfaces/base.d.mts.map +1 -0
  166. package/dist/interfaces/base.mjs +6 -0
  167. package/dist/interfaces/base.mjs.map +1 -0
  168. package/dist/interfaces/index.cjs +31 -0
  169. package/dist/interfaces/index.cjs.map +1 -0
  170. package/dist/interfaces/index.d.cts +15 -0
  171. package/dist/interfaces/index.d.cts.map +1 -0
  172. package/dist/interfaces/index.d.mts +15 -0
  173. package/dist/interfaces/index.d.mts.map +1 -0
  174. package/dist/interfaces/index.mjs +15 -0
  175. package/dist/interfaces/index.mjs.map +1 -0
  176. package/dist/interfaces/slp.cjs +7 -0
  177. package/dist/interfaces/slp.cjs.map +1 -0
  178. package/dist/interfaces/slp.d.cts +179 -0
  179. package/dist/interfaces/slp.d.cts.map +1 -0
  180. package/dist/interfaces/slp.d.mts +179 -0
  181. package/dist/interfaces/slp.d.mts.map +1 -0
  182. package/dist/interfaces/slp.mjs +6 -0
  183. package/dist/interfaces/slp.mjs.map +1 -0
  184. package/dist/interfaces/usdz.cjs +7 -0
  185. package/dist/interfaces/usdz.cjs.map +1 -0
  186. package/dist/interfaces/usdz.d.cts +104 -0
  187. package/dist/interfaces/usdz.d.cts.map +1 -0
  188. package/dist/interfaces/usdz.d.mts +104 -0
  189. package/dist/interfaces/usdz.d.mts.map +1 -0
  190. package/dist/interfaces/usdz.mjs +6 -0
  191. package/dist/interfaces/usdz.mjs.map +1 -0
  192. package/dist/interfaces/zbtcvc.cjs +7 -0
  193. package/dist/interfaces/zbtcvc.cjs.map +1 -0
  194. package/dist/interfaces/zbtcvc.d.cts +64 -0
  195. package/dist/interfaces/zbtcvc.d.cts.map +1 -0
  196. package/dist/interfaces/zbtcvc.d.mts +64 -0
  197. package/dist/interfaces/zbtcvc.d.mts.map +1 -0
  198. package/dist/interfaces/zbtcvc.mjs +6 -0
  199. package/dist/interfaces/zbtcvc.mjs.map +1 -0
  200. package/dist/interfaces/zlp.cjs +7 -0
  201. package/dist/interfaces/zlp.cjs.map +1 -0
  202. package/dist/interfaces/zlp.d.cts +114 -0
  203. package/dist/interfaces/zlp.d.cts.map +1 -0
  204. package/dist/interfaces/zlp.d.mts +114 -0
  205. package/dist/interfaces/zlp.d.mts.map +1 -0
  206. package/dist/interfaces/zlp.mjs +6 -0
  207. package/dist/interfaces/zlp.mjs.map +1 -0
  208. package/dist/oracle.cjs +118 -0
  209. package/dist/oracle.cjs.map +1 -0
  210. package/dist/oracle.d.cts +25 -0
  211. package/dist/oracle.d.cts.map +1 -0
  212. package/dist/oracle.d.mts +25 -0
  213. package/dist/oracle.d.mts.map +1 -0
  214. package/dist/oracle.mjs +114 -0
  215. package/dist/oracle.mjs.map +1 -0
  216. package/dist/utils.cjs +129 -0
  217. package/dist/utils.cjs.map +1 -0
  218. package/dist/utils.d.cts +44 -0
  219. package/dist/utils.d.cts.map +1 -0
  220. package/dist/utils.d.mts +44 -0
  221. package/dist/utils.d.mts.map +1 -0
  222. package/dist/utils.mjs +115 -0
  223. package/dist/utils.mjs.map +1 -0
  224. package/docs/SUMMARY.md +10 -0
  225. package/docs/api-reference.md +32 -0
  226. package/docs/architecture.md +14 -0
  227. package/docs/common-operations.md +52 -0
  228. package/docs/error-handling.md +17 -0
  229. package/docs/getting-started.md +60 -0
  230. package/docs/introduction.md +15 -0
  231. package/docs/lp-specific-features.md +96 -0
  232. package/docs/type-safety.md +29 -0
  233. package/eslint.config.mjs +18 -0
  234. package/package.json +42 -0
  235. package/src/abstract/BaseAPI.ts +575 -0
  236. package/src/abstract/BaseDataAPI.ts +207 -0
  237. package/src/abstract/index.ts +7 -0
  238. package/src/api.ts +1100 -0
  239. package/src/bcs.ts +45 -0
  240. package/src/consts/deployments-shared-mainnet.json +50 -0
  241. package/src/consts/deployments-shared-testnet.json +45 -0
  242. package/src/consts/deployments-slp-mainnet.json +600 -0
  243. package/src/consts/deployments-slp-testnet.json +87 -0
  244. package/src/consts/deployments-usdz-mainnet.json +494 -0
  245. package/src/consts/deployments-usdz-testnet.json +98 -0
  246. package/src/consts/deployments-zbtcvc-mainnet.json +180 -0
  247. package/src/consts/deployments-zlp-mainnet.json +791 -0
  248. package/src/consts/deployments-zlp-testnet.json +76 -0
  249. package/src/consts/index.ts +345 -0
  250. package/src/consts/price_id_to_object_id.mainnet.json +56 -0
  251. package/src/consts/price_id_to_object_id.testnet.json +17 -0
  252. package/src/data.ts +1279 -0
  253. package/src/factory/SDKFactory.ts +340 -0
  254. package/src/implementations/SLPAPI.ts +2722 -0
  255. package/src/implementations/SLPDataAPI.ts +1839 -0
  256. package/src/implementations/USDZAPI.ts +2488 -0
  257. package/src/implementations/USDZDataAPI.ts +1548 -0
  258. package/src/implementations/ZBTCVCAPI.ts +1337 -0
  259. package/src/implementations/ZBTCVCDataAPI.ts +993 -0
  260. package/src/implementations/ZLPAPI.ts +2888 -0
  261. package/src/implementations/ZLPDataAPI.ts +1603 -0
  262. package/src/implementations/index.ts +16 -0
  263. package/src/index.ts +58 -0
  264. package/src/interfaces/base.ts +838 -0
  265. package/src/interfaces/index.ts +50 -0
  266. package/src/interfaces/slp.ts +268 -0
  267. package/src/interfaces/usdz.ts +181 -0
  268. package/src/interfaces/zbtcvc.ts +116 -0
  269. package/src/interfaces/zlp.ts +244 -0
  270. package/src/oracle.ts +153 -0
  271. package/src/utils.ts +168 -0
  272. package/tests/api.test.ts +219 -0
  273. package/tests/data.test.ts +156 -0
  274. package/tests/oracle.test.ts +33 -0
  275. package/tsconfig.json +22 -0
@@ -0,0 +1,2722 @@
1
+ /**
2
+ * SLP API implementation
3
+ * Implements SLP-specific trading and transaction methods for Sudo SDK
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 type { TransactionObjectArgument } from '@mysten/sui/transactions'
10
+ import { Transaction } from '@mysten/sui/transactions'
11
+ import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils'
12
+
13
+ import { BaseAPI } from '../abstract'
14
+ import type { Network } from '../consts'
15
+ import { ALLOW_TRADE_CAN_TRADE, ALLOW_TRADE_MUST_TRADE, ALLOW_TRADE_NO_TRADE, LPToken } from '../consts'
16
+ import type {
17
+ IBasePositionInfo,
18
+ ISLPAPI,
19
+ ISLPCredential,
20
+ } from '../interfaces'
21
+ import { joinSymbol } from '../utils'
22
+ import { SLPDataAPI } from './SLPDataAPI'
23
+
24
+ export class SLPAPI extends BaseAPI implements ISLPAPI {
25
+ public dataAPI: SLPDataAPI
26
+
27
+ constructor(
28
+ network: Network,
29
+ provider: SuiClient,
30
+ apiEndpoint: string,
31
+ connectionURL: string,
32
+ ) {
33
+ super(network, provider, apiEndpoint, connectionURL, LPToken.SLP)
34
+ this.dataAPI = new SLPDataAPI(network, provider, apiEndpoint, connectionURL)
35
+ }
36
+
37
+ public calcPositionReserveFeeAmount(_position: IBasePositionInfo): Promise<number> {
38
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
39
+ }
40
+
41
+ public calcPositionFundingFeeValue(_position: IBasePositionInfo): Promise<number> {
42
+ throw new Error(`Method not implemented in ${this.constructor.name}.`)
43
+ }
44
+
45
+ /**
46
+ * Deposits collateral into SLP vault using Sudo SDK approach
47
+ */
48
+ public async deposit(
49
+ coin: string,
50
+ coinObjects: string[],
51
+ amount: number,
52
+ minAmountOut = 0,
53
+ referralAddress?: string,
54
+ sender?: string,
55
+ sponsoredTx?: boolean,
56
+ suiCoinObjectsForPythUpdate?: string[],
57
+ ): Promise<Transaction> {
58
+ let tx = new Transaction()
59
+
60
+ // Add referral if needed
61
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
62
+ tx = await this.addReferral(referralAddress, tx)
63
+ }
64
+
65
+ // Initialize oracle transaction
66
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
67
+
68
+ // Handle sponsored transaction case
69
+ if (sponsoredTx) {
70
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
71
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
72
+
73
+ // Process deposit coins
74
+ const depositObject = coin === 'sui'
75
+ ? tx.splitCoins(suiCoinObject, [tx.pure.u64(amount)])[0]
76
+ : tx.splitCoins(this.processCoins(tx, coin, coinObjects, true), [tx.pure.u64(amount)])[0]
77
+
78
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
79
+
80
+ tx.moveCall({
81
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit`,
82
+ typeArguments: [
83
+ `${this.consts.sudoCore.package}::slp::SLP`,
84
+ this.consts.coins[coin].module,
85
+ ],
86
+ arguments: [
87
+ tx.object(this.consts.sudoCore.market),
88
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
89
+ depositObject,
90
+ tx.pure.u64(minAmountOut),
91
+ vaultsValuation,
92
+ symbolsValuation,
93
+ ],
94
+ })
95
+ return tx
96
+ }
97
+
98
+ // Handle non-sponsored transaction case
99
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
100
+ const depositObject = tx.splitCoins(
101
+ this.processCoins(tx, coin, coinObjects, false),
102
+ [tx.pure.u64(amount)],
103
+ )[0]
104
+
105
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
106
+
107
+ tx.moveCall({
108
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit`,
109
+ typeArguments: [
110
+ `${this.consts.sudoCore.package}::slp::SLP`,
111
+ this.consts.coins[coin].module,
112
+ ],
113
+ arguments: [
114
+ tx.object(this.consts.sudoCore.market),
115
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
116
+ depositObject,
117
+ tx.pure.u64(minAmountOut),
118
+ vaultsValuation,
119
+ symbolsValuation,
120
+ ],
121
+ })
122
+ return tx
123
+ }
124
+
125
+ /**
126
+ * Deposits collateral into SLP vault and returns a coin
127
+ */
128
+ public async depositPtb(
129
+ coin: string,
130
+ coinObjects: string[],
131
+ amount: number,
132
+ minAmountOut = 0,
133
+ referralAddress?: string,
134
+ sender?: string,
135
+ tx?: Transaction,
136
+ sponsoredTx?: boolean,
137
+ suiCoinObjectsForPythUpdate?: string[],
138
+ ): Promise<TransactionObjectArgument> {
139
+ if (!tx) {
140
+ tx = new Transaction()
141
+ }
142
+
143
+ // Add referral if needed
144
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
145
+ tx = await this.addReferral(referralAddress, tx)
146
+ }
147
+
148
+ // Initialize oracle transaction
149
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
150
+
151
+ // Handle sponsored transaction case
152
+ if (sponsoredTx) {
153
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
154
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
155
+
156
+ // Process deposit coins
157
+ const depositObject = coin === 'sui'
158
+ ? tx.splitCoins(suiCoinObject, [tx.pure.u64(amount)])[0]
159
+ : tx.splitCoins(this.processCoins(tx, coin, coinObjects, true), [tx.pure.u64(amount)])[0]
160
+
161
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
162
+
163
+ const [mintedCoin] = tx.moveCall({
164
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit_ptb`,
165
+ typeArguments: [`${this.consts.sudoCore.package}::slp::SLP`, this.consts.coins[coin].module],
166
+ arguments: [
167
+ tx.object(this.consts.sudoCore.market),
168
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
169
+ depositObject,
170
+ tx.pure.u64(minAmountOut),
171
+ vaultsValuation,
172
+ symbolsValuation,
173
+ ],
174
+ })
175
+ return mintedCoin
176
+ }
177
+
178
+ // Handle non-sponsored transaction case
179
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
180
+ const depositObject = tx.splitCoins(
181
+ this.processCoins(tx, coin, coinObjects, false),
182
+ [tx.pure.u64(amount)],
183
+ )[0]
184
+
185
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
186
+
187
+ const [mintedCoin] = tx.moveCall({
188
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit_ptb`,
189
+ typeArguments: [
190
+ `${this.consts.sudoCore.package}::slp::SLP`,
191
+ this.consts.coins[coin].module,
192
+ ],
193
+ arguments: [
194
+ tx.object(this.consts.sudoCore.market),
195
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
196
+ depositObject,
197
+ tx.pure.u64(minAmountOut),
198
+ vaultsValuation,
199
+ symbolsValuation,
200
+ ],
201
+ })
202
+
203
+ return mintedCoin
204
+ }
205
+
206
+ /**
207
+ * Deposits collateral pool with PTB deposit object
208
+ */
209
+ public async depositWithPtb(
210
+ coin: string,
211
+ depositObject: TransactionObjectArgument,
212
+ minAmountOut = 0,
213
+ referralAddress?: string,
214
+ sender?: string,
215
+ tx?: Transaction,
216
+ sponsoredTx?: boolean,
217
+ suiCoinObjectsForPythUpdate?: string[],
218
+ ): Promise<Transaction> {
219
+ if (!tx) {
220
+ tx = new Transaction()
221
+ }
222
+
223
+ // Add referral if needed
224
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
225
+ tx = await this.addReferral(referralAddress, tx)
226
+ }
227
+
228
+ // Initialize oracle transaction
229
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
230
+
231
+ // Handle sponsored transaction case
232
+ if (sponsoredTx) {
233
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
234
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
235
+
236
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
237
+
238
+ tx.moveCall({
239
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit`,
240
+ typeArguments: [
241
+ `${this.consts.sudoCore.package}::slp::SLP`,
242
+ this.consts.coins[coin].module,
243
+ ],
244
+ arguments: [
245
+ tx.object(this.consts.sudoCore.market),
246
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
247
+ depositObject,
248
+ tx.pure.u64(minAmountOut),
249
+ vaultsValuation,
250
+ symbolsValuation,
251
+ ],
252
+ })
253
+ return tx
254
+ }
255
+
256
+ // Handle non-sponsored transaction case
257
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
258
+
259
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
260
+
261
+ tx.moveCall({
262
+ target: `${this.consts.sudoCore.upgradedPackage}::market::deposit`,
263
+ typeArguments: [
264
+ `${this.consts.sudoCore.package}::slp::SLP`,
265
+ this.consts.coins[coin].module,
266
+ ],
267
+ arguments: [
268
+ tx.object(this.consts.sudoCore.market),
269
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
270
+ depositObject,
271
+ tx.pure.u64(minAmountOut),
272
+ vaultsValuation,
273
+ symbolsValuation,
274
+ ],
275
+ })
276
+ return tx
277
+ }
278
+
279
+ /**
280
+ * Withdraws collateral from SLP vault using Sudo SDK approach
281
+ */
282
+ public async withdraw(
283
+ coin: string,
284
+ lpCoinObjects: string[],
285
+ amount: number,
286
+ minAmountOut = 0,
287
+ sponsoredTx?: boolean,
288
+ suiCoinObjectsForPythUpdate?: string[],
289
+ ): Promise<Transaction> {
290
+ let tx = new Transaction()
291
+
292
+ // Initialize oracle transaction
293
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
294
+
295
+ if (sponsoredTx) {
296
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
297
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
298
+ }
299
+ else {
300
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
301
+ }
302
+
303
+ const slpCoinObject = this.processCoins(tx, 'slp', lpCoinObjects, false)
304
+ const [withdrawObject] = tx.splitCoins(slpCoinObject, [tx.pure.u64(amount)])
305
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
306
+
307
+ tx.moveCall({
308
+ target: `${this.consts.sudoCore.upgradedPackage}::market::withdraw`,
309
+ typeArguments: [
310
+ `${this.consts.sudoCore.package}::slp::SLP`,
311
+ this.consts.coins[coin].module,
312
+ ],
313
+ arguments: [
314
+ tx.object(this.consts.sudoCore.market),
315
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
316
+ withdrawObject,
317
+ tx.pure.u64(minAmountOut),
318
+ vaultsValuation,
319
+ symbolsValuation,
320
+ ],
321
+ })
322
+ return tx
323
+ }
324
+
325
+ /**
326
+ * Withdraws LP coin object from SLP Vault
327
+ */
328
+ public async withdrawLpCoinObject(
329
+ coin: string,
330
+ lpCoinObject: TransactionObjectArgument,
331
+ minAmountOut = 0,
332
+ tx?: Transaction,
333
+ ): Promise<Transaction> {
334
+ if (!tx) {
335
+ tx = new Transaction()
336
+ }
337
+
338
+ // Initialize oracle transaction
339
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
340
+
341
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
342
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
343
+
344
+ tx.moveCall({
345
+ target: `${this.consts.sudoCore.upgradedPackage}::market::withdraw`,
346
+ typeArguments: [
347
+ `${this.consts.sudoCore.package}::slp::SLP`,
348
+ this.consts.coins[coin].module,
349
+ ],
350
+ arguments: [
351
+ tx.object(this.consts.sudoCore.market),
352
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
353
+ lpCoinObject,
354
+ tx.pure.u64(minAmountOut),
355
+ vaultsValuation,
356
+ symbolsValuation,
357
+ ],
358
+ })
359
+ return tx
360
+ }
361
+
362
+ public async withdrawPtb(
363
+ coin: string,
364
+ lpCoinObjects: string[],
365
+ amount: number,
366
+ minAmountOut = 0,
367
+ tx?: Transaction,
368
+ sponsoredTx?: boolean,
369
+ suiCoinObjectsForPythUpdate?: string[],
370
+ ): Promise<TransactionObjectArgument> {
371
+ if (!tx) {
372
+ tx = new Transaction()
373
+ }
374
+
375
+ // Initialize oracle transaction
376
+ const pythFeederKeys = Object.keys(this.consts.pythFeeder.feeder)
377
+
378
+ if (sponsoredTx) {
379
+ const suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
380
+ tx = await this.initOracleTxb(pythFeederKeys, tx, true, suiCoinObject)
381
+ }
382
+ else {
383
+ tx = await this.initOracleTxb(pythFeederKeys, tx)
384
+ }
385
+
386
+ const slpCoinObject = this.processCoins(tx, 'slp', lpCoinObjects, false)
387
+ const [withdrawObject] = tx.splitCoins(slpCoinObject, [tx.pure.u64(amount)])
388
+ const { vaultsValuation, symbolsValuation } = this.dataAPI.valuate(tx)
389
+
390
+ const [withdrawCoin] = tx.moveCall({
391
+ target: `${this.consts.sudoCore.upgradedPackage}::market::withdraw_ptb`,
392
+ typeArguments: [
393
+ `${this.consts.sudoCore.package}::slp::SLP`,
394
+ this.consts.coins[coin].module,
395
+ ],
396
+ arguments: [
397
+ tx.object(this.consts.sudoCore.market),
398
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
399
+ withdrawObject,
400
+ tx.pure.u64(minAmountOut),
401
+ vaultsValuation,
402
+ symbolsValuation,
403
+ ],
404
+ })
405
+ return withdrawCoin
406
+ }
407
+
408
+ public async swap(
409
+ fromToken: string,
410
+ toToken: string,
411
+ fromAmount: bigint,
412
+ fromCoinObjects: string[],
413
+ minAmountOut?: number,
414
+ ): Promise<Transaction> {
415
+ const tx = await this.initOracleTxb(
416
+ Object.keys(this.consts.sudoCore.vaults),
417
+ )
418
+ const fromCoinObject = this.processCoins(tx, fromToken, fromCoinObjects)
419
+ const [fromDepositObject] = tx.splitCoins(fromCoinObject, [
420
+ tx.pure.u64(fromAmount),
421
+ ])
422
+ const vaultsValuation = this.dataAPI.valuateVaults(tx)
423
+
424
+ tx.moveCall({
425
+ target: `${this.consts.sudoCore.upgradedPackage}::market::swap_v2`,
426
+ typeArguments: [
427
+ `${this.consts.sudoCore.package}::slp::SLP`,
428
+ this.consts.coins[fromToken].module,
429
+ this.consts.coins[toToken].module,
430
+ ],
431
+ arguments: [
432
+ tx.object(this.consts.sudoCore.market),
433
+ tx.object(this.consts.sudoCore.rebaseFeeModel),
434
+ fromDepositObject,
435
+ tx.pure.u64(minAmountOut || 0),
436
+ vaultsValuation,
437
+ tx.object(this.consts.pythFeeder.feeder[fromToken]),
438
+ tx.object(this.consts.pythFeeder.feeder[toToken]),
439
+ ],
440
+ })
441
+ return tx
442
+ }
443
+
444
+ /**
445
+ * Stakes SLP tokens in ZO staking pools
446
+ */
447
+ public stake(
448
+ lpCoinObjects: string[],
449
+ amount: bigint,
450
+ pool: string,
451
+ tx?: Transaction,
452
+ ): Transaction {
453
+ if (!tx) {
454
+ tx = new Transaction()
455
+ }
456
+
457
+ const coinObject = this.processCoins(tx, 'slp', lpCoinObjects)
458
+ const [depositObject] = tx.splitCoins(coinObject, [tx.pure.u64(amount)])
459
+
460
+ tx.moveCall({
461
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::deposit`,
462
+ typeArguments: [
463
+ `${this.consts.sudoCore.package}::slp::SLP`,
464
+ `${this.consts.sudoCore.package}::slp::SLP`,
465
+ ],
466
+ arguments: [
467
+ tx.object(pool),
468
+ tx.object(SUI_CLOCK_OBJECT_ID),
469
+ depositObject,
470
+ ],
471
+ })
472
+ return tx
473
+ }
474
+
475
+ /**
476
+ * Stakes SLP tokens using coin object only (PTB)
477
+ */
478
+ public stakeCoinObject(
479
+ coinObject: any,
480
+ pool: string,
481
+ tx?: Transaction,
482
+ ): Transaction {
483
+ if (!tx) {
484
+ tx = new Transaction()
485
+ }
486
+
487
+ tx.moveCall({
488
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::deposit`,
489
+ typeArguments: [
490
+ `${this.consts.sudoCore.package}::slp::SLP`,
491
+ `${this.consts.sudoCore.package}::slp::SLP`,
492
+ ],
493
+ arguments: [
494
+ tx.object(pool),
495
+ tx.object(SUI_CLOCK_OBJECT_ID),
496
+ coinObject,
497
+ ],
498
+ })
499
+ return tx
500
+ }
501
+
502
+ /**
503
+ * Unstakes SLP tokens from ZO staking pools
504
+ */
505
+ public unstake(
506
+ credentials: ISLPCredential[],
507
+ amount: bigint,
508
+ pool: string,
509
+ tx?: Transaction,
510
+ ): Transaction {
511
+ let unstakeAmount = amount
512
+ if (!tx) {
513
+ tx = new Transaction()
514
+ }
515
+ for (const credential of credentials) {
516
+ const withdrawAmount = (() => {
517
+ const min = (a: bigint, b: bigint) => a < b ? a : b
518
+ return min(unstakeAmount, credential.amount)
519
+ })()
520
+ unstakeAmount -= withdrawAmount
521
+ tx.moveCall({
522
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::withdraw`,
523
+ typeArguments: [
524
+ `${this.consts.sudoCore.package}::slp::SLP`,
525
+ `${this.consts.sudoCore.package}::slp::SLP`,
526
+ ],
527
+ arguments: [
528
+ tx.object(pool),
529
+ tx.object(SUI_CLOCK_OBJECT_ID),
530
+ tx.object(credential.id),
531
+ tx.pure.u64(withdrawAmount),
532
+ ],
533
+ })
534
+ if (credential.amount === BigInt(0)) {
535
+ tx.moveCall({
536
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::clear_empty_credential`,
537
+ typeArguments: [
538
+ `${this.consts.sudoCore.package}::slp::SLP`,
539
+ `${this.consts.sudoCore.package}::slp::SLP`,
540
+ ],
541
+ arguments: [tx.object(credential.id)],
542
+ })
543
+ }
544
+ }
545
+ return tx
546
+ }
547
+
548
+ /**
549
+ * Unstakes SLP tokens from ZO staking pools return Coins
550
+ */
551
+ public unstakeToCoins(
552
+ credentials: ISLPCredential[],
553
+ amount: bigint,
554
+ pool: string,
555
+ tx: Transaction,
556
+ ): TransactionObjectArgument[] {
557
+ let unstakeAmount = amount
558
+ const withdrawnCoinObjects = []
559
+ for (const credential of credentials) {
560
+ const withdrawAmount = (() => {
561
+ const min = (a: bigint, b: bigint) => a < b ? a : b
562
+ return min(unstakeAmount, credential.amount)
563
+ })()
564
+ unstakeAmount -= withdrawAmount
565
+ const [withdrawnCoin] = tx.moveCall({
566
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::withdraw_ptb`,
567
+ typeArguments: [
568
+ `${this.consts.sudoCore.package}::slp::SLP`,
569
+ `${this.consts.sudoCore.package}::slp::SLP`,
570
+ ],
571
+ arguments: [
572
+ tx.object(pool),
573
+ tx.object(SUI_CLOCK_OBJECT_ID),
574
+ tx.object(credential.id),
575
+ tx.pure.u64(withdrawAmount),
576
+ ],
577
+ })
578
+ withdrawnCoinObjects.push(withdrawnCoin)
579
+ if (credential.amount === BigInt(0)) {
580
+ tx.moveCall({
581
+ target: `${this.sharedConfig.zoStaking.package}::pool::clear_empty_credential`,
582
+ typeArguments: [
583
+ `${this.consts.sudoCore.package}::slp::SLP`,
584
+ `${this.consts.sudoCore.package}::slp::SLP`,
585
+ ],
586
+ arguments: [tx.object(credential.id)],
587
+ })
588
+ }
589
+ }
590
+ return withdrawnCoinObjects
591
+ }
592
+
593
+ /**
594
+ * Withdraws SLP tokens from a staking pool credential (PTB)
595
+ * Returns the withdrawn coin object for use in programmable transaction blocks
596
+ */
597
+ public withdrawFromVaultPtb(
598
+ pool: string,
599
+ credential: string,
600
+ withdrawAmount: bigint,
601
+ tx: Transaction,
602
+ ): TransactionObjectArgument {
603
+ const [withdrawnCoin] = tx.moveCall({
604
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::withdraw_ptb`,
605
+ typeArguments: [
606
+ `${this.consts.sudoCore.package}::slp::SLP`,
607
+ `${this.consts.sudoCore.package}::slp::SLP`,
608
+ ],
609
+ arguments: [
610
+ tx.object(pool),
611
+ tx.object(SUI_CLOCK_OBJECT_ID),
612
+ tx.object(credential),
613
+ tx.pure.u64(withdrawAmount),
614
+ ],
615
+ })
616
+ return withdrawnCoin
617
+ }
618
+
619
+ /**
620
+ * Claims rewards from a staking pool credential (PTB)
621
+ * Returns the reward coin object for use in programmable transaction blocks
622
+ */
623
+ public claimRewardsPtb(
624
+ pool: string,
625
+ credential: string,
626
+ tx: Transaction,
627
+ ): TransactionObjectArgument {
628
+ const [rewardCoin] = tx.moveCall({
629
+ target: `${this.sharedConfig.zoStaking.upgradedPackage}::pool::claim_rewards_ptb`,
630
+ typeArguments: [
631
+ `${this.consts.sudoCore.package}::slp::SLP`,
632
+ `${this.consts.sudoCore.package}::slp::SLP`,
633
+ ],
634
+ arguments: [
635
+ tx.object(pool),
636
+ tx.object(SUI_CLOCK_OBJECT_ID),
637
+ tx.object(credential),
638
+ ],
639
+ })
640
+ return rewardCoin
641
+ }
642
+
643
+ /**
644
+ * Opens a position using Sudo SDK approach
645
+ */
646
+ public async openPosition(
647
+ collateralToken: string,
648
+ indexToken: string,
649
+ size: bigint,
650
+ collateralAmount: bigint,
651
+ coinObjects: string[],
652
+ long: boolean,
653
+ reserveAmount: bigint,
654
+ indexPrice: number,
655
+ collateralPrice: number,
656
+ isLimitOrder = false,
657
+ isIocOrder = false,
658
+ pricesSlippage = 0.003,
659
+ collateralSlippage = 0.5,
660
+ relayerFee = BigInt(0.5),
661
+ referralAddress?: string,
662
+ sender?: string,
663
+ sponsoredTx?: boolean,
664
+ suiCoinObjectsForPythUpdate?: string[],
665
+ ): Promise<Transaction> {
666
+ let tx = new Transaction()
667
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
668
+ tx = await this.addReferral(referralAddress, tx)
669
+ }
670
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
671
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
672
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
673
+
674
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
675
+ if (isLimitOrder) {
676
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
677
+ }
678
+
679
+ // Handle oracle initialization and coin processing
680
+ let suiCoinObject
681
+ if (sponsoredTx) {
682
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
683
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
684
+ }
685
+ else {
686
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
687
+ }
688
+
689
+ // Process coin splitting
690
+ const [depositObject, feeObject] = this.processCoinSplitting(
691
+ tx,
692
+ collateralToken,
693
+ coinObjects,
694
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
695
+ sponsoredTx,
696
+ suiCoinObject,
697
+ )
698
+
699
+ tx.moveCall({
700
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_v2_1`,
701
+ typeArguments: [
702
+ `${this.consts.sudoCore.package}::slp::SLP`,
703
+ this.consts.coins[collateralToken].module,
704
+ this.consts.coins[indexToken].module,
705
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
706
+ this.consts.coins[collateralToken].module,
707
+ ],
708
+ arguments: [
709
+ tx.object(SUI_CLOCK_OBJECT_ID),
710
+ tx.object(this.consts.sudoCore.market),
711
+ tx.object(
712
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
713
+ ),
714
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
715
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
716
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
717
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
718
+ depositObject,
719
+ feeObject,
720
+ tx.pure.u8(allowTrade),
721
+ tx.pure.u64(size),
722
+ tx.pure.u64(reserveAmount),
723
+ tx.pure.u256(adjustCollateralPrice),
724
+ tx.pure.u256(adjustPrice),
725
+ ],
726
+ })
727
+ return tx
728
+ }
729
+
730
+ /**
731
+ * Opens a position using Sudo SDK approach
732
+ */
733
+ public async openPositionWithCoin(
734
+ collateralToken: string,
735
+ indexToken: string,
736
+ size: bigint,
737
+ coinObj: TransactionObjectArgument,
738
+ long: boolean,
739
+ reserveAmount: bigint,
740
+ indexPrice: number,
741
+ collateralPrice: number,
742
+ isLimitOrder = false,
743
+ isIocOrder = false,
744
+ pricesSlippage = 0.003,
745
+ collateralSlippage = 0.5,
746
+ relayerFee = BigInt(0.5),
747
+ referralAddress?: string,
748
+ sender?: string,
749
+ tx?: Transaction,
750
+ sponsoredTx?: boolean,
751
+ suiCoinObjectsForPythUpdate?: string[],
752
+ ): Promise<Transaction> {
753
+ if (!tx) {
754
+ tx = new Transaction()
755
+ }
756
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
757
+ tx = await this.addReferral(referralAddress, tx)
758
+ }
759
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
760
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
761
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
762
+
763
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
764
+ if (isLimitOrder) {
765
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
766
+ }
767
+
768
+ // Handle oracle initialization and coin processing
769
+ let suiCoinObject
770
+ if (sponsoredTx) {
771
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
772
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
773
+ }
774
+ else {
775
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
776
+ }
777
+
778
+ // Process coin splitting
779
+ const [feeObject] = tx.splitCoins(coinObj, [tx.pure.u64(relayerFee)])
780
+
781
+ tx.moveCall({
782
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_v2_1`,
783
+ typeArguments: [
784
+ `${this.consts.sudoCore.package}::slp::SLP`,
785
+ this.consts.coins[collateralToken].module,
786
+ this.consts.coins[indexToken].module,
787
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
788
+ this.consts.coins[collateralToken].module,
789
+ ],
790
+ arguments: [
791
+ tx.object(SUI_CLOCK_OBJECT_ID),
792
+ tx.object(this.consts.sudoCore.market),
793
+ tx.object(
794
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
795
+ ),
796
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
797
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
798
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
799
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
800
+ coinObj,
801
+ feeObject,
802
+ tx.pure.u8(allowTrade),
803
+ tx.pure.u64(size),
804
+ tx.pure.u64(reserveAmount),
805
+ tx.pure.u256(adjustCollateralPrice),
806
+ tx.pure.u256(adjustPrice),
807
+ ],
808
+ })
809
+ return tx
810
+ }
811
+
812
+ /**
813
+ * Opens a new position in SLP (V2 - uses v3 contract)
814
+ */
815
+ public async openPositionV2(
816
+ collateralToken: string,
817
+ indexToken: string,
818
+ size: bigint,
819
+ collateralAmount: bigint,
820
+ coinObjects: string[],
821
+ long: boolean,
822
+ reserveAmount: bigint,
823
+ indexPrice: number,
824
+ collateralPrice: number,
825
+ isLimitOrder?: boolean,
826
+ isIocOrder?: boolean,
827
+ pricesSlippage = 0.003,
828
+ collateralSlippage = 0.5,
829
+ relayerFee = BigInt(0.5),
830
+ referralAddress?: string,
831
+ sender?: string,
832
+ sponsoredTx?: boolean,
833
+ suiCoinObjectsForPythUpdate?: string[],
834
+ ): Promise<Transaction> {
835
+ let tx = new Transaction()
836
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
837
+ tx = await this.addReferral(referralAddress, tx)
838
+ }
839
+
840
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
841
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
842
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
843
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
844
+
845
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
846
+ if (isLimitOrder) {
847
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
848
+ }
849
+
850
+ // Handle oracle initialization and coin processing
851
+ let suiCoinObject
852
+ if (sponsoredTx) {
853
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
854
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
855
+ }
856
+ else {
857
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
858
+ }
859
+
860
+ // Process coin splitting
861
+ const [depositObject, feeObject] = this.processCoinSplitting(
862
+ tx,
863
+ collateralToken,
864
+ coinObjects,
865
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
866
+ sponsoredTx,
867
+ suiCoinObject,
868
+ )
869
+
870
+ tx.moveCall({
871
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_v3`,
872
+ typeArguments: [
873
+ `${this.consts.sudoCore.package}::slp::SLP`,
874
+ this.consts.coins[collateralToken].module,
875
+ this.consts.coins[indexToken].module,
876
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
877
+ this.consts.coins[collateralToken].module,
878
+ ],
879
+ arguments: [
880
+ tx.object(SUI_CLOCK_OBJECT_ID),
881
+ tx.object(this.consts.sudoCore.market),
882
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
883
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
884
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
885
+ depositObject,
886
+ feeObject,
887
+ tx.pure.u8(allowTrade),
888
+ tx.pure.u64(size),
889
+ tx.pure.u64(reserveAmount),
890
+ tx.pure.u256(adjustCollateralPrice),
891
+ tx.pure.u256(adjustPrice),
892
+ tx.pure.u256(indexPriceThreshold),
893
+ ],
894
+ })
895
+
896
+ return tx
897
+ }
898
+
899
+ /**
900
+ * Opens a new position with Coin in SLP (V2 - uses v3 contract)
901
+ */
902
+ public async openPositionWithCoinV2(
903
+ collateralToken: string,
904
+ indexToken: string,
905
+ size: bigint,
906
+ coinObj: TransactionObjectArgument,
907
+ long: boolean,
908
+ reserveAmount: bigint,
909
+ indexPrice: number,
910
+ collateralPrice: number,
911
+ isLimitOrder?: boolean,
912
+ isIocOrder?: boolean,
913
+ pricesSlippage = 0.003,
914
+ collateralSlippage = 0.5,
915
+ relayerFee = BigInt(0.5),
916
+ referralAddress?: string,
917
+ sender?: string,
918
+ tx?: Transaction,
919
+ sponsoredTx?: boolean,
920
+ suiCoinObjectsForPythUpdate?: string[],
921
+ ): Promise<Transaction> {
922
+ if (!tx) {
923
+ tx = new Transaction()
924
+ }
925
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
926
+ tx = await this.addReferral(referralAddress, tx)
927
+ }
928
+
929
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
930
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
931
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
932
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
933
+
934
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
935
+ if (isLimitOrder) {
936
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
937
+ }
938
+
939
+ // Handle oracle initialization and coin processing
940
+ let suiCoinObject
941
+ if (sponsoredTx) {
942
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
943
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
944
+ }
945
+ else {
946
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
947
+ }
948
+
949
+ // Process coin splitting
950
+ const [feeObject] = tx.splitCoins(coinObj, [tx.pure.u64(relayerFee)])
951
+
952
+ tx.moveCall({
953
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_v3`,
954
+ typeArguments: [
955
+ `${this.consts.sudoCore.package}::slp::SLP`,
956
+ this.consts.coins[collateralToken].module,
957
+ this.consts.coins[indexToken].module,
958
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
959
+ this.consts.coins[collateralToken].module,
960
+ ],
961
+ arguments: [
962
+ tx.object(SUI_CLOCK_OBJECT_ID),
963
+ tx.object(this.consts.sudoCore.market),
964
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
965
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
966
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
967
+ coinObj,
968
+ feeObject,
969
+ tx.pure.u8(allowTrade),
970
+ tx.pure.u64(size),
971
+ tx.pure.u64(reserveAmount),
972
+ tx.pure.u256(adjustCollateralPrice),
973
+ tx.pure.u256(adjustPrice),
974
+ tx.pure.u256(indexPriceThreshold),
975
+ ],
976
+ })
977
+
978
+ return tx
979
+ }
980
+
981
+ /**
982
+ * Decreases an existing position in SLP using Sudo SDK approach
983
+ */
984
+ public async decreasePosition(
985
+ pcpId: string,
986
+ collateralToken: string,
987
+ indexToken: string,
988
+ amount: bigint,
989
+ long: boolean,
990
+ indexPrice: number,
991
+ collateralPrice: number,
992
+ isTriggerOrder = false,
993
+ isTakeProfitOrder = true,
994
+ isIocOrder = false,
995
+ pricesSlippage = 0.003,
996
+ collateralSlippage = 0.5,
997
+ relayerFee = BigInt(0.5),
998
+ coinObjects?: string[],
999
+ sponsoredTx?: boolean,
1000
+ suiCoinObjectsForPythUpdate?: string[],
1001
+ ): Promise<Transaction> {
1002
+ if (!coinObjects) {
1003
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
1004
+ }
1005
+
1006
+ let tx = new Transaction()
1007
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1008
+
1009
+ const adjustPrice = this.processSlippage(
1010
+ indexPrice,
1011
+ !long,
1012
+ isTriggerOrder ? 0 : pricesSlippage,
1013
+ )
1014
+ const adjustCollateralPrice = this.processSlippage(
1015
+ collateralPrice,
1016
+ false,
1017
+ collateralSlippage,
1018
+ )
1019
+
1020
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1021
+ if (isTriggerOrder) {
1022
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1023
+ }
1024
+ else {
1025
+ isTakeProfitOrder = true
1026
+ }
1027
+
1028
+ let suiCoinObject
1029
+ if (sponsoredTx) {
1030
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1031
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1032
+ }
1033
+ else {
1034
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1035
+ }
1036
+
1037
+ // Handle oracle initialization and coin processing
1038
+ const [feeObject] = this.processCoinSplitting(
1039
+ tx,
1040
+ collateralToken,
1041
+ coinObjects,
1042
+ [tx.pure.u64(relayerFee)],
1043
+ sponsoredTx,
1044
+ suiCoinObject,
1045
+ )
1046
+
1047
+ tx.moveCall({
1048
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_v2_1`,
1049
+ typeArguments: [
1050
+ `${this.consts.sudoCore.package}::slp::SLP`,
1051
+ this.consts.coins[collateralToken].module,
1052
+ this.consts.coins[indexToken].module,
1053
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1054
+ this.consts.coins[collateralToken].module,
1055
+ ],
1056
+ arguments: [
1057
+ tx.object(SUI_CLOCK_OBJECT_ID),
1058
+ tx.object(this.consts.sudoCore.market),
1059
+ tx.object(pcpId),
1060
+ tx.object(
1061
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
1062
+ ),
1063
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
1064
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1065
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1066
+ feeObject,
1067
+ tx.pure.u8(allowTrade),
1068
+ tx.pure.bool(isTakeProfitOrder),
1069
+ tx.pure.u64(amount),
1070
+ tx.pure.u256(adjustCollateralPrice),
1071
+ tx.pure.u256(adjustPrice),
1072
+ ],
1073
+ })
1074
+
1075
+ return tx
1076
+ }
1077
+
1078
+ /**
1079
+ * Decreases an existing position in SLP (V2 - uses v3 contract)
1080
+ */
1081
+ public async decreasePositionV2(
1082
+ pcpId: string,
1083
+ collateralToken: string,
1084
+ indexToken: string,
1085
+ amount: bigint,
1086
+ long: boolean,
1087
+ indexPrice: number,
1088
+ collateralPrice: number,
1089
+ isTriggerOrder = false,
1090
+ isTakeProfitOrder = true,
1091
+ isIocOrder = false,
1092
+ pricesSlippage = 0.003,
1093
+ collateralSlippage = 0.5,
1094
+ relayerFee = BigInt(0.5),
1095
+ coinObjects?: string[],
1096
+ sponsoredTx?: boolean,
1097
+ suiCoinObjectsForPythUpdate?: string[],
1098
+ ): Promise<Transaction> {
1099
+ if (!coinObjects) {
1100
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
1101
+ }
1102
+
1103
+ let tx = new Transaction()
1104
+
1105
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
1106
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
1107
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
1108
+
1109
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1110
+ if (isTriggerOrder) {
1111
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1112
+ }
1113
+ else {
1114
+ isTakeProfitOrder = true
1115
+ }
1116
+
1117
+ // Handle oracle initialization and coin processing
1118
+ let suiCoinObject
1119
+ if (sponsoredTx) {
1120
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1121
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1122
+ }
1123
+ else {
1124
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1125
+ }
1126
+
1127
+ // Process coin splitting
1128
+ const [feeObject] = this.processCoinSplitting(
1129
+ tx,
1130
+ collateralToken,
1131
+ coinObjects,
1132
+ [tx.pure.u64(relayerFee)],
1133
+ sponsoredTx,
1134
+ suiCoinObject,
1135
+ )
1136
+
1137
+ tx.moveCall({
1138
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_v3`,
1139
+ typeArguments: [
1140
+ `${this.consts.sudoCore.package}::slp::SLP`,
1141
+ this.consts.coins[collateralToken].module,
1142
+ this.consts.coins[indexToken].module,
1143
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1144
+ this.consts.coins[collateralToken].module,
1145
+ ],
1146
+ arguments: [
1147
+ tx.object(SUI_CLOCK_OBJECT_ID),
1148
+ tx.object(this.consts.sudoCore.market),
1149
+ tx.object(pcpId),
1150
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1151
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1152
+ feeObject,
1153
+ tx.pure.u8(allowTrade),
1154
+ tx.pure.bool(isTakeProfitOrder),
1155
+ tx.pure.u64(amount),
1156
+ tx.pure.u256(adjustCollateralPrice),
1157
+ tx.pure.u256(adjustPrice),
1158
+ tx.pure.u256(indexPriceThreshold),
1159
+ ],
1160
+ })
1161
+
1162
+ return tx
1163
+ }
1164
+
1165
+ public async decreaseMultiPositions(
1166
+ positions: Array<{
1167
+ pcpId: string
1168
+ collateralToken: string
1169
+ indexToken: string
1170
+ amount: bigint
1171
+ long: boolean
1172
+ indexPrice: number
1173
+ collateralPrice: number
1174
+ isTriggerOrder?: boolean
1175
+ isTakeProfitOrder?: boolean
1176
+ isIocOrder?: boolean
1177
+ pricesSlippage?: number
1178
+ collateralSlippage?: number
1179
+ relayerFee?: bigint
1180
+ coinObjects?: string[]
1181
+ }>,
1182
+ tx?: Transaction,
1183
+ sponsoredTx?: boolean,
1184
+ suiCoinObjectsForPythUpdate?: string[],
1185
+ ): Promise<Transaction> {
1186
+ if (!tx) {
1187
+ tx = new Transaction()
1188
+ }
1189
+
1190
+ // Handle oracle initialization and coin processing
1191
+ let suiCoinObject
1192
+ if (sponsoredTx) {
1193
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1194
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx, true, suiCoinObject)
1195
+ }
1196
+ else {
1197
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx)
1198
+ }
1199
+
1200
+ for (const position of positions) {
1201
+ const {
1202
+ pcpId,
1203
+ collateralToken,
1204
+ coinObjects = [],
1205
+ indexToken,
1206
+ amount,
1207
+ long,
1208
+ indexPrice,
1209
+ collateralPrice,
1210
+ isTriggerOrder = false,
1211
+ isTakeProfitOrder = true,
1212
+ isIocOrder = false,
1213
+ pricesSlippage = 0.003,
1214
+ collateralSlippage = 0.5,
1215
+ relayerFee = BigInt(0.5),
1216
+ } = position
1217
+ let innerIsTakeProfitOrder = isTakeProfitOrder
1218
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1219
+
1220
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
1221
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
1222
+
1223
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1224
+ if (isTriggerOrder) {
1225
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1226
+ }
1227
+ else {
1228
+ innerIsTakeProfitOrder = true
1229
+ }
1230
+
1231
+ // Process coin splitting
1232
+ const [feeObject] = this.processCoinSplitting(
1233
+ tx,
1234
+ collateralToken,
1235
+ coinObjects,
1236
+ [tx.pure.u64(relayerFee)],
1237
+ sponsoredTx,
1238
+ suiCoinObject,
1239
+ )
1240
+
1241
+ tx.moveCall({
1242
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_v2_1`,
1243
+ typeArguments: [
1244
+ `${this.consts.sudoCore.package}::slp::SLP`,
1245
+ this.consts.coins[collateralToken].module,
1246
+ this.consts.coins[indexToken].module,
1247
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1248
+ this.consts.coins[collateralToken].module,
1249
+ ],
1250
+ arguments: [
1251
+ tx.object(SUI_CLOCK_OBJECT_ID),
1252
+ tx.object(this.consts.sudoCore.market),
1253
+ tx.object(pcpId),
1254
+ tx.object(
1255
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
1256
+ ),
1257
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
1258
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1259
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1260
+ feeObject,
1261
+ tx.pure.u8(allowTrade),
1262
+ tx.pure.bool(innerIsTakeProfitOrder),
1263
+ tx.pure.u64(amount),
1264
+ tx.pure.u256(adjustCollateralPrice),
1265
+ tx.pure.u256(adjustPrice),
1266
+ ],
1267
+ })
1268
+ }
1269
+ return tx
1270
+ }
1271
+
1272
+ public async decreaseMultiPositionsV2(positions: Array<{
1273
+ pcpId: string
1274
+ collateralToken: string
1275
+ indexToken: string
1276
+ amount: bigint
1277
+ long: boolean
1278
+ indexPrice: number
1279
+ collateralPrice: number
1280
+ isTriggerOrder?: boolean
1281
+ isTakeProfitOrder?: boolean
1282
+ isIocOrder?: boolean
1283
+ pricesSlippage?: number
1284
+ collateralSlippage?: number
1285
+ relayerFee?: bigint
1286
+ coinObjects?: string[]
1287
+ }>, tx?: Transaction, sponsoredTx?: boolean, suiCoinObjectsForPythUpdate?: string[], feeObjects?: TransactionObjectArgument[]): Promise<Transaction> {
1288
+ const transaction = tx ?? new Transaction()
1289
+
1290
+ // Handle oracle initialization and coin processing
1291
+ const tokens = positions.flatMap(position => [position.collateralToken, position.indexToken])
1292
+ const suiCoinObject = sponsoredTx
1293
+ ? this.processCoins(transaction, 'sui', suiCoinObjectsForPythUpdate || [], true)
1294
+ : undefined
1295
+ await this.initOracleTxb(tokens, transaction, !!sponsoredTx, suiCoinObject)
1296
+
1297
+ if (!feeObjects || feeObjects.length !== positions.length) {
1298
+ throw new Error('feeObjects must be provided (pre-processed via buildFeeCoinObjects) and match positions length')
1299
+ }
1300
+
1301
+ for (const [i, position] of positions.entries()) {
1302
+ const feeObject = feeObjects[i]
1303
+ const {
1304
+ pcpId,
1305
+ collateralToken,
1306
+ indexToken,
1307
+ amount,
1308
+ long,
1309
+ indexPrice,
1310
+ collateralPrice,
1311
+ isTriggerOrder = false,
1312
+ isTakeProfitOrder = true,
1313
+ isIocOrder = false,
1314
+ pricesSlippage = 0.003,
1315
+ collateralSlippage = 0.5,
1316
+ } = position
1317
+ let innerIsTakeProfitOrder = isTakeProfitOrder
1318
+
1319
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
1320
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
1321
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
1322
+
1323
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1324
+ if (isTriggerOrder) {
1325
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1326
+ }
1327
+ else {
1328
+ innerIsTakeProfitOrder = true
1329
+ }
1330
+
1331
+ transaction.moveCall({
1332
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_v3`,
1333
+ typeArguments: [
1334
+ `${this.consts.sudoCore.package}::slp::SLP`,
1335
+ this.consts.coins[collateralToken].module,
1336
+ this.consts.coins[indexToken].module,
1337
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1338
+ this.consts.coins[collateralToken].module,
1339
+ ],
1340
+ arguments: [
1341
+ transaction.object(SUI_CLOCK_OBJECT_ID),
1342
+ transaction.object(this.consts.sudoCore.market),
1343
+ transaction.object(pcpId),
1344
+ transaction.object(this.consts.pythFeeder.feeder[collateralToken]),
1345
+ transaction.object(this.consts.pythFeeder.feeder[indexToken]),
1346
+ feeObject,
1347
+ transaction.pure.u8(allowTrade),
1348
+ transaction.pure.bool(innerIsTakeProfitOrder),
1349
+ transaction.pure.u64(amount),
1350
+ transaction.pure.u256(adjustCollateralPrice),
1351
+ transaction.pure.u256(adjustPrice),
1352
+ transaction.pure.u256(indexPriceThreshold),
1353
+ ],
1354
+ })
1355
+ }
1356
+ return transaction
1357
+ }
1358
+
1359
+ public async pledgeInPosition(
1360
+ pcpId: string,
1361
+ collateralToken: string,
1362
+ indexToken: string,
1363
+ amount: number,
1364
+ coinObjects: string[],
1365
+ long: boolean,
1366
+ sponsoredTx?: boolean,
1367
+ suiCoinObjectsForPythUpdate?: string[],
1368
+ ): Promise<Transaction> {
1369
+ let tx = new Transaction()
1370
+
1371
+ // Handle oracle initialization and coin processing
1372
+ let suiCoinObject
1373
+ if (sponsoredTx) {
1374
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1375
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1376
+ }
1377
+ else {
1378
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1379
+ }
1380
+
1381
+ // Process coin splitting
1382
+ const [depositObject] = this.processCoinSplitting(
1383
+ tx,
1384
+ collateralToken,
1385
+ coinObjects,
1386
+ [tx.pure.u64(amount)],
1387
+ sponsoredTx,
1388
+ suiCoinObject,
1389
+ )
1390
+
1391
+ tx.moveCall({
1392
+ target: `${this.consts.sudoCore.upgradedPackage}::market::pledge_in_position`,
1393
+ typeArguments: [
1394
+ `${this.consts.sudoCore.package}::slp::SLP`,
1395
+ this.consts.coins[collateralToken].module,
1396
+ this.consts.coins[indexToken].module,
1397
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1398
+ ],
1399
+ arguments: [
1400
+ tx.object(this.consts.sudoCore.market),
1401
+ tx.object(pcpId),
1402
+ depositObject,
1403
+ ],
1404
+ })
1405
+ return tx
1406
+ }
1407
+
1408
+ public async redeemFromPosition(
1409
+ pcpId: string,
1410
+ collateralToken: string,
1411
+ indexToken: string,
1412
+ amount: number,
1413
+ long: boolean,
1414
+ sponsoredTx?: boolean,
1415
+ suiCoinObjectsForPythUpdate?: string[],
1416
+ ): Promise<Transaction> {
1417
+ let tx = new Transaction()
1418
+ // Handle oracle initialization and coin processing
1419
+ let suiCoinObject
1420
+ if (sponsoredTx) {
1421
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1422
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1423
+ }
1424
+ else {
1425
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1426
+ }
1427
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1428
+
1429
+ tx.moveCall({
1430
+ target: `${this.consts.sudoCore.upgradedPackage}::market::redeem_from_position_v1_1`,
1431
+ typeArguments: [
1432
+ `${this.consts.sudoCore.package}::slp::SLP`,
1433
+ this.consts.coins[collateralToken].module,
1434
+ this.consts.coins[indexToken].module,
1435
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1436
+ ],
1437
+ arguments: [
1438
+ tx.object(SUI_CLOCK_OBJECT_ID),
1439
+ tx.object(this.consts.sudoCore.market),
1440
+ tx.object(pcpId),
1441
+ tx.object(
1442
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
1443
+ ),
1444
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
1445
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1446
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1447
+ tx.pure.u64(amount),
1448
+ ],
1449
+ })
1450
+
1451
+ return tx
1452
+ }
1453
+
1454
+ public cancelOrder(
1455
+ orderCapId: string,
1456
+ collateralToken: string,
1457
+ indexToken: string,
1458
+ long: boolean,
1459
+ type: string,
1460
+ isV11Order?: boolean,
1461
+ ): Transaction {
1462
+ const tx = new Transaction()
1463
+ let functionName = ''
1464
+ switch (type) {
1465
+ case 'OPEN_POSITION': {
1466
+ functionName = 'clear_open_position_order_unified'
1467
+ break
1468
+ }
1469
+ case 'OPEN_MARKET': {
1470
+ functionName = 'clear_open_market_order'
1471
+ break
1472
+ }
1473
+ case 'DECREASE_POSITION': {
1474
+ functionName = 'clear_decrease_position_order_unified'
1475
+ break
1476
+ }
1477
+ case 'DECREASE_MARKET': {
1478
+ functionName = 'clear_decrease_market_order'
1479
+ break
1480
+ }
1481
+ default: {
1482
+ throw new Error('invalid order type')
1483
+ }
1484
+ }
1485
+ tx.moveCall({
1486
+ target: `${this.consts.sudoCore.upgradedPackage}::market::${functionName}`,
1487
+ typeArguments: [
1488
+ `${this.consts.sudoCore.package}::slp::SLP`,
1489
+ this.consts.coins[collateralToken].module,
1490
+ this.consts.coins[indexToken].module,
1491
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1492
+ isV11Order ? this.consts.coins.sui.module : this.consts.coins[collateralToken].module,
1493
+ ],
1494
+ arguments: [
1495
+ tx.object(this.consts.sudoCore.market),
1496
+ tx.object(orderCapId),
1497
+ ],
1498
+ })
1499
+ return tx
1500
+ }
1501
+
1502
+ public cancelMultiOrders(
1503
+ orders: Array<{
1504
+ orderCapId: string
1505
+ collateralToken: string
1506
+ indexToken: string
1507
+ long: boolean
1508
+ type: string
1509
+ isV11Order?: boolean
1510
+ }>,
1511
+ tx?: Transaction,
1512
+ ): Transaction {
1513
+ if (!tx) {
1514
+ tx = new Transaction()
1515
+ }
1516
+
1517
+ for (const order of orders) {
1518
+ const { orderCapId, collateralToken, indexToken, long, type } = order
1519
+ let functionName = ''
1520
+ switch (type) {
1521
+ case 'OPEN_POSITION': {
1522
+ functionName = 'clear_open_position_order_unified'
1523
+ break
1524
+ }
1525
+ case 'OPEN_MARKET': {
1526
+ functionName = 'clear_open_market_order'
1527
+ break
1528
+ }
1529
+ case 'DECREASE_POSITION': {
1530
+ functionName = 'clear_decrease_position_order_unified'
1531
+ break
1532
+ }
1533
+ case 'DECREASE_MARKET': {
1534
+ functionName = 'clear_decrease_market_order'
1535
+ break
1536
+ }
1537
+ default: {
1538
+ throw new Error('invalid order type')
1539
+ }
1540
+ }
1541
+
1542
+ tx.moveCall({
1543
+ target: `${this.consts.sudoCore.upgradedPackage}::market::${functionName}`,
1544
+ typeArguments: [
1545
+ `${this.consts.sudoCore.package}::slp::SLP`,
1546
+ this.consts.coins[collateralToken].module,
1547
+ this.consts.coins[indexToken].module,
1548
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1549
+ this.consts.coins[collateralToken].module,
1550
+ ],
1551
+ arguments: [tx.object(this.consts.sudoCore.market), tx.object(orderCapId)],
1552
+ })
1553
+ }
1554
+ return tx
1555
+ }
1556
+
1557
+ public clearClosedPosition(
1558
+ pcpId: string,
1559
+ collateralToken: string,
1560
+ indexToken: string,
1561
+ long: boolean,
1562
+ tx: Transaction,
1563
+ ): void {
1564
+ tx.moveCall({
1565
+ target: `${this.consts.sudoCore.upgradedPackage}::market::clear_closed_position`,
1566
+ typeArguments: [
1567
+ `${this.consts.sudoCore.package}::slp::SLP`,
1568
+ this.consts.coins[collateralToken].module,
1569
+ this.consts.coins[indexToken].module,
1570
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1571
+ ],
1572
+ arguments: [tx.object(this.consts.sudoCore.market), tx.object(pcpId)],
1573
+ })
1574
+ }
1575
+
1576
+ public clearOpenPositionOrder(
1577
+ orderCapId: string,
1578
+ collateralToken: string,
1579
+ indexToken: string,
1580
+ long: boolean,
1581
+ tx: Transaction,
1582
+ isV11Order = true,
1583
+ ): void {
1584
+ tx.moveCall({
1585
+ target: `${this.consts.sudoCore.upgradedPackage}::market::clear_open_position_order_unified`,
1586
+ typeArguments: [
1587
+ `${this.consts.sudoCore.package}::slp::SLP`,
1588
+ this.consts.coins[collateralToken].module,
1589
+ this.consts.coins[indexToken].module,
1590
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1591
+ isV11Order ? this.consts.coins.sui.module : this.consts.coins[collateralToken].module,
1592
+ ],
1593
+ arguments: [
1594
+ tx.object(this.consts.sudoCore.market),
1595
+ tx.object(orderCapId),
1596
+ ],
1597
+ })
1598
+ }
1599
+
1600
+ public clearDecreasePositionOrder(
1601
+ orderCapId: string,
1602
+ collateralToken: string,
1603
+ indexToken: string,
1604
+ long: boolean,
1605
+ tx: Transaction,
1606
+ isV11Order = true,
1607
+ ): void {
1608
+ tx.moveCall({
1609
+ target: `${this.consts.sudoCore.upgradedPackage}::market::clear_decrease_position_order_unified`,
1610
+ typeArguments: [
1611
+ `${this.consts.sudoCore.package}::slp::SLP`,
1612
+ this.consts.coins[collateralToken].module,
1613
+ this.consts.coins[indexToken].module,
1614
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1615
+ isV11Order ? this.consts.coins.sui.module : this.consts.coins[collateralToken].module,
1616
+ ],
1617
+ arguments: [
1618
+ tx.object(this.consts.sudoCore.market),
1619
+ tx.object(orderCapId),
1620
+ ],
1621
+ })
1622
+ }
1623
+
1624
+ public clearOpenMarketOrder(
1625
+ orderCapId: string,
1626
+ collateralToken: string,
1627
+ indexToken: string,
1628
+ long: boolean,
1629
+ tx: Transaction,
1630
+ _isV11Order?: boolean,
1631
+ ): void {
1632
+ const funcName = 'clear_open_market_order'
1633
+ tx.moveCall({
1634
+ target: `${this.consts.sudoCore.upgradedPackage}::market::${funcName}`,
1635
+ typeArguments: [
1636
+ `${this.consts.sudoCore.package}::slp::SLP`,
1637
+ this.consts.coins[collateralToken].module,
1638
+ this.consts.coins[indexToken].module,
1639
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1640
+ this.consts.coins[collateralToken].module,
1641
+ ],
1642
+ arguments: [tx.object(this.consts.sudoCore.market), tx.object(orderCapId)],
1643
+ })
1644
+ }
1645
+
1646
+ public clearDecreaseMarketOrder(
1647
+ orderCapId: string,
1648
+ collateralToken: string,
1649
+ indexToken: string,
1650
+ long: boolean,
1651
+ tx: Transaction,
1652
+ _isV11Order?: boolean,
1653
+ ): void {
1654
+ const funcName = 'clear_decrease_market_order'
1655
+ tx.moveCall({
1656
+ target: `${this.consts.sudoCore.upgradedPackage}::market::${funcName}`,
1657
+ typeArguments: [
1658
+ `${this.consts.sudoCore.package}::slp::SLP`,
1659
+ this.consts.coins[collateralToken].module,
1660
+ this.consts.coins[indexToken].module,
1661
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1662
+ this.consts.coins[collateralToken].module,
1663
+ ],
1664
+ arguments: [tx.object(this.consts.sudoCore.market), tx.object(orderCapId)],
1665
+ })
1666
+ }
1667
+
1668
+ public async openPositionWithSCard(
1669
+ collateralToken: string,
1670
+ indexToken: string,
1671
+ size: bigint,
1672
+ collateralAmount: bigint,
1673
+ coinObjects: string[],
1674
+ long: boolean,
1675
+ reserveAmount: bigint,
1676
+ indexPrice: number,
1677
+ collateralPrice: number,
1678
+ kioskClient: KioskClient,
1679
+ kioskCap: KioskOwnerCap,
1680
+ scard: string,
1681
+ isLimitOrder = false,
1682
+ isIocOrder = false,
1683
+ pricesSlippage = 0.003,
1684
+ collateralSlippage = 0.5,
1685
+ relayerFee = BigInt(0.5),
1686
+ referralAddress?: string,
1687
+ sender?: string,
1688
+ sponsoredTx?: boolean,
1689
+ suiCoinObjectsForPythUpdate?: string[],
1690
+ ): Promise<Transaction> {
1691
+ let tx = new Transaction()
1692
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
1693
+ tx = await this.addReferral(referralAddress, tx)
1694
+ }
1695
+
1696
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1697
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage || 0.003)
1698
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage || 0.5)
1699
+
1700
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1701
+ if (isLimitOrder) {
1702
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1703
+ }
1704
+
1705
+ const kioskTx = new KioskTransaction({
1706
+ transaction: tx,
1707
+ kioskClient,
1708
+ cap: kioskCap,
1709
+ })
1710
+
1711
+ const [sudoCard, promise] = kioskTx.borrow({
1712
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1713
+ itemId: scard,
1714
+ })
1715
+
1716
+ // Handle oracle initialization and coin processing
1717
+ let suiCoinObject
1718
+ if (sponsoredTx) {
1719
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1720
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1721
+ }
1722
+ else {
1723
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1724
+ }
1725
+
1726
+ // Process coin splitting
1727
+ const [depositObject, feeObject] = this.processCoinSplitting(
1728
+ tx,
1729
+ collateralToken,
1730
+ coinObjects,
1731
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
1732
+ sponsoredTx,
1733
+ suiCoinObject,
1734
+ )
1735
+
1736
+ tx.moveCall({
1737
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_with_scard_v1`,
1738
+ typeArguments: [
1739
+ `${this.consts.sudoCore.package}::slp::SLP`,
1740
+ this.consts.coins[collateralToken].module,
1741
+ this.consts.coins[indexToken].module,
1742
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1743
+ this.consts.coins[collateralToken].module,
1744
+ ],
1745
+ arguments: [
1746
+ tx.object(SUI_CLOCK_OBJECT_ID),
1747
+ tx.object(this.consts.sudoCore.market),
1748
+ tx.object(
1749
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
1750
+ ),
1751
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
1752
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
1753
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1754
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1755
+ depositObject,
1756
+ feeObject,
1757
+ tx.pure.u8(allowTrade),
1758
+ tx.pure.u64(size),
1759
+ tx.pure.u64(reserveAmount),
1760
+ tx.pure.u256(adjustCollateralPrice),
1761
+ tx.pure.u256(adjustPrice),
1762
+ sudoCard,
1763
+ ],
1764
+ })
1765
+
1766
+ kioskTx
1767
+ .return({
1768
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1769
+ item: sudoCard,
1770
+ promise,
1771
+ })
1772
+ .finalize()
1773
+ return tx
1774
+ }
1775
+
1776
+ public async openPositionWithCoinAndSCard(
1777
+ collateralToken: string,
1778
+ indexToken: string,
1779
+ size: bigint,
1780
+ coinObj: TransactionObjectArgument,
1781
+ long: boolean,
1782
+ reserveAmount: bigint,
1783
+ indexPrice: number,
1784
+ collateralPrice: number,
1785
+ kioskClient: KioskClient,
1786
+ kioskCap: KioskOwnerCap,
1787
+ scard: string,
1788
+ isLimitOrder = false,
1789
+ isIocOrder = false,
1790
+ pricesSlippage = 0.003,
1791
+ collateralSlippage = 0.5,
1792
+ relayerFee = BigInt(0.5),
1793
+ referralAddress?: string,
1794
+ sender?: string,
1795
+ tx?: Transaction,
1796
+ sponsoredTx?: boolean,
1797
+ suiCoinObjectsForPythUpdate?: string[],
1798
+ ): Promise<Transaction> {
1799
+ if (!tx) {
1800
+ tx = new Transaction()
1801
+ }
1802
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
1803
+ tx = await this.addReferral(referralAddress, tx)
1804
+ }
1805
+
1806
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1807
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage || 0.003)
1808
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage || 0.5)
1809
+
1810
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1811
+ if (isLimitOrder) {
1812
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1813
+ }
1814
+
1815
+ const kioskTx = new KioskTransaction({
1816
+ transaction: tx,
1817
+ kioskClient,
1818
+ cap: kioskCap,
1819
+ })
1820
+
1821
+ const [sudoCard, promise] = kioskTx.borrow({
1822
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1823
+ itemId: scard,
1824
+ })
1825
+
1826
+ // Handle oracle initialization and coin processing
1827
+ let suiCoinObject
1828
+ if (sponsoredTx) {
1829
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1830
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1831
+ }
1832
+ else {
1833
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1834
+ }
1835
+
1836
+ // Process coin splitting
1837
+ const [feeObject] = tx.splitCoins(coinObj, [tx.pure.u64(relayerFee)])
1838
+
1839
+ tx.moveCall({
1840
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_with_scard_v1`,
1841
+ typeArguments: [
1842
+ `${this.consts.sudoCore.package}::slp::SLP`,
1843
+ this.consts.coins[collateralToken].module,
1844
+ this.consts.coins[indexToken].module,
1845
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1846
+ this.consts.coins[collateralToken].module,
1847
+ ],
1848
+ arguments: [
1849
+ tx.object(SUI_CLOCK_OBJECT_ID),
1850
+ tx.object(this.consts.sudoCore.market),
1851
+ tx.object(
1852
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
1853
+ ),
1854
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
1855
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
1856
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1857
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1858
+ coinObj,
1859
+ feeObject,
1860
+ tx.pure.u8(allowTrade),
1861
+ tx.pure.u64(size),
1862
+ tx.pure.u64(reserveAmount),
1863
+ tx.pure.u256(adjustCollateralPrice),
1864
+ tx.pure.u256(adjustPrice),
1865
+ sudoCard,
1866
+ ],
1867
+ })
1868
+
1869
+ kioskTx
1870
+ .return({
1871
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1872
+ item: sudoCard,
1873
+ promise,
1874
+ })
1875
+ .finalize()
1876
+ return tx
1877
+ }
1878
+
1879
+ public async openPositionWithSCardV2(
1880
+ collateralToken: string,
1881
+ indexToken: string,
1882
+ size: bigint,
1883
+ collateralAmount: bigint,
1884
+ coinObjects: string[],
1885
+ long: boolean,
1886
+ reserveAmount: bigint,
1887
+ indexPrice: number,
1888
+ collateralPrice: number,
1889
+ kioskClient: KioskClient,
1890
+ kioskCap: KioskOwnerCap,
1891
+ scard: string,
1892
+ isLimitOrder?: boolean,
1893
+ isIocOrder?: boolean,
1894
+ pricesSlippage = 0.003,
1895
+ collateralSlippage = 0.5,
1896
+ relayerFee = BigInt(0.5),
1897
+ referralAddress?: string,
1898
+ sender?: string,
1899
+ sponsoredTx?: boolean,
1900
+ suiCoinObjectsForPythUpdate?: string[],
1901
+ ): Promise<Transaction> {
1902
+ let tx = new Transaction()
1903
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
1904
+ tx = await this.addReferral(referralAddress, tx)
1905
+ }
1906
+
1907
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
1908
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
1909
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
1910
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
1911
+
1912
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
1913
+ if (isLimitOrder) {
1914
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
1915
+ }
1916
+
1917
+ const kioskTx = new KioskTransaction({
1918
+ transaction: tx,
1919
+ kioskClient,
1920
+ cap: kioskCap,
1921
+ })
1922
+
1923
+ const [sudoCard, promise] = kioskTx.borrow({
1924
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1925
+ itemId: scard,
1926
+ })
1927
+
1928
+ // Handle oracle initialization and coin processing
1929
+ let suiCoinObject
1930
+ if (sponsoredTx) {
1931
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
1932
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
1933
+ }
1934
+ else {
1935
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
1936
+ }
1937
+
1938
+ // Process coin splitting
1939
+ const [depositObject, feeObject] = this.processCoinSplitting(
1940
+ tx,
1941
+ collateralToken,
1942
+ coinObjects,
1943
+ [tx.pure.u64(collateralAmount), tx.pure.u64(relayerFee)],
1944
+ sponsoredTx,
1945
+ suiCoinObject,
1946
+ )
1947
+
1948
+ tx.moveCall({
1949
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_with_scard_v2`,
1950
+ typeArguments: [
1951
+ `${this.consts.sudoCore.package}::slp::SLP`,
1952
+ this.consts.coins[collateralToken].module,
1953
+ this.consts.coins[indexToken].module,
1954
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
1955
+ this.consts.coins[collateralToken].module,
1956
+ ],
1957
+ arguments: [
1958
+ tx.object(SUI_CLOCK_OBJECT_ID),
1959
+ tx.object(this.consts.sudoCore.market),
1960
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
1961
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
1962
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
1963
+ depositObject,
1964
+ feeObject,
1965
+ tx.pure.u8(allowTrade),
1966
+ tx.pure.u64(size),
1967
+ tx.pure.u64(reserveAmount),
1968
+ tx.pure.u256(adjustCollateralPrice),
1969
+ tx.pure.u256(adjustPrice),
1970
+ tx.pure.u256(indexPriceThreshold),
1971
+ sudoCard,
1972
+ ],
1973
+ })
1974
+
1975
+ kioskTx
1976
+ .return({
1977
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
1978
+ item: sudoCard,
1979
+ promise,
1980
+ })
1981
+ .finalize()
1982
+
1983
+ return tx
1984
+ }
1985
+
1986
+ // S Card operations
1987
+ public async openPositionWithCoinAndSCardV2(
1988
+ collateralToken: string,
1989
+ indexToken: string,
1990
+ size: bigint,
1991
+ coinObj: TransactionObjectArgument,
1992
+ long: boolean,
1993
+ reserveAmount: bigint,
1994
+ indexPrice: number,
1995
+ collateralPrice: number,
1996
+ kioskClient: KioskClient,
1997
+ kioskCap: KioskOwnerCap,
1998
+ scard: string,
1999
+ isLimitOrder?: boolean,
2000
+ isIocOrder?: boolean,
2001
+ pricesSlippage = 0.003,
2002
+ collateralSlippage = 0.5,
2003
+ relayerFee = BigInt(0.5),
2004
+ referralAddress?: string,
2005
+ sender?: string,
2006
+ tx?: Transaction,
2007
+ sponsoredTx?: boolean,
2008
+ suiCoinObjectsForPythUpdate?: string[],
2009
+ ): Promise<Transaction> {
2010
+ if (!tx) {
2011
+ tx = new Transaction()
2012
+ }
2013
+ if (referralAddress && !(await this.dataAPI.hasReferral(sender || ''))) {
2014
+ tx = await this.addReferral(referralAddress, tx)
2015
+ }
2016
+
2017
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2018
+ const adjustPrice = this.processSlippage(indexPrice, long, isLimitOrder ? 0 : pricesSlippage)
2019
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2020
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2021
+
2022
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2023
+ if (isLimitOrder) {
2024
+ allowTrade = isIocOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2025
+ }
2026
+
2027
+ const kioskTx = new KioskTransaction({
2028
+ transaction: tx,
2029
+ kioskClient,
2030
+ cap: kioskCap,
2031
+ })
2032
+
2033
+ const [sudoCard, promise] = kioskTx.borrow({
2034
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2035
+ itemId: scard,
2036
+ })
2037
+
2038
+ // Handle oracle initialization and coin processing
2039
+ let suiCoinObject
2040
+ if (sponsoredTx) {
2041
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
2042
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
2043
+ }
2044
+ else {
2045
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
2046
+ }
2047
+
2048
+ // Process coin splitting
2049
+ const [feeObject] = tx.splitCoins(coinObj, [tx.pure.u64(relayerFee)])
2050
+
2051
+ tx.moveCall({
2052
+ target: `${this.consts.sudoCore.upgradedPackage}::market::open_position_with_scard_v2`,
2053
+ typeArguments: [
2054
+ `${this.consts.sudoCore.package}::slp::SLP`,
2055
+ this.consts.coins[collateralToken].module,
2056
+ this.consts.coins[indexToken].module,
2057
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2058
+ this.consts.coins[collateralToken].module,
2059
+ ],
2060
+ arguments: [
2061
+ tx.object(SUI_CLOCK_OBJECT_ID),
2062
+ tx.object(this.consts.sudoCore.market),
2063
+ tx.object(this.consts.sudoCore.symbols[symbol].positionConfig),
2064
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
2065
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
2066
+ coinObj,
2067
+ feeObject,
2068
+ tx.pure.u8(allowTrade),
2069
+ tx.pure.u64(size),
2070
+ tx.pure.u64(reserveAmount),
2071
+ tx.pure.u256(adjustCollateralPrice),
2072
+ tx.pure.u256(adjustPrice),
2073
+ tx.pure.u256(indexPriceThreshold),
2074
+ sudoCard,
2075
+ ],
2076
+ })
2077
+
2078
+ kioskTx
2079
+ .return({
2080
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2081
+ item: sudoCard,
2082
+ promise,
2083
+ })
2084
+ .finalize()
2085
+
2086
+ return tx
2087
+ }
2088
+
2089
+ public async decreasePositionWithSCard(
2090
+ pcpId: string,
2091
+ collateralToken: string,
2092
+ indexToken: string,
2093
+ amount: bigint,
2094
+ long: boolean,
2095
+ indexPrice: number,
2096
+ collateralPrice: number,
2097
+ kioskClient: KioskClient,
2098
+ kioskCap: KioskOwnerCap,
2099
+ scard: string,
2100
+ isTriggerOrder = false,
2101
+ isTakeProfitOrder = true,
2102
+ isIocOrder = false,
2103
+ pricesSlippage = 0.003,
2104
+ collateralSlippage = 0.5,
2105
+ relayerFee = BigInt(0.5),
2106
+ coinObjects?: string[],
2107
+ sponsoredTx?: boolean,
2108
+ suiCoinObjectsForPythUpdate?: string[],
2109
+ ): Promise<Transaction> {
2110
+ if (!coinObjects) {
2111
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
2112
+ }
2113
+
2114
+ let tx = new Transaction()
2115
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2116
+
2117
+ const adjustPrice = this.processSlippage(
2118
+ indexPrice,
2119
+ !long,
2120
+ isTriggerOrder ? 0 : pricesSlippage,
2121
+ )
2122
+ const adjustCollateralPrice = this.processSlippage(
2123
+ collateralPrice,
2124
+ false,
2125
+ collateralSlippage,
2126
+ )
2127
+
2128
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2129
+ if (isTriggerOrder) {
2130
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2131
+ }
2132
+ else {
2133
+ isTakeProfitOrder = true
2134
+ }
2135
+
2136
+ const kioskTx = new KioskTransaction({
2137
+ transaction: tx,
2138
+ kioskClient,
2139
+ cap: kioskCap,
2140
+ })
2141
+
2142
+ const [sudoCard, promise] = kioskTx.borrow({
2143
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2144
+ itemId: scard,
2145
+ })
2146
+
2147
+ // Handle oracle initialization and coin processing
2148
+ let suiCoinObject
2149
+ if (sponsoredTx) {
2150
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
2151
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
2152
+ }
2153
+ else {
2154
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
2155
+ }
2156
+
2157
+ // Process coin splitting
2158
+ const [feeObject] = this.processCoinSplitting(
2159
+ tx,
2160
+ collateralToken,
2161
+ coinObjects,
2162
+ [tx.pure.u64(relayerFee)],
2163
+ sponsoredTx,
2164
+ suiCoinObject,
2165
+ )
2166
+
2167
+ tx.moveCall({
2168
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_with_scard_v1`,
2169
+ typeArguments: [
2170
+ `${this.consts.sudoCore.package}::slp::SLP`,
2171
+ this.consts.coins[collateralToken].module,
2172
+ this.consts.coins[indexToken].module,
2173
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2174
+ this.consts.coins[collateralToken].module,
2175
+ ],
2176
+ arguments: [
2177
+ tx.object(SUI_CLOCK_OBJECT_ID),
2178
+ tx.object(this.consts.sudoCore.market),
2179
+ tx.object(pcpId),
2180
+ tx.object(
2181
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
2182
+ ),
2183
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
2184
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
2185
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
2186
+ feeObject,
2187
+ tx.pure.u8(allowTrade),
2188
+ tx.pure.bool(isTakeProfitOrder),
2189
+ tx.pure.u64(amount),
2190
+ tx.pure.u256(adjustCollateralPrice),
2191
+ tx.pure.u256(adjustPrice),
2192
+ sudoCard,
2193
+ ],
2194
+ })
2195
+
2196
+ kioskTx
2197
+ .return({
2198
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2199
+ item: sudoCard,
2200
+ promise,
2201
+ })
2202
+ .finalize()
2203
+ return tx
2204
+ }
2205
+
2206
+ public async decreasePositionWithSCardV2(
2207
+ pcpId: string,
2208
+ collateralToken: string,
2209
+ indexToken: string,
2210
+ amount: bigint,
2211
+ long: boolean,
2212
+ indexPrice: number,
2213
+ collateralPrice: number,
2214
+ kioskClient: KioskClient,
2215
+ kioskCap: KioskOwnerCap,
2216
+ scard: string,
2217
+ isTriggerOrder = false,
2218
+ isTakeProfitOrder = true,
2219
+ isIocOrder = false,
2220
+ pricesSlippage = 0.003,
2221
+ collateralSlippage = 0.5,
2222
+ relayerFee = BigInt(0.5),
2223
+ coinObjects?: string[],
2224
+ sponsoredTx?: boolean,
2225
+ suiCoinObjectsForPythUpdate?: string[],
2226
+ ): Promise<Transaction> {
2227
+ if (!coinObjects) {
2228
+ throw new Error(`${this.constructor.name}: coinObjects is required`)
2229
+ }
2230
+
2231
+ let tx = new Transaction()
2232
+
2233
+ const kioskTx = new KioskTransaction({
2234
+ transaction: tx,
2235
+ kioskClient,
2236
+ cap: kioskCap,
2237
+ })
2238
+
2239
+ const [sudoCard, promise] = kioskTx.borrow({
2240
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2241
+ itemId: scard,
2242
+ })
2243
+
2244
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
2245
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2246
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2247
+
2248
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2249
+ if (isTriggerOrder) {
2250
+ allowTrade = isIocOrder || !isTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2251
+ }
2252
+ else {
2253
+ isTakeProfitOrder = true
2254
+ }
2255
+
2256
+ // Handle oracle initialization and coin processing
2257
+ let suiCoinObject
2258
+ if (sponsoredTx) {
2259
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
2260
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx, true, suiCoinObject)
2261
+ }
2262
+ else {
2263
+ tx = await this.initOracleTxb([collateralToken, indexToken], tx)
2264
+ }
2265
+
2266
+ // Process coin splitting
2267
+ const [feeObject] = this.processCoinSplitting(
2268
+ tx,
2269
+ collateralToken,
2270
+ coinObjects,
2271
+ [tx.pure.u64(relayerFee)],
2272
+ sponsoredTx,
2273
+ suiCoinObject,
2274
+ )
2275
+
2276
+ tx.moveCall({
2277
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_with_scard_v2`,
2278
+ typeArguments: [
2279
+ `${this.consts.sudoCore.package}::slp::SLP`,
2280
+ this.consts.coins[collateralToken].module,
2281
+ this.consts.coins[indexToken].module,
2282
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2283
+ this.consts.coins[collateralToken].module,
2284
+ ],
2285
+ arguments: [
2286
+ tx.object(SUI_CLOCK_OBJECT_ID),
2287
+ tx.object(this.consts.sudoCore.market),
2288
+ tx.object(pcpId),
2289
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
2290
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
2291
+ feeObject,
2292
+ tx.pure.u8(allowTrade),
2293
+ tx.pure.bool(isTakeProfitOrder),
2294
+ tx.pure.u64(amount),
2295
+ tx.pure.u256(adjustCollateralPrice),
2296
+ tx.pure.u256(adjustPrice),
2297
+ tx.pure.u256(indexPriceThreshold),
2298
+ sudoCard,
2299
+ ],
2300
+ })
2301
+
2302
+ kioskTx
2303
+ .return({
2304
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2305
+ item: sudoCard,
2306
+ promise,
2307
+ })
2308
+ .finalize()
2309
+ return tx
2310
+ }
2311
+
2312
+ public async decreaseMultiPositionsWithSCard(
2313
+ positions: Array<{
2314
+ pcpId: string
2315
+ collateralToken: string
2316
+ indexToken: string
2317
+ amount: bigint
2318
+ long: boolean
2319
+ indexPrice: number
2320
+ collateralPrice: number
2321
+ isTriggerOrder?: boolean
2322
+ isTakeProfitOrder?: boolean
2323
+ isIocOrder?: boolean
2324
+ pricesSlippage?: number
2325
+ collateralSlippage?: number
2326
+ relayerFee?: bigint
2327
+ coinObjects?: string[]
2328
+ }>,
2329
+ kioskClient: KioskClient,
2330
+ kioskCap: KioskOwnerCap,
2331
+ scard: string,
2332
+ tx?: Transaction,
2333
+ sponsoredTx?: boolean,
2334
+ suiCoinObjectsForPythUpdate?: string[],
2335
+ ): Promise<Transaction> {
2336
+ if (!tx) {
2337
+ tx = new Transaction()
2338
+ }
2339
+
2340
+ // Handle oracle initialization and coin processing
2341
+ let suiCoinObject
2342
+ if (sponsoredTx) {
2343
+ suiCoinObject = this.processCoins(tx, 'sui', suiCoinObjectsForPythUpdate || [], true)
2344
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx, true, suiCoinObject)
2345
+ }
2346
+ else {
2347
+ tx = await this.initOracleTxb(positions.flatMap(position => [position.collateralToken, position.indexToken]), tx)
2348
+ }
2349
+
2350
+ const kioskTx = new KioskTransaction({
2351
+ transaction: tx,
2352
+ kioskClient,
2353
+ cap: kioskCap,
2354
+ })
2355
+
2356
+ const [sudoCard, promise] = kioskTx.borrow({
2357
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2358
+ itemId: scard,
2359
+ })
2360
+
2361
+ for (const position of positions) {
2362
+ const {
2363
+ pcpId,
2364
+ collateralToken,
2365
+ indexToken,
2366
+ amount,
2367
+ long,
2368
+ indexPrice,
2369
+ collateralPrice,
2370
+ isTriggerOrder = false,
2371
+ isTakeProfitOrder = true,
2372
+ isIocOrder = false,
2373
+ pricesSlippage = 0.003,
2374
+ collateralSlippage = 0.5,
2375
+ relayerFee = BigInt(0.5),
2376
+ coinObjects = [],
2377
+ } = position
2378
+ let innerIsTakeProfitOrder = isTakeProfitOrder
2379
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2380
+
2381
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
2382
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2383
+
2384
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2385
+ if (isTriggerOrder) {
2386
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2387
+ }
2388
+ else {
2389
+ innerIsTakeProfitOrder = true
2390
+ }
2391
+
2392
+ // Process coin splitting
2393
+ const [feeObject] = this.processCoinSplitting(
2394
+ tx,
2395
+ collateralToken,
2396
+ coinObjects,
2397
+ [tx.pure.u64(relayerFee)],
2398
+ sponsoredTx,
2399
+ suiCoinObject,
2400
+ )
2401
+
2402
+ tx.moveCall({
2403
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_with_scard_v1`,
2404
+ typeArguments: [
2405
+ `${this.consts.sudoCore.package}::slp::SLP`,
2406
+ this.consts.coins[collateralToken].module,
2407
+ this.consts.coins[indexToken].module,
2408
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2409
+ this.consts.coins[collateralToken].module,
2410
+ ],
2411
+ arguments: [
2412
+ tx.object(SUI_CLOCK_OBJECT_ID),
2413
+ tx.object(this.consts.sudoCore.market),
2414
+ tx.object(pcpId),
2415
+ tx.object(
2416
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
2417
+ ),
2418
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
2419
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
2420
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
2421
+ feeObject,
2422
+ tx.pure.u8(allowTrade),
2423
+ tx.pure.bool(isTakeProfitOrder),
2424
+ tx.pure.u64(amount),
2425
+ tx.pure.u256(adjustCollateralPrice),
2426
+ tx.pure.u256(adjustPrice),
2427
+ sudoCard,
2428
+ ],
2429
+ })
2430
+ }
2431
+
2432
+ kioskTx
2433
+ .return({
2434
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2435
+ item: sudoCard,
2436
+ promise,
2437
+ })
2438
+ .finalize()
2439
+ return tx
2440
+ }
2441
+
2442
+ public async decreaseMultiPositionsWithSCardV2(
2443
+ positions: Array<{
2444
+ pcpId: string
2445
+ collateralToken: string
2446
+ indexToken: string
2447
+ amount: bigint
2448
+ long: boolean
2449
+ indexPrice: number
2450
+ collateralPrice: number
2451
+ isTriggerOrder?: boolean
2452
+ isTakeProfitOrder?: boolean
2453
+ isIocOrder?: boolean
2454
+ pricesSlippage?: number
2455
+ collateralSlippage?: number
2456
+ relayerFee?: bigint
2457
+ coinObjects?: string[]
2458
+ }>,
2459
+ kioskClient: KioskClient,
2460
+ kioskCap: KioskOwnerCap,
2461
+ scard: string,
2462
+ tx?: Transaction,
2463
+ sponsoredTx?: boolean,
2464
+ suiCoinObjectsForPythUpdate?: string[],
2465
+ feeObjects?: TransactionObjectArgument[],
2466
+ ): Promise<Transaction> {
2467
+ const transaction = tx ?? new Transaction()
2468
+
2469
+ // Handle oracle initialization and coin processing
2470
+ const tokens = positions.flatMap(position => [position.collateralToken, position.indexToken])
2471
+ const suiCoinObject = sponsoredTx
2472
+ ? this.processCoins(transaction, 'sui', suiCoinObjectsForPythUpdate || [], true)
2473
+ : undefined
2474
+ await this.initOracleTxb(tokens, transaction, !!sponsoredTx, suiCoinObject)
2475
+
2476
+ if (!feeObjects || feeObjects.length !== positions.length) {
2477
+ throw new Error('feeObjects must be provided (pre-processed via buildFeeCoinObjects) and match positions length')
2478
+ }
2479
+
2480
+ const kioskTx = new KioskTransaction({
2481
+ transaction,
2482
+ kioskClient,
2483
+ cap: kioskCap,
2484
+ })
2485
+
2486
+ const [sudoCard, promise] = kioskTx.borrow({
2487
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2488
+ itemId: scard,
2489
+ })
2490
+
2491
+ for (const [i, position] of positions.entries()) {
2492
+ const feeObject = feeObjects[i]
2493
+ const {
2494
+ pcpId,
2495
+ collateralToken,
2496
+ indexToken,
2497
+ amount,
2498
+ long,
2499
+ indexPrice,
2500
+ collateralPrice,
2501
+ isTriggerOrder = false,
2502
+ isTakeProfitOrder = true,
2503
+ isIocOrder = false,
2504
+ pricesSlippage = 0.003,
2505
+ collateralSlippage = 0.5,
2506
+ } = position
2507
+ let innerIsTakeProfitOrder = isTakeProfitOrder
2508
+
2509
+ const adjustPrice = this.processSlippage(indexPrice, !long, isTriggerOrder ? 0 : pricesSlippage)
2510
+ const adjustCollateralPrice = this.processSlippage(collateralPrice, false, collateralSlippage)
2511
+ const indexPriceThreshold = this.processPriceThreshold(indexPrice, pricesSlippage)
2512
+
2513
+ let allowTrade = ALLOW_TRADE_MUST_TRADE
2514
+ if (isTriggerOrder) {
2515
+ allowTrade = isIocOrder || !innerIsTakeProfitOrder ? ALLOW_TRADE_NO_TRADE : ALLOW_TRADE_CAN_TRADE
2516
+ }
2517
+ else {
2518
+ innerIsTakeProfitOrder = true
2519
+ }
2520
+
2521
+ transaction.moveCall({
2522
+ target: `${this.consts.sudoCore.upgradedPackage}::market::decrease_position_with_scard_v2`,
2523
+ typeArguments: [
2524
+ `${this.consts.sudoCore.package}::slp::SLP`,
2525
+ this.consts.coins[collateralToken].module,
2526
+ this.consts.coins[indexToken].module,
2527
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2528
+ this.consts.coins[collateralToken].module,
2529
+ ],
2530
+ arguments: [
2531
+ transaction.object(SUI_CLOCK_OBJECT_ID),
2532
+ transaction.object(this.consts.sudoCore.market),
2533
+ transaction.object(pcpId),
2534
+ transaction.object(this.consts.pythFeeder.feeder[collateralToken]),
2535
+ transaction.object(this.consts.pythFeeder.feeder[indexToken]),
2536
+ feeObject,
2537
+ transaction.pure.u8(allowTrade),
2538
+ transaction.pure.bool(innerIsTakeProfitOrder),
2539
+ transaction.pure.u64(amount),
2540
+ transaction.pure.u256(adjustCollateralPrice),
2541
+ transaction.pure.u256(adjustPrice),
2542
+ transaction.pure.u256(indexPriceThreshold),
2543
+ sudoCard,
2544
+ ],
2545
+ })
2546
+ }
2547
+
2548
+ kioskTx
2549
+ .return({
2550
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2551
+ item: sudoCard,
2552
+ promise,
2553
+ })
2554
+ .finalize()
2555
+ return transaction
2556
+ }
2557
+
2558
+ public addReferral(
2559
+ referrer: string,
2560
+ tx?: Transaction,
2561
+ ): Transaction {
2562
+ if (!tx) {
2563
+ tx = new Transaction()
2564
+ }
2565
+ tx.moveCall({
2566
+ target: `${this.consts.sudoCore.upgradedPackage}::market::add_new_referral`,
2567
+ typeArguments: [`${this.consts.sudoCore.package}::slp::SLP`],
2568
+ arguments: [tx.object(this.consts.sudoCore.market), tx.pure.address(referrer)],
2569
+ })
2570
+
2571
+ return tx
2572
+ }
2573
+
2574
+ public async adminUpdatePriceFeed(
2575
+ collateralToken: string,
2576
+ indexToken: string,
2577
+ ): Promise<Transaction> {
2578
+ const tx = await this.initOracleTxb([collateralToken, indexToken])
2579
+ return tx
2580
+ }
2581
+
2582
+ public adminSettlePosition(
2583
+ _positionId: string,
2584
+ _owner: string,
2585
+ _collateralToken: string,
2586
+ _indexToken: string,
2587
+ _long: boolean,
2588
+ ): Transaction {
2589
+ // SLP does not support this operation
2590
+ throw new Error(`Method not implemented for ${this.constructor.name}`)
2591
+ }
2592
+
2593
+ public adminDecreasePosition(
2594
+ positionId: string,
2595
+ owner: string,
2596
+ collateralToken: string,
2597
+ indexToken: string,
2598
+ positionAmount: number,
2599
+ amount: bigint,
2600
+ long: boolean,
2601
+ collateralPrice?: number,
2602
+ collateralSlippage?: number,
2603
+ relayerFee?: bigint,
2604
+ ): Transaction {
2605
+ const tx = new Transaction()
2606
+ const symbol = joinSymbol(long ? 'long' : 'short', indexToken)
2607
+ const feeObject = tx.splitCoins(tx.gas, [tx.pure.u64(relayerFee || BigInt(1))])
2608
+
2609
+ const adjustCollateralPrice = this.processSlippage(
2610
+ collateralPrice || 0,
2611
+ false,
2612
+ collateralSlippage || 0.5,
2613
+ )
2614
+
2615
+ const allowTrade = ALLOW_TRADE_MUST_TRADE
2616
+
2617
+ tx.moveCall({
2618
+ target: `${this.consts.sudoCore.upgradedPackage}::market::admin_decrease_position_v1_3`,
2619
+ typeArguments: [
2620
+ `${this.consts.sudoCore.package}::slp::SLP`,
2621
+ this.consts.coins[collateralToken].module,
2622
+ this.consts.coins[indexToken].module,
2623
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2624
+ this.consts.coins.sui.module,
2625
+ ],
2626
+ arguments: [
2627
+ tx.object(this.consts.sudoCore.adminCap),
2628
+ tx.object(SUI_CLOCK_OBJECT_ID),
2629
+ tx.object(this.consts.sudoCore.market),
2630
+ tx.object(positionId),
2631
+ tx.object(
2632
+ this.consts.sudoCore.vaults[collateralToken].reservingFeeModel,
2633
+ ),
2634
+ tx.object(this.consts.sudoCore.symbols[symbol].fundingFeeModel),
2635
+ tx.object(this.consts.pythFeeder.feeder[collateralToken]),
2636
+ tx.object(this.consts.pythFeeder.feeder[indexToken]),
2637
+ feeObject,
2638
+ tx.pure.u8(allowTrade),
2639
+ tx.pure.u64(amount),
2640
+ tx.pure.u256(adjustCollateralPrice),
2641
+ tx.object(owner),
2642
+ ],
2643
+ })
2644
+
2645
+ if (amount === BigInt(positionAmount)) {
2646
+ this.adminClearClosedPosition(
2647
+ positionId,
2648
+ owner,
2649
+ collateralToken,
2650
+ indexToken,
2651
+ long,
2652
+ tx,
2653
+ )
2654
+ }
2655
+
2656
+ return tx
2657
+ }
2658
+
2659
+ public adminClearClosedPosition(
2660
+ positionId: string,
2661
+ owner: string,
2662
+ collateralToken: string,
2663
+ indexToken: string,
2664
+ long: boolean,
2665
+ tx: Transaction,
2666
+ ): void {
2667
+ tx.moveCall({
2668
+ target: `${this.consts.sudoCore.upgradedPackage}::market::admin_clear_closed_position_v1_1`,
2669
+ typeArguments: [
2670
+ `${this.consts.sudoCore.package}::slp::SLP`,
2671
+ this.consts.coins[collateralToken].module,
2672
+ this.consts.coins[indexToken].module,
2673
+ `${this.consts.sudoCore.package}::market::${long ? 'LONG' : 'SHORT'}`,
2674
+ ],
2675
+ arguments: [
2676
+ tx.object(this.consts.sudoCore.adminCap),
2677
+ tx.object(owner),
2678
+ tx.object(this.consts.sudoCore.market),
2679
+ tx.object(positionId),
2680
+ ],
2681
+ })
2682
+ }
2683
+
2684
+ // SLP Specific APIs
2685
+ public claimTokenFromSCard(
2686
+ token: string,
2687
+ coinObjects: string[],
2688
+ kioskClient: KioskClient,
2689
+ kioskCap: KioskOwnerCap,
2690
+ scard: string,
2691
+ ): Transaction {
2692
+ const tx = new Transaction()
2693
+ const kioskTx = new KioskTransaction({
2694
+ transaction: tx,
2695
+ kioskClient,
2696
+ cap: kioskCap,
2697
+ })
2698
+
2699
+ const [sudoCard, promise] = kioskTx.borrow({
2700
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2701
+ itemId: scard,
2702
+ })
2703
+
2704
+ // claim tokens
2705
+ coinObjects.forEach((coinObject) => {
2706
+ return tx.moveCall({
2707
+ target: `${this.consts.sudoNft.upgradedPackage}::card::claim_token`,
2708
+ typeArguments: [`${this.consts.coins[token].module}`],
2709
+ arguments: [sudoCard, tx.object(coinObject)],
2710
+ })
2711
+ })
2712
+
2713
+ kioskTx
2714
+ .return({
2715
+ itemType: `${this.consts.sudoNft.package}::card::SudoCard`,
2716
+ item: sudoCard,
2717
+ promise,
2718
+ })
2719
+ .finalize()
2720
+ return tx
2721
+ }
2722
+ }