@waterx/sdk 2.1.0 → 2.4.0

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 (231) hide show
  1. package/README.md +75 -169
  2. package/dist/src/client.d.ts +40 -2
  3. package/dist/src/client.js +55 -6
  4. package/dist/src/config.d.ts +66 -3
  5. package/dist/src/config.js +10 -4
  6. package/dist/src/constants.d.ts +6 -0
  7. package/dist/src/constants.js +6 -0
  8. package/dist/src/core/waterx-account.d.ts +31 -0
  9. package/dist/src/core/waterx-account.js +26 -0
  10. package/dist/src/fetch.d.ts +110 -0
  11. package/dist/src/fetch.js +149 -4
  12. package/dist/src/generated/bucket_v2_framework/account.d.ts +5 -5
  13. package/dist/src/generated/bucket_v2_framework/double.d.ts +77 -77
  14. package/dist/src/generated/bucket_v2_framework/float.d.ts +73 -73
  15. package/dist/src/generated/bucket_v2_framework/liability.d.ts +33 -33
  16. package/dist/src/generated/bucket_v2_framework/linked_table.d.ts +5 -5
  17. package/dist/src/generated/bucket_v2_framework/linked_table.js +2 -2
  18. package/dist/src/generated/bucket_v2_framework/sheet.d.ts +57 -57
  19. package/dist/src/generated/bucket_v2_framework/sheet.js +5 -11
  20. package/dist/src/generated/native_custody/custody_vault.d.ts +46 -32
  21. package/dist/src/generated/native_custody/custody_vault.js +19 -10
  22. package/dist/src/generated/native_custody/deps/bucket_v2_framework/sheet.js +1 -3
  23. package/dist/src/generated/native_custody/events.js +1 -2
  24. package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.d.ts +7 -7
  25. package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.js +1 -2
  26. package/dist/src/generated/utils/index.d.ts +7 -7
  27. package/dist/src/generated/utils/index.js +9 -6
  28. package/dist/src/generated/waterx_account/account.d.ts +124 -71
  29. package/dist/src/generated/waterx_account/account.js +64 -29
  30. package/dist/src/generated/waterx_account/deps/bucket_v2_framework/sheet.js +1 -3
  31. package/dist/src/generated/waterx_account/direct_rule.d.ts +5 -5
  32. package/dist/src/generated/waterx_account/events.d.ts +10 -0
  33. package/dist/src/generated/waterx_account/events.js +31 -50
  34. package/dist/src/generated/waterx_constant_rule/constant_rule.d.ts +68 -0
  35. package/dist/src/generated/waterx_constant_rule/constant_rule.js +59 -0
  36. package/dist/src/generated/waterx_constant_rule/deps/bucket_v2_framework/float.d.ts +8 -0
  37. package/dist/src/generated/waterx_constant_rule/deps/bucket_v2_framework/float.js +10 -0
  38. package/dist/src/generated/waterx_constant_rule/deps/sui/vec_map.d.ts +36 -0
  39. package/dist/src/generated/waterx_constant_rule/deps/sui/vec_map.js +27 -0
  40. package/dist/src/generated/waterx_credit/credit_registry.d.ts +9 -9
  41. package/dist/src/generated/waterx_credit/credit_registry.js +1 -2
  42. package/dist/src/generated/waterx_credit/limited_supply.d.ts +17 -17
  43. package/dist/src/generated/waterx_oracle/aggregator.js +1 -2
  44. package/dist/src/generated/waterx_oracle/collector.d.ts +17 -17
  45. package/dist/src/generated/waterx_oracle/collector.js +1 -1
  46. package/dist/src/generated/waterx_oracle/oracle.d.ts +5 -5
  47. package/dist/src/generated/waterx_perp/account_data.d.ts +5 -5
  48. package/dist/src/generated/waterx_perp/account_data.js +1 -2
  49. package/dist/src/generated/waterx_perp/deps/bucket_v2_framework/sheet.js +1 -3
  50. package/dist/src/generated/waterx_perp/events.d.ts +181 -181
  51. package/dist/src/generated/waterx_perp/events.js +87 -173
  52. package/dist/src/generated/waterx_perp/global_config.d.ts +3 -3
  53. package/dist/src/generated/waterx_perp/global_config.js +6 -12
  54. package/dist/src/generated/waterx_perp/keyed_big_vector.d.ts +9 -9
  55. package/dist/src/generated/waterx_perp/keyed_big_vector.js +1 -2
  56. package/dist/src/generated/waterx_perp/lp_pool.d.ts +115 -115
  57. package/dist/src/generated/waterx_perp/lp_pool.js +11 -22
  58. package/dist/src/generated/waterx_perp/market_config.d.ts +61 -43
  59. package/dist/src/generated/waterx_perp/market_config.js +29 -22
  60. package/dist/src/generated/waterx_perp/math.d.ts +7 -7
  61. package/dist/src/generated/waterx_perp/order_book.d.ts +47 -47
  62. package/dist/src/generated/waterx_perp/position.d.ts +99 -99
  63. package/dist/src/generated/waterx_perp/position.js +6 -12
  64. package/dist/src/generated/waterx_perp/request.d.ts +67 -67
  65. package/dist/src/generated/waterx_perp/request.js +2 -3
  66. package/dist/src/generated/waterx_perp/response.d.ts +35 -35
  67. package/dist/src/generated/waterx_perp/response.js +1 -2
  68. package/dist/src/generated/waterx_perp/trading.d.ts +303 -179
  69. package/dist/src/generated/waterx_perp/trading.js +99 -14
  70. package/dist/src/generated/waterx_perp_view/view.js +5 -10
  71. package/dist/src/generated/waterx_pyth_rule/pyth_rule.d.ts +5 -5
  72. package/dist/src/generated/waterx_pyth_rule/pyth_rule.js +1 -2
  73. package/dist/src/generated/waterx_referral/referral_table.d.ts +5 -5
  74. package/dist/src/generated/waterx_referral/referral_table.js +1 -2
  75. package/dist/src/generated/waterx_staking/waterx_staking.d.ts +19 -19
  76. package/dist/src/generated/waterx_staking/waterx_staking.js +10 -20
  77. package/dist/src/generated/waterx_supra_rule/deps/sui/vec_map.d.ts +36 -0
  78. package/dist/src/generated/waterx_supra_rule/deps/sui/vec_map.js +27 -0
  79. package/dist/src/generated/waterx_supra_rule/supra_rule.d.ts +158 -0
  80. package/dist/src/generated/waterx_supra_rule/supra_rule.js +148 -0
  81. package/dist/src/generated/withdrawal_queue/deps/bucket_v2_framework/float.d.ts +8 -0
  82. package/dist/src/generated/withdrawal_queue/deps/bucket_v2_framework/float.js +10 -0
  83. package/dist/src/generated/withdrawal_queue/deps/sui/vec_map.d.ts +36 -0
  84. package/dist/src/generated/withdrawal_queue/deps/sui/vec_map.js +27 -0
  85. package/dist/src/generated/withdrawal_queue/withdrawal_queue.d.ts +444 -4
  86. package/dist/src/generated/withdrawal_queue/withdrawal_queue.js +417 -4
  87. package/dist/src/generated/wormhole_bridge/wormhole_bridge.d.ts +214 -74
  88. package/dist/src/generated/wormhole_bridge/wormhole_bridge.js +158 -29
  89. package/dist/src/index.d.ts +4 -3
  90. package/dist/src/index.js +3 -2
  91. package/dist/src/prediction/account.d.ts +96 -0
  92. package/dist/src/prediction/account.js +230 -0
  93. package/dist/src/prediction/admin.d.ts +47 -0
  94. package/dist/src/prediction/admin.js +105 -0
  95. package/dist/src/prediction/bcs.d.ts +22 -0
  96. package/dist/src/prediction/bcs.js +240 -0
  97. package/dist/src/prediction/client.d.ts +75 -0
  98. package/dist/src/prediction/client.js +164 -0
  99. package/dist/src/prediction/config.d.ts +60 -0
  100. package/dist/src/prediction/config.js +75 -0
  101. package/dist/src/prediction/constants.d.ts +44 -0
  102. package/dist/src/prediction/constants.js +46 -0
  103. package/dist/src/prediction/fetch.d.ts +82 -0
  104. package/dist/src/prediction/fetch.js +270 -0
  105. package/dist/src/prediction/generated/bucket_v2_framework/account.d.ts +100 -0
  106. package/dist/src/prediction/generated/bucket_v2_framework/account.js +129 -0
  107. package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.d.ts +6 -0
  108. package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.js +19 -0
  109. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/balance.d.ts +10 -0
  110. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/balance.js +14 -0
  111. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.d.ts +36 -0
  112. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.js +27 -0
  113. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_set.d.ts +16 -0
  114. package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_set.js +19 -0
  115. package/dist/src/prediction/generated/bucket_v2_framework/double.d.ts +382 -0
  116. package/dist/src/prediction/generated/bucket_v2_framework/double.js +466 -0
  117. package/dist/src/prediction/generated/bucket_v2_framework/float.d.ts +362 -0
  118. package/dist/src/prediction/generated/bucket_v2_framework/float.js +440 -0
  119. package/dist/src/prediction/generated/bucket_v2_framework/liability.d.ts +193 -0
  120. package/dist/src/prediction/generated/bucket_v2_framework/liability.js +205 -0
  121. package/dist/src/prediction/generated/bucket_v2_framework/linked_table.d.ts +384 -0
  122. package/dist/src/prediction/generated/bucket_v2_framework/linked_table.js +382 -0
  123. package/dist/src/prediction/generated/bucket_v2_framework/sheet.d.ts +344 -0
  124. package/dist/src/prediction/generated/bucket_v2_framework/sheet.js +338 -0
  125. package/dist/src/prediction/generated/utils/index.d.ts +30 -0
  126. package/dist/src/prediction/generated/utils/index.js +160 -0
  127. package/dist/src/prediction/generated/waterx_account/account.d.ts +1589 -0
  128. package/dist/src/prediction/generated/waterx_account/account.js +1758 -0
  129. package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.d.ts +7 -0
  130. package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.js +13 -0
  131. package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.d.ts +7 -0
  132. package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.js +16 -0
  133. package/dist/src/prediction/generated/waterx_account/deps/std/type_name.d.ts +6 -0
  134. package/dist/src/prediction/generated/waterx_account/deps/std/type_name.js +19 -0
  135. package/dist/src/prediction/generated/waterx_account/deps/sui/balance.d.ts +10 -0
  136. package/dist/src/prediction/generated/waterx_account/deps/sui/balance.js +14 -0
  137. package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.d.ts +12 -0
  138. package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.js +19 -0
  139. package/dist/src/prediction/generated/waterx_account/deps/sui/table.d.ts +24 -0
  140. package/dist/src/prediction/generated/waterx_account/deps/sui/table.js +31 -0
  141. package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.d.ts +36 -0
  142. package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.js +27 -0
  143. package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.d.ts +16 -0
  144. package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.js +19 -0
  145. package/dist/src/prediction/generated/waterx_account/direct_rule.d.ts +75 -0
  146. package/dist/src/prediction/generated/waterx_account/direct_rule.js +78 -0
  147. package/dist/src/prediction/generated/waterx_account/events.d.ts +33 -0
  148. package/dist/src/prediction/generated/waterx_account/events.js +137 -0
  149. package/dist/src/prediction/generated/waterx_account/version.d.ts +10 -0
  150. package/dist/src/prediction/generated/waterx_account/version.js +8 -0
  151. package/dist/src/prediction/generated/waterx_prediction/account_data.d.ts +327 -0
  152. package/dist/src/prediction/generated/waterx_prediction/account_data.js +405 -0
  153. package/dist/src/prediction/generated/waterx_prediction/admin.d.ts +5 -0
  154. package/dist/src/prediction/generated/waterx_prediction/admin.js +9 -0
  155. package/dist/src/prediction/generated/waterx_prediction/bet_sharing.d.ts +60 -0
  156. package/dist/src/prediction/generated/waterx_prediction/bet_sharing.js +83 -0
  157. package/dist/src/prediction/generated/waterx_prediction/deps/bucket_v2_framework/linked_table.d.ts +8 -0
  158. package/dist/src/prediction/generated/waterx_prediction/deps/bucket_v2_framework/linked_table.js +18 -0
  159. package/dist/src/prediction/generated/waterx_prediction/deps/sui/balance.d.ts +10 -0
  160. package/dist/src/prediction/generated/waterx_prediction/deps/sui/balance.js +14 -0
  161. package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.d.ts +24 -0
  162. package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.js +31 -0
  163. package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.d.ts +16 -0
  164. package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.js +19 -0
  165. package/dist/src/prediction/generated/waterx_prediction/events.d.ts +22 -0
  166. package/dist/src/prediction/generated/waterx_prediction/events.js +179 -0
  167. package/dist/src/prediction/generated/waterx_prediction/global_config.d.ts +116 -0
  168. package/dist/src/prediction/generated/waterx_prediction/global_config.js +141 -0
  169. package/dist/src/prediction/generated/waterx_prediction/order.d.ts +200 -0
  170. package/dist/src/prediction/generated/waterx_prediction/order.js +284 -0
  171. package/dist/src/prediction/generated/waterx_prediction/outcome.d.ts +58 -0
  172. package/dist/src/prediction/generated/waterx_prediction/outcome.js +73 -0
  173. package/dist/src/prediction/generated/waterx_prediction/position.d.ts +160 -0
  174. package/dist/src/prediction/generated/waterx_prediction/position.js +214 -0
  175. package/dist/src/prediction/generated/waterx_prediction/version.d.ts +10 -0
  176. package/dist/src/prediction/generated/waterx_prediction/version.js +8 -0
  177. package/dist/src/prediction/generated/waterx_prediction/view.d.ts +353 -0
  178. package/dist/src/prediction/generated/waterx_prediction/view.js +432 -0
  179. package/dist/src/prediction/generated/waterx_prediction/waterx_prediction.d.ts +1698 -0
  180. package/dist/src/prediction/generated/waterx_prediction/waterx_prediction.js +1733 -0
  181. package/dist/src/prediction/gift-link.d.ts +6 -0
  182. package/dist/src/prediction/gift-link.js +5 -0
  183. package/dist/src/prediction/gift.d.ts +223 -0
  184. package/dist/src/prediction/gift.js +451 -0
  185. package/dist/src/prediction/index.d.ts +29 -0
  186. package/dist/src/prediction/index.js +21 -0
  187. package/dist/src/prediction/prediction.d.ts +104 -0
  188. package/dist/src/prediction/prediction.js +317 -0
  189. package/dist/src/prediction/tx-builders.d.ts +44 -0
  190. package/dist/src/prediction/tx-builders.js +52 -0
  191. package/dist/src/prediction/types.d.ts +93 -0
  192. package/dist/src/prediction/types.js +1 -0
  193. package/dist/src/prediction/user/account.d.ts +2 -0
  194. package/dist/src/prediction/user/account.js +1 -0
  195. package/dist/src/prediction/user/admin.d.ts +6 -0
  196. package/dist/src/prediction/user/admin.js +3 -0
  197. package/dist/src/prediction/user/gift.d.ts +2 -0
  198. package/dist/src/prediction/user/gift.js +1 -0
  199. package/dist/src/prediction/user/index.d.ts +5 -0
  200. package/dist/src/prediction/user/index.js +3 -0
  201. package/dist/src/prediction/user/keeper.d.ts +2 -0
  202. package/dist/src/prediction/user/keeper.js +1 -0
  203. package/dist/src/prediction/user/order.d.ts +2 -0
  204. package/dist/src/prediction/user/order.js +1 -0
  205. package/dist/src/prediction/user/position.d.ts +2 -0
  206. package/dist/src/prediction/user/position.js +1 -0
  207. package/dist/src/prediction/utils/bcs.d.ts +1 -0
  208. package/dist/src/prediction/utils/bcs.js +1 -0
  209. package/dist/src/prediction/utils/index.d.ts +1 -0
  210. package/dist/src/prediction/utils/index.js +1 -0
  211. package/dist/src/prediction/utils.d.ts +30 -0
  212. package/dist/src/prediction/utils.js +177 -0
  213. package/dist/src/sdk.d.ts +18 -0
  214. package/dist/src/sdk.js +17 -0
  215. package/dist/src/tx-builders.d.ts +54 -0
  216. package/dist/src/tx-builders.js +141 -0
  217. package/dist/src/unified-client.d.ts +407 -0
  218. package/dist/src/unified-client.js +123 -0
  219. package/dist/src/user/account.d.ts +27 -0
  220. package/dist/src/user/account.js +34 -8
  221. package/dist/src/user/credit.d.ts +8 -14
  222. package/dist/src/user/credit.js +9 -23
  223. package/dist/src/user/custody.d.ts +4 -18
  224. package/dist/src/user/custody.js +14 -25
  225. package/dist/src/utils/consolidate-balance.d.ts +37 -0
  226. package/dist/src/utils/consolidate-balance.js +89 -0
  227. package/dist/src/utils/math.d.ts +86 -0
  228. package/dist/src/utils/math.js +100 -0
  229. package/dist/src/utils/pyth.d.ts +42 -7
  230. package/dist/src/utils/pyth.js +107 -31
  231. package/package.json +129 -34
@@ -10,7 +10,8 @@
10
10
  * `enqueueWithdrawal` parks a FIFO `Queue<CREDIT>` entry.
11
11
  * - Keeper drains the queue via `executeWithdrawalWormhole` /
12
12
  * `executeWithdrawalNative` (caller must be on the executor allowlist).
13
- * - PSM: `custodyMint` / `custodyBurn` against the native `CustodyVault`.
13
+ * - PSM: `custodyMint` against the native `CustodyVault` (direct burn was
14
+ * removed — audit L03/M14; redeem via the withdraw queue path above).
14
15
  *
15
16
  * Every builder that emits a hot potato returns its argument so the caller
16
17
  * (or the high-level `tx-builders.ts` wrappers) can pair + consume it in the
@@ -55,6 +56,12 @@ export declare function routeWormhole(client: WaterXClient, tx: Transaction, par
55
56
  export interface RouteNativeParams {
56
57
  /** Fully-qualified backing asset Move type `T` (e.g. via `client.getNativeAsset`). */
57
58
  assetType: string;
59
+ /**
60
+ * Minimum `Coin<T>` the user will accept after the native burn fee;
61
+ * `execute_native` aborts `EOutputBelowMin` if a later fee change would
62
+ * deliver less (audit M15). Defaults to `0` (opt out).
63
+ */
64
+ minOutput?: bigint | number;
58
65
  }
59
66
  /** Build `withdrawal_queue::route_native<T>`. Returns the `extra_data` argument. */
60
67
  export declare function routeNative(client: WaterXClient, tx: Transaction, params: RouteNativeParams): TransactionArgument;
@@ -120,16 +127,3 @@ export interface CustodyMintParams {
120
127
  * {@link consumeCreditDeposit}).
121
128
  */
122
129
  export declare function custodyMint(client: WaterXClient, tx: Transaction, params: CustodyMintParams): TransactionArgument;
123
- export interface CustodyBurnParams {
124
- /** wxa account ID the burned CREDIT belongs to (cap / fee key). */
125
- accountId: string;
126
- /** `Coin<CREDIT>` to burn. */
127
- creditCoin: TransactionArgument;
128
- assetType: string;
129
- creditType?: string;
130
- }
131
- /**
132
- * Build `native_custody::custody_vault::burn<T, CREDIT>`. Returns the
133
- * resulting `Coin<T>` argument.
134
- */
135
- export declare function custodyBurn(client: WaterXClient, tx: Transaction, params: CustodyBurnParams): TransactionArgument;
@@ -10,14 +10,16 @@
10
10
  * `enqueueWithdrawal` parks a FIFO `Queue<CREDIT>` entry.
11
11
  * - Keeper drains the queue via `executeWithdrawalWormhole` /
12
12
  * `executeWithdrawalNative` (caller must be on the executor allowlist).
13
- * - PSM: `custodyMint` / `custodyBurn` against the native `CustodyVault`.
13
+ * - PSM: `custodyMint` against the native `CustodyVault` (direct burn was
14
+ * removed — audit L03/M14; redeem via the withdraw queue path above).
14
15
  *
15
16
  * Every builder that emits a hot potato returns its argument so the caller
16
17
  * (or the high-level `tx-builders.ts` wrappers) can pair + consume it in the
17
18
  * same PTB.
18
19
  */
19
20
  import { fromHex } from "@mysten/bcs";
20
- import { burn as custodyBurnCall, mint as custodyMintCall, } from "../generated/native_custody/custody_vault.js";
21
+ import { normalizeStructTag } from "@mysten/sui/utils";
22
+ import { mint as custodyMintCall } from "../generated/native_custody/custody_vault.js";
21
23
  import { requestWithdraw as requestWithdrawCall } from "../generated/waterx_account/account.js";
22
24
  import { consumeDepositDirect } from "../generated/waterx_account/direct_rule.js";
23
25
  import { enqueue as enqueueCall, executeNative as executeNativeCall, executeWormhole as executeWormholeCall, routeNative as routeNativeCall, routeWormhole as routeWormholeCall, } from "../generated/withdrawal_queue/withdrawal_queue.js";
@@ -45,7 +47,7 @@ function toEvmAddressBytes(input, field) {
45
47
  return bytes;
46
48
  }
47
49
  function creditTypeOf(client, override) {
48
- return override ?? client.creditType();
50
+ return normalizeStructTag(override ?? client.creditType());
49
51
  }
50
52
  // Required-ID accessors: the credit/bridge package entries carry their
51
53
  // shared object ids only after the relevant deploy phase has run, so each
@@ -143,7 +145,8 @@ export function routeWormhole(client, tx, params) {
143
145
  export function routeNative(client, tx, params) {
144
146
  const out = routeNativeCall({
145
147
  package: queuePkg(client),
146
- typeArguments: [params.assetType],
148
+ arguments: { minOutput: BigInt(params.minOutput ?? 0n) },
149
+ typeArguments: [normalizeStructTag(params.assetType)],
147
150
  })(tx);
148
151
  return out;
149
152
  }
@@ -213,7 +216,7 @@ export function executeWithdrawalNative(client, tx, params) {
213
216
  vault: tx.object(custodyVaultId(client)),
214
217
  creditRegistry: tx.object(creditRegistryId(client)),
215
218
  },
216
- typeArguments: [params.assetType, creditTypeOf(client, params.creditType)],
219
+ typeArguments: [normalizeStructTag(params.assetType), creditTypeOf(client, params.creditType)],
217
220
  })(tx);
218
221
  }
219
222
  /**
@@ -232,24 +235,7 @@ export function custodyMint(client, tx, params) {
232
235
  assetCoin: params.assetCoin,
233
236
  extraData: toBytes(params.extraData ?? new Uint8Array()),
234
237
  },
235
- typeArguments: [params.assetType, creditTypeOf(client, params.creditType)],
238
+ typeArguments: [normalizeStructTag(params.assetType), creditTypeOf(client, params.creditType)],
236
239
  })(tx);
237
240
  return req;
238
241
  }
239
- /**
240
- * Build `native_custody::custody_vault::burn<T, CREDIT>`. Returns the
241
- * resulting `Coin<T>` argument.
242
- */
243
- export function custodyBurn(client, tx, params) {
244
- const out = custodyBurnCall({
245
- package: custodyPkg(client),
246
- arguments: {
247
- vault: tx.object(custodyVaultId(client)),
248
- registry: tx.object(creditRegistryId(client)),
249
- accountId: params.accountId,
250
- creditCoin: params.creditCoin,
251
- },
252
- typeArguments: [params.assetType, creditTypeOf(client, params.creditType)],
253
- })(tx);
254
- return out;
255
- }
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * Builders for `native_custody::custody_vault` — the Sui-native PSM that
3
3
  * mints the protocol CREDIT CoinType 1:1 against backing stable assets `T`
4
- * (CCTP USDC, USDT, …) and burns it back the other way.
4
+ * (CCTP USDC, USDT, …).
5
5
  *
6
6
  * `mintCredit` / `mintCreditFromRequest` return a `DepositRequest<CREDIT>`
7
7
  * hot potato — it must be consumed in the same PTB by the deposit policy
8
8
  * registered for CREDIT (the canonical policy is `direct_rule::DirectRule`).
9
9
  * `mintCreditToAccount` chains that consume for you.
10
10
  *
11
- * `burnCredit` returns the redeemed `Coin<T>`; the caller decides where it
12
- * goes (transfer, fold back into a wxa account, …).
11
+ * There is no direct burn builder: the contract removed witness-free
12
+ * `custody_vault::burn` (audit L03/M14). CREDIT redemption routes through
13
+ * requestCreditWithdraw -> enqueueWithdrawal -> keeper executeWithdrawalNative.
13
14
  *
14
15
  * Requires `waterx_credit` + `native_custody` in the loaded config — both
15
16
  * are optional in `WaterXConfig` since not every deployment ships the
@@ -54,18 +55,3 @@ export declare function mintCreditFromRequest(client: WaterXClient, tx: Transact
54
55
  * Assumes CREDIT's deposit policy is `DirectRule` (the canonical setup).
55
56
  */
56
57
  export declare function mintCreditToAccount(client: WaterXClient, tx: Transaction, params: MintCreditParams): void;
57
- export interface BurnCreditParams {
58
- /** wxa account ID the burned CREDIT belongs to (burn-cap + partner-fee key). */
59
- accountId: string;
60
- /** `Coin<CREDIT>` to redeem. */
61
- creditCoin: TransactionArgument;
62
- /** Fully-qualified backing-asset Move type `T` to redeem into. */
63
- assetType: string;
64
- /** CREDIT CoinType. Defaults to `client.creditType()`. */
65
- creditType?: string;
66
- }
67
- /**
68
- * Build `custody_vault::burn<T, CREDIT>`. Returns the redeemed `Coin<T>`
69
- * argument for the caller to forward.
70
- */
71
- export declare function burnCredit(client: WaterXClient, tx: Transaction, params: BurnCreditParams): TransactionArgument;
@@ -1,20 +1,22 @@
1
1
  /**
2
2
  * Builders for `native_custody::custody_vault` — the Sui-native PSM that
3
3
  * mints the protocol CREDIT CoinType 1:1 against backing stable assets `T`
4
- * (CCTP USDC, USDT, …) and burns it back the other way.
4
+ * (CCTP USDC, USDT, …).
5
5
  *
6
6
  * `mintCredit` / `mintCreditFromRequest` return a `DepositRequest<CREDIT>`
7
7
  * hot potato — it must be consumed in the same PTB by the deposit policy
8
8
  * registered for CREDIT (the canonical policy is `direct_rule::DirectRule`).
9
9
  * `mintCreditToAccount` chains that consume for you.
10
10
  *
11
- * `burnCredit` returns the redeemed `Coin<T>`; the caller decides where it
12
- * goes (transfer, fold back into a wxa account, …).
11
+ * There is no direct burn builder: the contract removed witness-free
12
+ * `custody_vault::burn` (audit L03/M14). CREDIT redemption routes through
13
+ * requestCreditWithdraw -> enqueueWithdrawal -> keeper executeWithdrawalNative.
13
14
  *
14
15
  * Requires `waterx_credit` + `native_custody` in the loaded config — both
15
16
  * are optional in `WaterXConfig` since not every deployment ships the
16
17
  * credit pipeline.
17
18
  */
19
+ import { normalizeStructTag } from "@mysten/sui/utils";
18
20
  import * as custody from "../generated/native_custody/custody_vault.js";
19
21
  import { consumeDepositDirect } from "../generated/waterx_account/direct_rule.js";
20
22
  function requireCredit(client) {
@@ -48,7 +50,10 @@ export function mintCredit(client, tx, params) {
48
50
  assetCoin: params.assetCoin,
49
51
  extraData: Array.from(params.extraData ?? new Uint8Array()),
50
52
  },
51
- typeArguments: [params.assetType, params.creditType ?? client.creditType()],
53
+ typeArguments: [
54
+ normalizeStructTag(params.assetType),
55
+ normalizeStructTag(params.creditType ?? client.creditType()),
56
+ ],
52
57
  })(tx);
53
58
  return req;
54
59
  }
@@ -68,7 +73,10 @@ export function mintCreditFromRequest(client, tx, params) {
68
73
  accountRegistry: tx.object(client.config.packages.waterx_account.account_registry),
69
74
  depositRequest: params.depositRequest,
70
75
  },
71
- typeArguments: [params.assetType, params.creditType ?? client.creditType()],
76
+ typeArguments: [
77
+ normalizeStructTag(params.assetType),
78
+ normalizeStructTag(params.creditType ?? client.creditType()),
79
+ ],
72
80
  })(tx);
73
81
  return req;
74
82
  }
@@ -88,25 +96,6 @@ export function mintCreditToAccount(client, tx, params) {
88
96
  registry: tx.object(client.config.packages.waterx_account.account_registry),
89
97
  req: req,
90
98
  },
91
- typeArguments: [params.creditType ?? client.creditType()],
99
+ typeArguments: [normalizeStructTag(params.creditType ?? client.creditType())],
92
100
  })(tx);
93
101
  }
94
- /**
95
- * Build `custody_vault::burn<T, CREDIT>`. Returns the redeemed `Coin<T>`
96
- * argument for the caller to forward.
97
- */
98
- export function burnCredit(client, tx, params) {
99
- const credit = requireCredit(client);
100
- const nc = requireCustody(client);
101
- const [coin] = custody.burn({
102
- package: nc.published_at,
103
- arguments: {
104
- vault: tx.object(nc.vault),
105
- registry: tx.object(credit.credit_registry),
106
- accountId: params.accountId,
107
- creditCoin: params.creditCoin,
108
- },
109
- typeArguments: [params.assetType, params.creditType ?? client.creditType()],
110
- })(tx);
111
- return coin;
112
- }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared probe helpers for {@link appendConsolidateToUsd} and
3
+ * {@link getSpendableCreditBalance} — one asset list, one gRPC read pattern,
4
+ * so display totals match what the next async tx-builder would sweep.
5
+ */
6
+ import type { WaterXClient } from "../client.ts";
7
+ /** CREDIT parked at a wxa account's Sui address (funds accumulator + owned coins). */
8
+ export interface AddressCreditBalance {
9
+ /** `getBalance.addressBalance` — funds accumulator path. */
10
+ fundsRaw: bigint;
11
+ /** Sum of `listCoins` object balances — TTO'd / owned `Coin<CREDIT>` path. */
12
+ coinsRaw: bigint;
13
+ }
14
+ /** One native-custody backing asset parked at a wxa account's Sui address. */
15
+ export interface ParkedBackingAssetBalance {
16
+ assetType: string;
17
+ decimals: number;
18
+ /** `getBalance.addressBalance` — funds accumulator (`send_funds` path). */
19
+ fundsRaw: bigint;
20
+ /** Sum of `listCoins` object balances — TTO'd / owned `Coin<T>` path. */
21
+ coinsRaw: bigint;
22
+ }
23
+ /** Rescale a u64 raw amount between token decimal precisions (truncates on downscale). */
24
+ export declare function rescaleRawAmount(raw: bigint, fromDecimals: number, toDecimals?: number): bigint;
25
+ /**
26
+ * Probe every backing asset registered on `native_custody` for non-zero balances
27
+ * parked at `accountId`'s Sui address. Matches the pre-tx scan inside
28
+ * {@link appendConsolidateToUsd}.
29
+ */
30
+ export declare function probeParkedBackingAssets(client: WaterXClient, accountId: string): Promise<ParkedBackingAssetBalance[]>;
31
+ /**
32
+ * Probe non-zero CREDIT parked at `accountId`'s Sui address. Matches the
33
+ * address-CREDIT legs inside {@link appendConsolidateAddressCredit}.
34
+ */
35
+ export declare function probeAddressCreditBalance(client: WaterXClient, accountId: string): Promise<AddressCreditBalance>;
36
+ /** Sum parked backing assets into CREDIT base units at the 1:1 PSM peg. */
37
+ export declare function sumParkedBackingAsCreditRaw(parked: readonly ParkedBackingAssetBalance[], creditDecimals?: number): bigint;
@@ -0,0 +1,89 @@
1
+ import { COLLATERAL_DECIMALS } from "../constants.js";
2
+ /** Rescale a u64 raw amount between token decimal precisions (truncates on downscale). */
3
+ export function rescaleRawAmount(raw, fromDecimals, toDecimals = COLLATERAL_DECIMALS) {
4
+ if (fromDecimals === toDecimals)
5
+ return raw;
6
+ if (fromDecimals < toDecimals) {
7
+ return raw * 10n ** BigInt(toDecimals - fromDecimals);
8
+ }
9
+ return raw / 10n ** BigInt(fromDecimals - toDecimals);
10
+ }
11
+ /**
12
+ * Probe every backing asset registered on `native_custody` for non-zero balances
13
+ * parked at `accountId`'s Sui address. Matches the pre-tx scan inside
14
+ * {@link appendConsolidateToUsd}.
15
+ */
16
+ export async function probeParkedBackingAssets(client, accountId) {
17
+ if (!client.config.packages.native_custody?.vault)
18
+ return [];
19
+ if (!client.config.packages.waterx_credit?.credit_type)
20
+ return [];
21
+ const out = [];
22
+ for (const asset of client.getNativeAssets()) {
23
+ const bal = (await client.getBalance({
24
+ owner: accountId,
25
+ coinType: asset.type,
26
+ }));
27
+ const fundsRaw = BigInt(bal.balance?.addressBalance ?? "0");
28
+ const coins = (await client.listCoins({
29
+ owner: accountId,
30
+ coinType: asset.type,
31
+ }));
32
+ let coinsRaw = 0n;
33
+ for (const coin of coins.objects ?? []) {
34
+ coinsRaw += BigInt(coin.balance ?? "0");
35
+ }
36
+ if (fundsRaw > 0n || coinsRaw > 0n) {
37
+ out.push({
38
+ assetType: asset.type,
39
+ decimals: asset.decimal,
40
+ fundsRaw,
41
+ coinsRaw,
42
+ });
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ /**
48
+ * Probe non-zero CREDIT parked at `accountId`'s Sui address. Matches the
49
+ * address-CREDIT legs inside {@link appendConsolidateAddressCredit}.
50
+ */
51
+ export async function probeAddressCreditBalance(client, accountId) {
52
+ if (!client.config.packages.waterx_credit?.credit_type) {
53
+ return { fundsRaw: 0n, coinsRaw: 0n };
54
+ }
55
+ const creditType = client.creditType();
56
+ let fundsRaw = 0n;
57
+ let coinsRaw = 0n;
58
+ try {
59
+ const bal = (await client.getBalance({
60
+ owner: accountId,
61
+ coinType: creditType,
62
+ }));
63
+ fundsRaw = BigInt(bal.balance?.addressBalance ?? "0");
64
+ }
65
+ catch {
66
+ // ignore — treat as zero parked funds
67
+ }
68
+ try {
69
+ const coins = (await client.listCoins({
70
+ owner: accountId,
71
+ coinType: creditType,
72
+ }));
73
+ for (const coin of coins.objects ?? []) {
74
+ coinsRaw += BigInt(coin.balance ?? "0");
75
+ }
76
+ }
77
+ catch {
78
+ // ignore — treat as zero owned coins
79
+ }
80
+ return { fundsRaw, coinsRaw };
81
+ }
82
+ /** Sum parked backing assets into CREDIT base units at the 1:1 PSM peg. */
83
+ export function sumParkedBackingAsCreditRaw(parked, creditDecimals = COLLATERAL_DECIMALS) {
84
+ let sum = 0n;
85
+ for (const row of parked) {
86
+ sum += rescaleRawAmount(row.fundsRaw + row.coinsRaw, row.decimals, creditDecimals);
87
+ }
88
+ return sum;
89
+ }
@@ -33,6 +33,92 @@ export declare function calcEstLiqPrice(params: {
33
33
  spotPrice: number;
34
34
  totalFeesUsd: number;
35
35
  }): number;
36
+ /**
37
+ * Effective (fee-adjusted) collateral in USD.
38
+ *
39
+ * Mirrors `calculate_effective_collateral_amount` in `trading.move`: the contract
40
+ * subtracts accrued borrow + trading fees and, **only when the position owes funding**
41
+ * (`fundingSign === true`, i.e. `unrealized_funding_sign`), the funding fee too. Funding
42
+ * *income* (position receives funding, `fundingSign === false`) is NOT added here —
43
+ * matching the contract's saturating-subtract path. Result clamps at 0.
44
+ *
45
+ * This is the collateral the contract actually uses for the max-leverage and
46
+ * min-collateral checks on `withdraw_collateral` — NOT the gross `collateral_amount`.
47
+ * Displaying leverage / max-reducible off gross collateral is the common UI bug
48
+ * (a position shows e.g. 23.3x on gross while the contract sees ~24.9x on effective).
49
+ *
50
+ * All inputs are human-readable USD. Convert raw collateral-token fee fields via
51
+ * `feeUsd = (rawFee / 10 ** collateralDecimal) * collateralPriceUsd`.
52
+ *
53
+ * @param grossCollateralUsd Position collateral in USD (`collateral_amount` → USD).
54
+ * @param borrowFeeUsd `unrealized_borrow_fee` in USD.
55
+ * @param fundingSign `unrealized_funding_sign` — true when the position owes funding.
56
+ * @param fundingFeeUsd `unrealized_funding_fee` magnitude in USD.
57
+ * @param tradingFeeUsd `unrealized_trading_fee` in USD.
58
+ * @param projectedTradingFeeUsd Closing fee to reserve (0 for a bare collateral withdrawal).
59
+ */
60
+ export declare function calcEffectiveCollateralUsd(params: {
61
+ grossCollateralUsd: number;
62
+ borrowFeeUsd: number;
63
+ fundingSign: boolean;
64
+ fundingFeeUsd: number;
65
+ tradingFeeUsd: number;
66
+ projectedTradingFeeUsd?: number;
67
+ }): number;
68
+ /**
69
+ * Maximum collateral (in USD) a position can safely withdraw ("最大可减少").
70
+ *
71
+ * Reproduces the three post-withdrawal checks in `execute_withdraw_collateral`
72
+ * (`trading.move`), all evaluated on **effective** (fee-adjusted) collateral, and
73
+ * returns the smallest allowed withdrawal:
74
+ *
75
+ * (A) max leverage — `notional / (effLeverage − w) ≤ maxLeverage`
76
+ * (B) min collateral — `(effLeverage − w) ≥ minCollValueUsd`
77
+ * (C) not liquidatable — `(liqRemaining − w) > maintenanceMargin × notional`
78
+ *
79
+ * where
80
+ * notional = sizeInAsset × spotPrice
81
+ * effLeverage = effective collateral with projectedTradingFee = 0
82
+ * (the contract's leverage/min-coll checks ignore the closing fee and PnL)
83
+ * liqRemaining = grossCollateralUsd + signedPnl − borrow − trading − closingFee ∓ funding
84
+ * (the contract's `is_liquidatable` boundary; funding income is added back)
85
+ *
86
+ * The result is a USD figure (matching the "$X" the UI shows), already aligned so that
87
+ * converting it to raw collateral units with floor is abort-safe:
88
+ * `rawAmount = floor((maxReducibleUsd / collateralPriceUsd) * 10 ** collateralDecimal)`.
89
+ * The liquidation leg backs off one raw collateral unit because `is_liquidatable` aborts
90
+ * on `remaining <= maintenance` (inclusive) — the safe withdrawal must leave remaining
91
+ * *strictly* above maintenance. The leverage (`> max`) and min-collateral (`>=`) checks
92
+ * are equality-safe on their own and floor-rounding only adds margin, so they need no offset.
93
+ *
94
+ * Funding handling is signed (income added, expense subtracted) — a close approximation
95
+ * of the contract's deficit-aware sequencing, exact whenever the position is solvent
96
+ * (the only case where a withdrawal can succeed). Clamps at 0.
97
+ *
98
+ * @param maxLeverage Max leverage as a ratio (e.g. 25 for `max_leverage_bps` 250000).
99
+ * @param maintenanceMarginRate `maintenance_margin` as a fraction (e.g. 0.01 for 1%).
100
+ * @param minCollValueUsd `min_coll_value` in USD (raw scaled value ÷ 1e9).
101
+ * @param closingFeeUsd Full closing fee in USD (`close_fee` → USD).
102
+ * @param collateralPriceUsd Oracle price of the collateral token (USD per token).
103
+ * @param collateralDecimal Collateral token decimals — sets the smallest withdraw step.
104
+ */
105
+ export declare function calcMaxReducibleCollateralUsd(params: {
106
+ grossCollateralUsd: number;
107
+ sizeInAsset: number;
108
+ spotPrice: number;
109
+ isLong: boolean;
110
+ entryPrice: number;
111
+ maxLeverage: number;
112
+ maintenanceMarginRate: number;
113
+ minCollValueUsd: number;
114
+ borrowFeeUsd: number;
115
+ tradingFeeUsd: number;
116
+ closingFeeUsd: number;
117
+ fundingSign: boolean;
118
+ fundingFeeUsd: number;
119
+ collateralPriceUsd: number;
120
+ collateralDecimal: number;
121
+ }): number;
36
122
  /**
37
123
  * Impact fee rate for an order (as a fraction, not bps).
38
124
  *
@@ -59,6 +59,106 @@ export function calcEstLiqPrice(params) {
59
59
  }
60
60
  return avgPrice * (1 + ratio);
61
61
  }
62
+ /**
63
+ * Effective (fee-adjusted) collateral in USD.
64
+ *
65
+ * Mirrors `calculate_effective_collateral_amount` in `trading.move`: the contract
66
+ * subtracts accrued borrow + trading fees and, **only when the position owes funding**
67
+ * (`fundingSign === true`, i.e. `unrealized_funding_sign`), the funding fee too. Funding
68
+ * *income* (position receives funding, `fundingSign === false`) is NOT added here —
69
+ * matching the contract's saturating-subtract path. Result clamps at 0.
70
+ *
71
+ * This is the collateral the contract actually uses for the max-leverage and
72
+ * min-collateral checks on `withdraw_collateral` — NOT the gross `collateral_amount`.
73
+ * Displaying leverage / max-reducible off gross collateral is the common UI bug
74
+ * (a position shows e.g. 23.3x on gross while the contract sees ~24.9x on effective).
75
+ *
76
+ * All inputs are human-readable USD. Convert raw collateral-token fee fields via
77
+ * `feeUsd = (rawFee / 10 ** collateralDecimal) * collateralPriceUsd`.
78
+ *
79
+ * @param grossCollateralUsd Position collateral in USD (`collateral_amount` → USD).
80
+ * @param borrowFeeUsd `unrealized_borrow_fee` in USD.
81
+ * @param fundingSign `unrealized_funding_sign` — true when the position owes funding.
82
+ * @param fundingFeeUsd `unrealized_funding_fee` magnitude in USD.
83
+ * @param tradingFeeUsd `unrealized_trading_fee` in USD.
84
+ * @param projectedTradingFeeUsd Closing fee to reserve (0 for a bare collateral withdrawal).
85
+ */
86
+ export function calcEffectiveCollateralUsd(params) {
87
+ const { grossCollateralUsd, borrowFeeUsd, fundingSign, fundingFeeUsd, tradingFeeUsd, projectedTradingFeeUsd = 0, } = params;
88
+ const eff = grossCollateralUsd -
89
+ borrowFeeUsd -
90
+ tradingFeeUsd -
91
+ projectedTradingFeeUsd -
92
+ (fundingSign ? fundingFeeUsd : 0);
93
+ return Math.max(0, eff);
94
+ }
95
+ /**
96
+ * Maximum collateral (in USD) a position can safely withdraw ("最大可减少").
97
+ *
98
+ * Reproduces the three post-withdrawal checks in `execute_withdraw_collateral`
99
+ * (`trading.move`), all evaluated on **effective** (fee-adjusted) collateral, and
100
+ * returns the smallest allowed withdrawal:
101
+ *
102
+ * (A) max leverage — `notional / (effLeverage − w) ≤ maxLeverage`
103
+ * (B) min collateral — `(effLeverage − w) ≥ minCollValueUsd`
104
+ * (C) not liquidatable — `(liqRemaining − w) > maintenanceMargin × notional`
105
+ *
106
+ * where
107
+ * notional = sizeInAsset × spotPrice
108
+ * effLeverage = effective collateral with projectedTradingFee = 0
109
+ * (the contract's leverage/min-coll checks ignore the closing fee and PnL)
110
+ * liqRemaining = grossCollateralUsd + signedPnl − borrow − trading − closingFee ∓ funding
111
+ * (the contract's `is_liquidatable` boundary; funding income is added back)
112
+ *
113
+ * The result is a USD figure (matching the "$X" the UI shows), already aligned so that
114
+ * converting it to raw collateral units with floor is abort-safe:
115
+ * `rawAmount = floor((maxReducibleUsd / collateralPriceUsd) * 10 ** collateralDecimal)`.
116
+ * The liquidation leg backs off one raw collateral unit because `is_liquidatable` aborts
117
+ * on `remaining <= maintenance` (inclusive) — the safe withdrawal must leave remaining
118
+ * *strictly* above maintenance. The leverage (`> max`) and min-collateral (`>=`) checks
119
+ * are equality-safe on their own and floor-rounding only adds margin, so they need no offset.
120
+ *
121
+ * Funding handling is signed (income added, expense subtracted) — a close approximation
122
+ * of the contract's deficit-aware sequencing, exact whenever the position is solvent
123
+ * (the only case where a withdrawal can succeed). Clamps at 0.
124
+ *
125
+ * @param maxLeverage Max leverage as a ratio (e.g. 25 for `max_leverage_bps` 250000).
126
+ * @param maintenanceMarginRate `maintenance_margin` as a fraction (e.g. 0.01 for 1%).
127
+ * @param minCollValueUsd `min_coll_value` in USD (raw scaled value ÷ 1e9).
128
+ * @param closingFeeUsd Full closing fee in USD (`close_fee` → USD).
129
+ * @param collateralPriceUsd Oracle price of the collateral token (USD per token).
130
+ * @param collateralDecimal Collateral token decimals — sets the smallest withdraw step.
131
+ */
132
+ export function calcMaxReducibleCollateralUsd(params) {
133
+ const { grossCollateralUsd, sizeInAsset, spotPrice, isLong, entryPrice, maxLeverage, maintenanceMarginRate, minCollValueUsd, borrowFeeUsd, tradingFeeUsd, closingFeeUsd, fundingSign, fundingFeeUsd, collateralPriceUsd, collateralDecimal, } = params;
134
+ const notional = sizeInAsset * spotPrice;
135
+ // effLeverage: matches calculate_effective_collateral_amount(..., projectedTradingFee = 0).
136
+ const effLeverage = calcEffectiveCollateralUsd({
137
+ grossCollateralUsd,
138
+ borrowFeeUsd,
139
+ fundingSign,
140
+ fundingFeeUsd,
141
+ tradingFeeUsd,
142
+ });
143
+ // (A) max leverage and (B) min collateral, both bounded by effLeverage. Both checks
144
+ // pass at equality (`leverage_bps > max` / `collateral >= min`), so no offset needed.
145
+ const leverageHeadroom = maxLeverage > 0 ? effLeverage - notional / maxLeverage : effLeverage;
146
+ const minCollHeadroom = effLeverage - minCollValueUsd;
147
+ // (C) is_liquidatable: aborts on `remaining <= maintenance`, so the post-withdrawal
148
+ // remaining must stay STRICTLY above maintenance. Back off one raw collateral unit (the
149
+ // smallest withdrawable step) so the floored raw amount can never land on equality.
150
+ const signedPnl = calcUnrealizedPnl(isLong, entryPrice, spotPrice, sizeInAsset);
151
+ const liqRemaining = grossCollateralUsd +
152
+ signedPnl -
153
+ borrowFeeUsd -
154
+ tradingFeeUsd -
155
+ closingFeeUsd -
156
+ (fundingSign ? fundingFeeUsd : -fundingFeeUsd);
157
+ const maintenanceUsd = maintenanceMarginRate * notional;
158
+ const oneRawUnitUsd = collateralPriceUsd > 0 ? collateralPriceUsd / 10 ** collateralDecimal : 0;
159
+ const liquidationHeadroom = liqRemaining - maintenanceUsd - oneRawUnitUsd;
160
+ return Math.max(0, Math.min(leverageHeadroom, minCollHeadroom, liquidationHeadroom));
161
+ }
62
162
  // ======== Impact fee ========
63
163
  /**
64
164
  * Cost integral used by the impact fee curve (internal helper).
@@ -46,20 +46,55 @@ export declare function updatePythPrices(tx: Transaction, client: WaterXClient,
46
46
  packageId: string;
47
47
  }): Promise<string[]>;
48
48
  /**
49
- * For a given ticker, build the collector feed aggregate chain that
50
- * refreshes the on-chain `Oracle` aggregator for that ticker.
49
+ * Aggregate one ticker's price into the shared `Oracle`: build a collector, feed
50
+ * every rule the ticker is configured for, then `aggregate`. The fed rule set must
51
+ * match the on-chain weighted set for the ticker — `aggregator::remove_outliers`
52
+ * aborts `EMissingPriceSource` if a weighted rule is missing from the collector:
51
53
  *
52
- * Caller must have first called `buildPythPriceUpdateCalls` /
53
- * `updatePythPrices` so the corresponding `PriceInfoObject` is fresh.
54
+ * - **Pyth** fed when `priceInfoObjectId` is supplied (i.e. the ticker has a
55
+ * `pyth_rule.feeds` entry). Caller must run the Pyth update first so the
56
+ * `PriceInfoObject` is fresh.
57
+ * - **Supra** — fed alongside Pyth when supra is enabled + wired (abstains on-chain
58
+ * for symbols it has no pair for).
59
+ * - **Constant** — fed when the ticker is a constant ticker
60
+ * ({@link WaterXClient.isConstantTicker}).
61
+ *
62
+ * "Dual-feed" (Pyth + Constant) and "constant-only" are not special cases — they
63
+ * fall out of which rules the ticker is in: a constant ticker that also has a Pyth
64
+ * feed gets both; one with no Pyth feed (no `priceInfoObjectId`) gets constant only.
65
+ * Throws if no rule applies to the ticker.
66
+ */
67
+ export declare function aggregateTicker(tx: Transaction, client: WaterXClient, args: {
68
+ ticker: string;
69
+ priceInfoObjectId?: string;
70
+ }): void;
71
+ /**
72
+ * Thin wrapper over {@link aggregateTicker} for a Pyth-fed ticker. Kept for
73
+ * back-compat (e.g. WLP mint builds). Caller must run the Pyth update first.
54
74
  */
55
75
  export declare function aggregateTickerWithPyth(tx: Transaction, client: WaterXClient, args: {
56
76
  ticker: string;
57
77
  priceInfoObjectId: string;
58
78
  }): void;
59
79
  /**
60
- * Refresh multiple tickers via Pyth in one PTB. Updates Pyth on-chain
61
- * first (one accumulator), then runs the collector → feed → aggregate
62
- * cycle for each ticker.
80
+ * {@link aggregateTicker} for a **constant-only** ticker (no Pyth update needed
81
+ * the price comes from the on-chain `constant_rule::Config`).
82
+ *
83
+ * Throws if the ticker ALSO has a `pyth_rule.feeds` entry (a dual-feed transition
84
+ * ticker): feeding only the constant leg would leave the still-weighted Pyth rule
85
+ * absent from the collector and abort `aggregate` with `EMissingPriceSource`. Such
86
+ * tickers must go through {@link aggregateTicker} with a `priceInfoObjectId` (or
87
+ * {@link refreshOraclePrices}), which feeds both.
88
+ */
89
+ export declare function aggregateTickerWithConstant(tx: Transaction, client: WaterXClient, args: {
90
+ ticker: string;
91
+ }): void;
92
+ /**
93
+ * Refresh multiple tickers in one PTB. For each ticker {@link aggregateTicker}
94
+ * feeds whichever rules it is configured for (Pyth if it has a `pyth_rule.feeds`
95
+ * entry, Supra when enabled, Constant when it's a constant ticker). Tickers with a
96
+ * Pyth feed are updated on-chain via one shared Pyth accumulator first; the rest
97
+ * (constant-only) skip Pyth entirely.
63
98
  */
64
99
  export declare function refreshOraclePrices(tx: Transaction, client: WaterXClient, tickers: string[], opts?: {
65
100
  cache?: PythCache;