perp-cli 0.12.17 → 0.14.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 (361) hide show
  1. package/README.md +247 -27
  2. package/dist/_stderr-filter.js +0 -1
  3. package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
  4. package/dist/agent-wallet/lighter-keystore.js +92 -10
  5. package/dist/agent-wallet/passphrase.d.ts +1 -1
  6. package/dist/agent-wallet/passphrase.js +16 -3
  7. package/dist/agent-wallet/store.d.ts +37 -4
  8. package/dist/agent-wallet/store.js +132 -0
  9. package/dist/agent-wallet/venue-keystore.d.ts +14 -0
  10. package/dist/agent-wallet/venue-keystore.js +121 -0
  11. package/dist/api/public/hyperliquid.js +4 -4
  12. package/dist/api/public/lighter.js +5 -5
  13. package/dist/api/public/pacifica.d.ts +0 -1
  14. package/dist/api/public/pacifica.js +4 -13
  15. package/dist/api/public/urls.d.ts +9 -1
  16. package/dist/api/public/urls.js +35 -13
  17. package/dist/arb/file-lock.d.ts +11 -0
  18. package/dist/arb/file-lock.js +74 -0
  19. package/dist/arb/index.d.ts +2 -2
  20. package/dist/arb/index.js +2 -2
  21. package/dist/arb/pending-entry.d.ts +32 -0
  22. package/dist/arb/pending-entry.js +77 -0
  23. package/dist/arb/sizing.d.ts +6 -13
  24. package/dist/arb/sizing.js +12 -51
  25. package/dist/arb/state.d.ts +45 -12
  26. package/dist/arb/state.js +214 -42
  27. package/dist/arb/utils.d.ts +20 -6
  28. package/dist/arb/utils.js +43 -39
  29. package/dist/bot/conditions.d.ts +4 -4
  30. package/dist/bot/conditions.js +11 -6
  31. package/dist/bot/config.d.ts +17 -1
  32. package/dist/bot/config.js +48 -12
  33. package/dist/bot/engine.d.ts +61 -2
  34. package/dist/bot/engine.js +610 -144
  35. package/dist/bot/fill-size.d.ts +7 -0
  36. package/dist/bot/fill-size.js +18 -0
  37. package/dist/bot/index.d.ts +1 -1
  38. package/dist/bot/index.js +1 -1
  39. package/dist/bot/perp-order.d.ts +99 -0
  40. package/dist/bot/perp-order.js +299 -0
  41. package/dist/bot/presets.d.ts +7 -0
  42. package/dist/bot/presets.js +17 -0
  43. package/dist/bot/quarantine.d.ts +75 -0
  44. package/dist/bot/quarantine.js +190 -0
  45. package/dist/bot/quote-rules.d.ts +23 -0
  46. package/dist/bot/quote-rules.js +69 -0
  47. package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
  48. package/dist/bot/strategies/avellaneda-mm.js +72 -70
  49. package/dist/bot/strategies/basis-arb.js +2 -0
  50. package/dist/bot/strategies/dca-strategy.d.ts +2 -0
  51. package/dist/bot/strategies/dca-strategy.js +5 -0
  52. package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
  53. package/dist/bot/strategies/funding-arb-strategy.js +571 -380
  54. package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
  55. package/dist/bot/strategies/funding-arb-utils.js +159 -195
  56. package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
  57. package/dist/bot/strategies/funding-arb-v2.js +258 -47
  58. package/dist/bot/strategies/funding-auto.js +215 -194
  59. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
  60. package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
  61. package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
  62. package/dist/bot/strategies/spot-perp-executor.js +319 -120
  63. package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
  64. package/dist/bot/strategies/spot-perp-state.js +70 -0
  65. package/dist/bot/strategy-types.d.ts +6 -0
  66. package/dist/bot/tui/BotDashboard.d.ts +7 -2
  67. package/dist/bot/tui/BotDashboard.js +6 -3
  68. package/dist/bridge-engine.d.ts +120 -19
  69. package/dist/bridge-engine.js +710 -422
  70. package/dist/bridge-signers.d.ts +54 -0
  71. package/dist/bridge-signers.js +161 -0
  72. package/dist/cache.d.ts +4 -1
  73. package/dist/cache.js +11 -0
  74. package/dist/cli-flags.d.ts +50 -0
  75. package/dist/cli-flags.js +104 -0
  76. package/dist/cli-program.d.ts +35 -0
  77. package/dist/cli-program.js +286 -0
  78. package/dist/cli-spec.js +1 -1
  79. package/dist/client-id-tracker.js +11 -2
  80. package/dist/commands/account.d.ts +7 -1
  81. package/dist/commands/account.js +70 -92
  82. package/dist/commands/agent-import.d.ts +114 -0
  83. package/dist/commands/agent-import.js +794 -0
  84. package/dist/commands/agent.d.ts +232 -2
  85. package/dist/commands/agent.js +1858 -955
  86. package/dist/commands/alerts.d.ts +1 -0
  87. package/dist/commands/alerts.js +31 -28
  88. package/dist/commands/arb/index.d.ts +60 -1
  89. package/dist/commands/arb/index.js +381 -384
  90. package/dist/commands/arb-auto.d.ts +132 -4
  91. package/dist/commands/arb-auto.js +1474 -967
  92. package/dist/commands/arb.d.ts +3 -1
  93. package/dist/commands/arb.js +62 -30
  94. package/dist/commands/bot.js +127 -47
  95. package/dist/commands/bridge.d.ts +2 -1
  96. package/dist/commands/bridge.js +339 -192
  97. package/dist/commands/builder.d.ts +55 -0
  98. package/dist/commands/builder.js +387 -0
  99. package/dist/commands/funds-onchain.d.ts +32 -0
  100. package/dist/commands/funds-onchain.js +286 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +939 -245
  103. package/dist/commands/history.js +72 -45
  104. package/dist/commands/init.d.ts +107 -15
  105. package/dist/commands/init.js +1116 -249
  106. package/dist/commands/jobs.d.ts +2 -1
  107. package/dist/commands/jobs.js +77 -15
  108. package/dist/commands/manage.js +136 -91
  109. package/dist/commands/market.d.ts +4 -1
  110. package/dist/commands/market.js +35 -32
  111. package/dist/commands/outcome.d.ts +10 -0
  112. package/dist/commands/outcome.js +396 -0
  113. package/dist/commands/plan.js +52 -12
  114. package/dist/commands/portfolio.d.ts +1 -0
  115. package/dist/commands/portfolio.js +60 -72
  116. package/dist/commands/rebalance.d.ts +2 -1
  117. package/dist/commands/rebalance.js +33 -43
  118. package/dist/commands/risk.js +46 -19
  119. package/dist/commands/settings.d.ts +1 -0
  120. package/dist/commands/settings.js +246 -51
  121. package/dist/commands/trade.d.ts +50 -0
  122. package/dist/commands/trade.js +1943 -695
  123. package/dist/commands/wallet.d.ts +30 -1
  124. package/dist/commands/wallet.js +316 -337
  125. package/dist/config.d.ts +60 -9
  126. package/dist/config.js +252 -82
  127. package/dist/constants.d.ts +29 -4
  128. package/dist/constants.js +62 -20
  129. package/dist/dashboard/server.d.ts +2 -0
  130. package/dist/dashboard/server.js +9 -6
  131. package/dist/dashboard/ui.js +6 -4
  132. package/dist/dashboard/ws-feeds.js +20 -8
  133. package/dist/dex-asset-map.js +5 -3
  134. package/dist/errors.d.ts +122 -0
  135. package/dist/errors.js +194 -0
  136. package/dist/event-stream.js +75 -19
  137. package/dist/evm-master-tx.d.ts +59 -0
  138. package/dist/evm-master-tx.js +154 -0
  139. package/dist/exchanges/adapter-network.d.ts +10 -0
  140. package/dist/exchanges/adapter-network.js +10 -0
  141. package/dist/exchanges/arcus/adapter.d.ts +196 -0
  142. package/dist/exchanges/arcus/adapter.js +1092 -0
  143. package/dist/exchanges/arcus/agent.d.ts +55 -0
  144. package/dist/exchanges/arcus/agent.js +188 -0
  145. package/dist/exchanges/arcus/client.d.ts +63 -0
  146. package/dist/exchanges/arcus/client.js +285 -0
  147. package/dist/exchanges/arcus/public.d.ts +65 -0
  148. package/dist/exchanges/arcus/public.js +138 -0
  149. package/dist/exchanges/arcus/signing.d.ts +176 -0
  150. package/dist/exchanges/arcus/signing.js +288 -0
  151. package/dist/exchanges/arcus/spot-chain.d.ts +60 -0
  152. package/dist/exchanges/arcus/spot-chain.js +241 -0
  153. package/dist/exchanges/arcus/spot-router.d.ts +177 -0
  154. package/dist/exchanges/arcus/spot-router.js +183 -0
  155. package/dist/exchanges/arcus/spot.d.ts +109 -0
  156. package/dist/exchanges/arcus/spot.js +645 -0
  157. package/dist/exchanges/aster-funds.d.ts +127 -0
  158. package/dist/exchanges/aster-funds.js +252 -0
  159. package/dist/exchanges/aster-nonce.d.ts +2 -0
  160. package/dist/exchanges/aster-nonce.js +107 -0
  161. package/dist/exchanges/aster-spot.d.ts +117 -0
  162. package/dist/exchanges/aster-spot.js +686 -0
  163. package/dist/exchanges/aster-typed-data.d.ts +133 -7
  164. package/dist/exchanges/aster-typed-data.js +121 -7
  165. package/dist/exchanges/aster.d.ts +219 -6
  166. package/dist/exchanges/aster.js +1023 -153
  167. package/dist/exchanges/builder-fee.d.ts +254 -0
  168. package/dist/exchanges/builder-fee.js +421 -0
  169. package/dist/exchanges/canonical-symbols.d.ts +32 -0
  170. package/dist/exchanges/canonical-symbols.js +96 -0
  171. package/dist/exchanges/capabilities.d.ts +7 -1
  172. package/dist/exchanges/capabilities.js +7 -0
  173. package/dist/exchanges/hl-signing.d.ts +165 -0
  174. package/dist/exchanges/hl-signing.js +158 -0
  175. package/dist/exchanges/hyperliquid-outcome.d.ts +211 -0
  176. package/dist/exchanges/hyperliquid-outcome.js +646 -0
  177. package/dist/exchanges/hyperliquid-spot.d.ts +44 -5
  178. package/dist/exchanges/hyperliquid-spot.js +308 -117
  179. package/dist/exchanges/hyperliquid.d.ts +462 -57
  180. package/dist/exchanges/hyperliquid.js +1575 -449
  181. package/dist/exchanges/index.d.ts +6 -0
  182. package/dist/exchanges/index.js +4 -0
  183. package/dist/exchanges/interface.d.ts +63 -10
  184. package/dist/exchanges/interface.js +18 -3
  185. package/dist/exchanges/ioc-outcome.d.ts +44 -0
  186. package/dist/exchanges/ioc-outcome.js +57 -0
  187. package/dist/exchanges/legacy-trading-v2.d.ts +39 -0
  188. package/dist/exchanges/legacy-trading-v2.js +940 -0
  189. package/dist/exchanges/lighter-public.d.ts +43 -0
  190. package/dist/exchanges/lighter-public.js +276 -0
  191. package/dist/exchanges/lighter-rh-deposit.d.ts +62 -0
  192. package/dist/exchanges/lighter-rh-deposit.js +185 -0
  193. package/dist/exchanges/lighter-signer.d.ts +123 -0
  194. package/dist/exchanges/lighter-signer.js +215 -0
  195. package/dist/exchanges/lighter-spot.d.ts +91 -13
  196. package/dist/exchanges/lighter-spot.js +595 -233
  197. package/dist/exchanges/lighter.d.ts +611 -39
  198. package/dist/exchanges/lighter.js +1890 -649
  199. package/dist/exchanges/ondo/adapter.d.ts +166 -0
  200. package/dist/exchanges/ondo/adapter.js +835 -0
  201. package/dist/exchanges/ondo/agent.d.ts +31 -0
  202. package/dist/exchanges/ondo/agent.js +101 -0
  203. package/dist/exchanges/ondo/client.d.ts +60 -0
  204. package/dist/exchanges/ondo/client.js +297 -0
  205. package/dist/exchanges/ondo/funds.d.ts +122 -0
  206. package/dist/exchanges/ondo/funds.js +290 -0
  207. package/dist/exchanges/ondo/public.d.ts +95 -0
  208. package/dist/exchanges/ondo/public.js +214 -0
  209. package/dist/exchanges/ondo/spot.d.ts +127 -0
  210. package/dist/exchanges/ondo/spot.js +392 -0
  211. package/dist/exchanges/outcome-interface.d.ts +140 -0
  212. package/dist/exchanges/outcome-interface.js +16 -0
  213. package/dist/exchanges/pacifica-spot.d.ts +83 -0
  214. package/dist/exchanges/pacifica-spot.js +324 -0
  215. package/dist/exchanges/pacifica-typed-data.d.ts +30 -13
  216. package/dist/exchanges/pacifica-typed-data.js +57 -9
  217. package/dist/exchanges/pacifica.d.ts +288 -4
  218. package/dist/exchanges/pacifica.js +1013 -76
  219. package/dist/exchanges/precision.d.ts +47 -0
  220. package/dist/exchanges/precision.js +209 -0
  221. package/dist/exchanges/qfex/adapter.d.ts +341 -0
  222. package/dist/exchanges/qfex/adapter.js +1383 -0
  223. package/dist/exchanges/qfex/agent.d.ts +58 -0
  224. package/dist/exchanges/qfex/agent.js +188 -0
  225. package/dist/exchanges/qfex/client.d.ts +54 -0
  226. package/dist/exchanges/qfex/client.js +138 -0
  227. package/dist/exchanges/qfex/errors.d.ts +70 -0
  228. package/dist/exchanges/qfex/errors.js +236 -0
  229. package/dist/exchanges/qfex/public.d.ts +122 -0
  230. package/dist/exchanges/qfex/public.js +268 -0
  231. package/dist/exchanges/qfex/signing.d.ts +160 -0
  232. package/dist/exchanges/qfex/signing.js +283 -0
  233. package/dist/exchanges/qfex/ws-transport.d.ts +294 -0
  234. package/dist/exchanges/qfex/ws-transport.js +798 -0
  235. package/dist/exchanges/rate-limiter.d.ts +12 -0
  236. package/dist/exchanges/rate-limiter.js +64 -0
  237. package/dist/exchanges/registry.d.ts +14 -2
  238. package/dist/exchanges/registry.js +20 -32
  239. package/dist/exchanges/slippage.d.ts +37 -0
  240. package/dist/exchanges/slippage.js +70 -0
  241. package/dist/exchanges/spot-factory.d.ts +166 -0
  242. package/dist/exchanges/spot-factory.js +431 -0
  243. package/dist/exchanges/spot-interface.d.ts +98 -4
  244. package/dist/exchanges/spot-interface.js +27 -1
  245. package/dist/exchanges/spot-result.d.ts +79 -0
  246. package/dist/exchanges/spot-result.js +273 -0
  247. package/dist/exchanges/trading-v2.d.ts +117 -0
  248. package/dist/exchanges/trading-v2.js +301 -0
  249. package/dist/exchanges/venue-types.d.ts +231 -0
  250. package/dist/exchanges/venue-types.js +87 -0
  251. package/dist/exchanges/venue.d.ts +211 -0
  252. package/dist/exchanges/venue.js +132 -0
  253. package/dist/exchanges/venues/arcus.d.ts +8 -0
  254. package/dist/exchanges/venues/arcus.js +109 -0
  255. package/dist/exchanges/venues/aster.d.ts +49 -0
  256. package/dist/exchanges/venues/aster.js +176 -0
  257. package/dist/exchanges/venues/create-helpers.d.ts +18 -0
  258. package/dist/exchanges/venues/create-helpers.js +199 -0
  259. package/dist/exchanges/venues/hyperliquid.d.ts +23 -0
  260. package/dist/exchanges/venues/hyperliquid.js +126 -0
  261. package/dist/exchanges/venues/index.d.ts +16 -0
  262. package/dist/exchanges/venues/index.js +26 -0
  263. package/dist/exchanges/venues/lighter-family.d.ts +92 -0
  264. package/dist/exchanges/venues/lighter-family.js +166 -0
  265. package/dist/exchanges/venues/lighter-rh.d.ts +7 -0
  266. package/dist/exchanges/venues/lighter-rh.js +58 -0
  267. package/dist/exchanges/venues/lighter.d.ts +6 -0
  268. package/dist/exchanges/venues/lighter.js +55 -0
  269. package/dist/exchanges/venues/ondo.d.ts +34 -0
  270. package/dist/exchanges/venues/ondo.js +140 -0
  271. package/dist/exchanges/venues/pacifica.d.ts +8 -0
  272. package/dist/exchanges/venues/pacifica.js +95 -0
  273. package/dist/exchanges/venues/qfex.d.ts +28 -0
  274. package/dist/exchanges/venues/qfex.js +132 -0
  275. package/dist/execution-log.js +10 -2
  276. package/dist/funding/legacy-public.d.ts +31 -0
  277. package/dist/funding/legacy-public.js +369 -0
  278. package/dist/funding/normalize.d.ts +28 -16
  279. package/dist/funding/normalize.js +61 -29
  280. package/dist/funding/rates.d.ts +46 -11
  281. package/dist/funding/rates.js +228 -277
  282. package/dist/guardrail/perp-guardrail.js +0 -0
  283. package/dist/index.js +156 -684
  284. package/dist/jobs.d.ts +84 -6
  285. package/dist/jobs.js +239 -41
  286. package/dist/landing.d.ts +7 -2
  287. package/dist/landing.js +19 -3
  288. package/dist/mcp-server.d.ts +14 -4
  289. package/dist/mcp-server.js +820 -402
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/pacifica/client.d.ts +41 -10
  293. package/dist/pacifica/client.js +167 -63
  294. package/dist/pacifica/constants.d.ts +0 -1
  295. package/dist/pacifica/constants.js +0 -5
  296. package/dist/pacifica/deposit.d.ts +30 -3
  297. package/dist/pacifica/deposit.js +119 -2
  298. package/dist/pacifica/faucet.d.ts +29 -0
  299. package/dist/pacifica/faucet.js +100 -0
  300. package/dist/pacifica/sign-tx.d.ts +15 -0
  301. package/dist/pacifica/sign-tx.js +41 -0
  302. package/dist/pacifica/types/account.d.ts +28 -4
  303. package/dist/pacifica/types/lake.d.ts +20 -5
  304. package/dist/pacifica/types/lake.js +4 -0
  305. package/dist/pacifica/types/market.d.ts +5 -0
  306. package/dist/pacifica/types/order.d.ts +4 -1
  307. package/dist/pacifica/types/position.d.ts +9 -1
  308. package/dist/plan-executor.d.ts +10 -5
  309. package/dist/plan-executor.js +165 -54
  310. package/dist/position-history.js +13 -0
  311. package/dist/rebalance.d.ts +26 -2
  312. package/dist/rebalance.js +86 -7
  313. package/dist/relay-swap.d.ts +232 -0
  314. package/dist/relay-swap.js +630 -0
  315. package/dist/risk.js +5 -1
  316. package/dist/secret-env.d.ts +15 -0
  317. package/dist/secret-env.js +36 -0
  318. package/dist/settings.d.ts +169 -6
  319. package/dist/settings.js +219 -38
  320. package/dist/signer/ows-evm.d.ts +13 -0
  321. package/dist/signer/ows-evm.js +22 -0
  322. package/dist/smart-order.d.ts +9 -0
  323. package/dist/smart-order.js +53 -8
  324. package/dist/strategies/dca.d.ts +6 -2
  325. package/dist/strategies/dca.js +66 -26
  326. package/dist/strategies/funding-arb.d.ts +11 -1
  327. package/dist/strategies/funding-arb.js +202 -89
  328. package/dist/strategies/grid.d.ts +31 -0
  329. package/dist/strategies/grid.js +89 -11
  330. package/dist/strategies/pending-stop.d.ts +8 -0
  331. package/dist/strategies/pending-stop.js +12 -0
  332. package/dist/strategies/split-order.d.ts +45 -17
  333. package/dist/strategies/split-order.js +157 -91
  334. package/dist/strategies/trailing-stop.d.ts +2 -1
  335. package/dist/strategies/trailing-stop.js +52 -6
  336. package/dist/strategies/twap.d.ts +6 -1
  337. package/dist/strategies/twap.js +39 -11
  338. package/dist/trade-validator.d.ts +22 -0
  339. package/dist/trade-validator.js +119 -15
  340. package/dist/utils/numeric.d.ts +46 -0
  341. package/dist/utils/numeric.js +79 -0
  342. package/dist/utils.d.ts +19 -0
  343. package/dist/utils.js +96 -19
  344. package/dist/withdraw-gate.d.ts +49 -0
  345. package/dist/withdraw-gate.js +131 -0
  346. package/package.json +15 -6
  347. package/skills/perp-cli/SKILL.md +142 -55
  348. package/skills/perp-cli/references/agent-operations.md +110 -56
  349. package/skills/perp-cli/references/commands.md +266 -71
  350. package/skills/perp-cli/references/strategies.md +34 -31
  351. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  352. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  353. package/skills/perp-cli/scripts/preflight.sh +21 -14
  354. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  355. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  356. package/vendor/lighter-signer/SHA256SUMS +2 -0
  357. package/vendor/lighter-signer/VERSION +8 -0
  358. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  359. package/vendor/lighter-signer/wasm_exec.js +575 -0
  360. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  361. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -68,7 +68,7 @@ export interface ApproveAgentParams {
68
68
  builderName?: string;
69
69
  /** Microsecond-precision nonce (Date.now() * 1000 + counter). Serialized as decimal string. */
70
70
  nonceMicros: number | string;
71
- asterChain?: AsterChain;
71
+ asterChain: AsterChain;
72
72
  }
73
73
  /**
74
74
  * Build the EIP-712 typed-data payload for `POST /fapi/v3/approveAgent`.
@@ -90,15 +90,19 @@ export interface DelAgentParams {
90
90
  user: `0x${string}`;
91
91
  agentAddress: `0x${string}`;
92
92
  nonceMicros: number | string;
93
- asterChain?: AsterChain;
93
+ asterChain: AsterChain;
94
94
  }
95
95
  /**
96
96
  * Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
97
97
  *
98
- * TODO: confirm DelAgent struct vs Aster docs at Step 0b spike.
99
- * HypurrQuant_FE does not implement a revoke/delAgent method — this is a
100
- * best-effort field set mirroring the ApproveAgent terminal fields (AgentAddress,
101
- * AsterChain, User, Nonce) without the permission booleans.
98
+ * OPEN ITEM (docs/TEST-PLAN.md "Aster DelAgent struct — mainnet verification"): the
99
+ * public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
100
+ * document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
101
+ * revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
102
+ * AsterChain, User, Nonce) without the permission booleans. It is only reachable on
103
+ * mainnet (assertAgentApproveSupported refuses Aster agent management on testnet), and
104
+ * revoke treats any non-confirming venue response as APPROVE_FAILED (assertAsterAgentDeleted),
105
+ * so a wrong struct fails loudly instead of reporting a false revoke.
102
106
  */
103
107
  export declare function buildDelAgentTypedData(params: DelAgentParams): {
104
108
  domain: typeof ASTER_DOMAIN_A;
@@ -143,7 +147,7 @@ export interface ApproveBuilderParams {
143
147
  builderName?: string;
144
148
  user: `0x${string}`;
145
149
  nonceMicros: number | string;
146
- asterChain?: AsterChain;
150
+ asterChain: AsterChain;
147
151
  }
148
152
  /**
149
153
  * Build the EIP-712 typed-data payload for `POST /fapi/v3/approveBuilder`.
@@ -166,4 +170,126 @@ export declare function buildApproveBuilderTypedData(params: ApproveBuilderParam
166
170
  primaryType: "ApproveBuilder";
167
171
  message: Record<string, unknown>;
168
172
  };
173
+ export interface DelBuilderParams {
174
+ builder: string;
175
+ user: `0x${string}`;
176
+ nonceMicros: number | string;
177
+ asterChain: AsterChain;
178
+ }
179
+ /**
180
+ * EIP-712 payload for `DELETE /fapi/v3/builder` (revoke a builder approval).
181
+ * Source: asterdex/api-docs demo/aster-code.py `delBuilder` — main-wallet signed,
182
+ * primaryType "DelBuilder", fields = the request params with the first letter
183
+ * upper-cased in insertion order: Builder, AsterChain, User, Nonce (Domain A).
184
+ */
185
+ export declare function buildDelBuilderTypedData(params: DelBuilderParams): {
186
+ domain: typeof ASTER_DOMAIN_A;
187
+ types: {
188
+ DelBuilder: Eip712Field[];
189
+ };
190
+ primaryType: "DelBuilder";
191
+ message: Record<string, unknown>;
192
+ };
193
+ /** signatureChainId for an EVM `user` on POST /fapi/v3/registerAndApproveAgent (101 = Solana). */
194
+ export declare const ASTER_REGISTER_AGENT_EVM_CHAIN_ID = 56;
195
+ export interface RegisterAndApproveAgentParams {
196
+ user: `0x${string}`;
197
+ /** Microsecond timestamp; server tolerance ±10 s, never reused. */
198
+ nonceMicros: number | string;
199
+ agentName: string;
200
+ agentAddress: `0x${string}`;
201
+ /** Agent expiry, Unix milliseconds. */
202
+ expiredMs: number | string;
203
+ signatureChainId: number;
204
+ canSpotTrade: boolean;
205
+ canPerpTrade: boolean;
206
+ canWithdraw: boolean;
207
+ /** Space-delimited IPs / CIDRs; "" when none. Must be non-empty when canWithdraw. */
208
+ ipWhitelist: string;
209
+ }
210
+ /**
211
+ * EIP-712 payload for `POST /fapi/v3/registerAndApproveAgent` (asterdex/api-docs
212
+ * eeddec8, V3 futures v3 + testnet, added 2026-05-12). Unauthenticated endpoint;
213
+ * the user's wallet signs the literal (not URL-encoded) parameter string
214
+ * user=…&nonce=…&agentName=…&agentAddress=…&expired=…&signatureChainId=…&canSpotTrade=…&canPerpTrade=…&canWithdraw=…&ipWhitelist=…
215
+ * wrapped as Message{msg} under domain AsterSignTransaction / v1 / chainId =
216
+ * signatureChainId (56 for EVM) / zero verifyingContract. Unlike approveAgent
217
+ * this carries no AsterChain field — the host selects the network.
218
+ */
219
+ export declare function buildRegisterAndApproveAgentTypedData(params: RegisterAndApproveAgentParams): {
220
+ domain: {
221
+ name: string;
222
+ version: string;
223
+ chainId: number;
224
+ verifyingContract: string;
225
+ };
226
+ types: typeof ORDER_TYPES;
227
+ primaryType: "Message";
228
+ message: {
229
+ msg: string;
230
+ };
231
+ /** Request parameters in signing order (the caller appends `signature`). */
232
+ params: [string, string][];
233
+ };
234
+ /** EIP-712 types of the EVM withdraw signature (field names contain spaces — they are part of the type hash). */
235
+ export declare const ASTER_WITHDRAW_TYPES: {
236
+ readonly Action: readonly [{
237
+ readonly name: "type";
238
+ readonly type: "string";
239
+ }, {
240
+ readonly name: "destination";
241
+ readonly type: "address";
242
+ }, {
243
+ readonly name: "destination Chain";
244
+ readonly type: "string";
245
+ }, {
246
+ readonly name: "token";
247
+ readonly type: "string";
248
+ }, {
249
+ readonly name: "amount";
250
+ readonly type: "string";
251
+ }, {
252
+ readonly name: "fee";
253
+ readonly type: "string";
254
+ }, {
255
+ readonly name: "nonce";
256
+ readonly type: "uint256";
257
+ }, {
258
+ readonly name: "aster chain";
259
+ readonly type: "string";
260
+ }];
261
+ };
262
+ export interface WithdrawTypedDataParams {
263
+ /** Destination chain id — also the EIP-712 domain chainId (docs: "The chainId of the withdraw chain"). */
264
+ chainId: number;
265
+ /** `destination Chain` name: 1 → "ETH", 56 → "BSC", 42161 → "Arbitrum". */
266
+ chainName: string;
267
+ /** Receipt address — the account's own registered address. */
268
+ receiver: string;
269
+ /** Currency name, e.g. "USDT". */
270
+ asset: string;
271
+ /** Amount in token units, the SAME string sent as the `amount` request param. */
272
+ amount: string;
273
+ /** Fee in token units, the SAME string sent as the `fee` request param. */
274
+ fee: string;
275
+ /** ms timestamp × 1000, decimal string; sent as the `userNonce` request param. */
276
+ userNonce: string;
277
+ }
278
+ /**
279
+ * Master-signed EVM withdraw signature (`userSignature` of POST /fapi/v3/aster/user-withdraw).
280
+ * Source: asterdex/api-docs demo/aster-deposit-withdrawal.md "EVM Withdraw Signature" and
281
+ * asterdex/API-demo futures-v3-demo/58_withdrawEvm.js. Domain name "Aster" (NOT the
282
+ * "AsterSignTransaction" API-auth domain); `aster chain` is the fixed string "Mainnet".
283
+ */
284
+ export declare function buildWithdrawTypedData(p: WithdrawTypedDataParams): {
285
+ domain: {
286
+ name: "Aster";
287
+ version: "1";
288
+ chainId: number;
289
+ verifyingContract: string;
290
+ };
291
+ types: typeof ASTER_WITHDRAW_TYPES;
292
+ primaryType: "Action";
293
+ message: Record<string, string>;
294
+ };
169
295
  export {};
@@ -11,6 +11,7 @@
11
11
  * - uint256 fields serialized as decimal strings (never BigInt) to survive JSON.stringify
12
12
  * - EIP-712 message keys are PascalCase; HTTP query-string keys are camelCase
13
13
  */
14
+ import { PerpError } from "../errors.js";
14
15
  // ── Domain constants ──────────────────────────────────────────────────────────
15
16
  /** Domain A: used for master-signed ops (ApproveAgent, DelAgent, ApproveBuilder). */
16
17
  export const ASTER_DOMAIN_A = {
@@ -85,7 +86,7 @@ export function buildApproveAgentTypedData(params) {
85
86
  message["BuilderName"] = params.builderName;
86
87
  }
87
88
  }
88
- message["AsterChain"] = params.asterChain ?? "Mainnet";
89
+ message["AsterChain"] = params.asterChain;
89
90
  message["User"] = params.user;
90
91
  message["Nonce"] = String(params.nonceMicros);
91
92
  return {
@@ -98,10 +99,14 @@ export function buildApproveAgentTypedData(params) {
98
99
  /**
99
100
  * Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
100
101
  *
101
- * TODO: confirm DelAgent struct vs Aster docs at Step 0b spike.
102
- * HypurrQuant_FE does not implement a revoke/delAgent method — this is a
103
- * best-effort field set mirroring the ApproveAgent terminal fields (AgentAddress,
104
- * AsterChain, User, Nonce) without the permission booleans.
102
+ * OPEN ITEM (docs/TEST-PLAN.md "Aster DelAgent struct — mainnet verification"): the
103
+ * public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
104
+ * document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
105
+ * revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
106
+ * AsterChain, User, Nonce) without the permission booleans. It is only reachable on
107
+ * mainnet (assertAgentApproveSupported refuses Aster agent management on testnet), and
108
+ * revoke treats any non-confirming venue response as APPROVE_FAILED (assertAsterAgentDeleted),
109
+ * so a wrong struct fails loudly instead of reporting a false revoke.
105
110
  */
106
111
  export function buildDelAgentTypedData(params) {
107
112
  const delTypes = [
@@ -112,7 +117,7 @@ export function buildDelAgentTypedData(params) {
112
117
  ];
113
118
  const message = {
114
119
  AgentAddress: params.agentAddress,
115
- AsterChain: params.asterChain ?? "Mainnet",
120
+ AsterChain: params.asterChain,
116
121
  User: params.user,
117
122
  Nonce: String(params.nonceMicros),
118
123
  };
@@ -190,7 +195,7 @@ export function buildApproveBuilderTypedData(params) {
190
195
  if (params.builderName !== undefined) {
191
196
  message["BuilderName"] = params.builderName;
192
197
  }
193
- message["AsterChain"] = params.asterChain ?? "Mainnet";
198
+ message["AsterChain"] = params.asterChain;
194
199
  message["User"] = params.user;
195
200
  message["Nonce"] = String(params.nonceMicros);
196
201
  return {
@@ -200,3 +205,112 @@ export function buildApproveBuilderTypedData(params) {
200
205
  message,
201
206
  };
202
207
  }
208
+ /**
209
+ * EIP-712 payload for `DELETE /fapi/v3/builder` (revoke a builder approval).
210
+ * Source: asterdex/api-docs demo/aster-code.py `delBuilder` — main-wallet signed,
211
+ * primaryType "DelBuilder", fields = the request params with the first letter
212
+ * upper-cased in insertion order: Builder, AsterChain, User, Nonce (Domain A).
213
+ */
214
+ export function buildDelBuilderTypedData(params) {
215
+ return {
216
+ domain: ASTER_DOMAIN_A,
217
+ types: {
218
+ DelBuilder: [
219
+ { name: "Builder", type: "string" },
220
+ { name: "AsterChain", type: "string" },
221
+ { name: "User", type: "string" },
222
+ { name: "Nonce", type: "uint256" },
223
+ ],
224
+ },
225
+ primaryType: "DelBuilder",
226
+ message: { Builder: params.builder, AsterChain: params.asterChain, User: params.user, Nonce: String(params.nonceMicros) },
227
+ };
228
+ }
229
+ // ── buildRegisterAndApproveAgentTypedData ─────────────────────────────────────
230
+ /** signatureChainId for an EVM `user` on POST /fapi/v3/registerAndApproveAgent (101 = Solana). */
231
+ export const ASTER_REGISTER_AGENT_EVM_CHAIN_ID = 56;
232
+ /**
233
+ * EIP-712 payload for `POST /fapi/v3/registerAndApproveAgent` (asterdex/api-docs
234
+ * eeddec8, V3 futures v3 + testnet, added 2026-05-12). Unauthenticated endpoint;
235
+ * the user's wallet signs the literal (not URL-encoded) parameter string
236
+ * user=…&nonce=…&agentName=…&agentAddress=…&expired=…&signatureChainId=…&canSpotTrade=…&canPerpTrade=…&canWithdraw=…&ipWhitelist=…
237
+ * wrapped as Message{msg} under domain AsterSignTransaction / v1 / chainId =
238
+ * signatureChainId (56 for EVM) / zero verifyingContract. Unlike approveAgent
239
+ * this carries no AsterChain field — the host selects the network.
240
+ */
241
+ export function buildRegisterAndApproveAgentTypedData(params) {
242
+ if (params.canWithdraw && params.ipWhitelist.trim().length === 0) {
243
+ throw new PerpError("INVALID_PARAMS", "Aster registerAndApproveAgent requires an IP whitelist when withdraw permission is granted", {
244
+ remediation: "Pass --ip-whitelist \"<ip> <ip/cidr>\" (space-separated), or drop --can-withdraw",
245
+ });
246
+ }
247
+ for (const [k, v] of [["agentName", params.agentName], ["ipWhitelist", params.ipWhitelist]]) {
248
+ // The signed msg is a raw k=v&… string — a '&' or '=' inside a value would make it ambiguous.
249
+ if (/[&=]/.test(v)) {
250
+ throw new PerpError("INVALID_PARAMS", `Aster registerAndApproveAgent: ${k} must not contain '&' or '='`, {
251
+ remediation: k === "agentName" ? "Choose an --agent-name without '&' or '='" : "Separate IP whitelist entries with spaces",
252
+ });
253
+ }
254
+ }
255
+ const entries = [
256
+ ["user", params.user],
257
+ ["nonce", String(params.nonceMicros)],
258
+ ["agentName", params.agentName],
259
+ ["agentAddress", params.agentAddress],
260
+ ["expired", String(params.expiredMs)],
261
+ ["signatureChainId", String(params.signatureChainId)],
262
+ ["canSpotTrade", String(params.canSpotTrade)],
263
+ ["canPerpTrade", String(params.canPerpTrade)],
264
+ ["canWithdraw", String(params.canWithdraw)],
265
+ ["ipWhitelist", params.ipWhitelist],
266
+ ];
267
+ return {
268
+ domain: {
269
+ name: "AsterSignTransaction",
270
+ version: "1",
271
+ chainId: params.signatureChainId,
272
+ verifyingContract: "0x0000000000000000000000000000000000000000",
273
+ },
274
+ types: ORDER_TYPES,
275
+ primaryType: "Message",
276
+ message: { msg: entries.map(([k, v]) => `${k}=${v}`).join("&") },
277
+ params: entries,
278
+ };
279
+ }
280
+ // ── buildWithdrawTypedData ────────────────────────────────────────────────────
281
+ /** EIP-712 types of the EVM withdraw signature (field names contain spaces — they are part of the type hash). */
282
+ export const ASTER_WITHDRAW_TYPES = {
283
+ Action: [
284
+ { name: "type", type: "string" },
285
+ { name: "destination", type: "address" },
286
+ { name: "destination Chain", type: "string" },
287
+ { name: "token", type: "string" },
288
+ { name: "amount", type: "string" },
289
+ { name: "fee", type: "string" },
290
+ { name: "nonce", type: "uint256" },
291
+ { name: "aster chain", type: "string" },
292
+ ],
293
+ };
294
+ /**
295
+ * Master-signed EVM withdraw signature (`userSignature` of POST /fapi/v3/aster/user-withdraw).
296
+ * Source: asterdex/api-docs demo/aster-deposit-withdrawal.md "EVM Withdraw Signature" and
297
+ * asterdex/API-demo futures-v3-demo/58_withdrawEvm.js. Domain name "Aster" (NOT the
298
+ * "AsterSignTransaction" API-auth domain); `aster chain` is the fixed string "Mainnet".
299
+ */
300
+ export function buildWithdrawTypedData(p) {
301
+ return {
302
+ domain: { name: "Aster", version: "1", chainId: p.chainId, verifyingContract: "0x0000000000000000000000000000000000000000" },
303
+ types: ASTER_WITHDRAW_TYPES,
304
+ primaryType: "Action",
305
+ message: {
306
+ "type": "Withdraw",
307
+ "destination": p.receiver,
308
+ "destination Chain": p.chainName,
309
+ "token": p.asset,
310
+ "amount": p.amount,
311
+ "fee": p.fee,
312
+ "nonce": p.userNonce,
313
+ "aster chain": "Mainnet",
314
+ },
315
+ };
316
+ }
@@ -19,9 +19,40 @@
19
19
  * Base: https://fapi.asterdex.com
20
20
  */
21
21
  import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
22
+ import type { ResolvedSlippage } from "./slippage.js";
22
23
  import type { EvmSigner } from "../signer/interface.js";
23
24
  import type { AgentMeta } from "../settings.js";
24
25
  import type { AgentSigningStrategy } from "../agent-wallet/signing-strategy.js";
26
+ import { PerpError } from "../errors.js";
27
+ import { type BuilderApproval, type BuilderDecision, type BuilderFeeGate, type BuilderTarget } from "./builder-fee.js";
28
+ import { type AsterFundsChain } from "./venues/aster.js";
29
+ import { type AsterWithdrawLimits, type AsterWithdrawResult } from "./aster-funds.js";
30
+ /**
31
+ * Definite IOC outcome of a raw Aster order response (perp and spot share the
32
+ * Binance-compatible shape) — contract in ./ioc-outcome.ts. Final only for a terminal
33
+ * status (FILLED / EXPIRED / CANCELED) with a reported executedQty, on an IOC (or
34
+ * MARKET) order; anything else → null (caller measures).
35
+ */
36
+ export declare function asterIocOutcome(raw: unknown): {
37
+ filledSize: string;
38
+ final: true;
39
+ } | null;
40
+ /**
41
+ * Verdict of a failed POST / PUT /fapi/v3/order that the venue ANSWERED with an HTTP 4xx and a
42
+ * documented error code: the order was refused — a definite, non-retryable PerpError (never the
43
+ * retryable EXCHANGE_ERROR, which callers must treat as an unknown write outcome). Live mainnet
44
+ * 2026-10-05: a reduce-only order without a position → 400 {"code":-2022,"msg":"ReduceOnly Order
45
+ * is rejected."}. Unchanged: HTTP 5xx, no / undocumented code, and the "status unknown" codes —
46
+ * those become ORDER_PENDING unless the error was already classified definite (e.g. the venue's
47
+ * -1000 "Signature check failed" → SIGNATURE_FAILED).
48
+ */
49
+ export declare function asterOrderRejection(e: PerpError): PerpError;
50
+ /**
51
+ * An Aster client order id as sent / queried. V3 futures "New Order" `newClientOrderId`: "A unique
52
+ * id among open orders. Automatically generated if not sent. Can only be string following the
53
+ * rule: ^[\.A-Z\:/a-z0-9_-]{1,36}$". Anything else → INVALID_PARAMS, nothing sent.
54
+ */
55
+ export declare function requireAsterClientOrderId(id: string): string;
25
56
  type ResolvedSigner = {
26
57
  tier: "agent" | "master" | "pk";
27
58
  signer: EvmSigner | AgentSigningStrategy;
@@ -46,27 +77,108 @@ export declare class AsterAdapter implements ExchangeAdapter {
46
77
  private _marketsCache;
47
78
  private _marketsCacheTime;
48
79
  private _fundingHoursCache;
80
+ /** When the venue-wide funding-interval table was last loaded (0 = never). */
81
+ private _fundingInfoLoadedAt;
82
+ /** API symbol → price filters; null = listed but PRICE_FILTER / PERCENT_PRICE unreadable. */
83
+ private _priceFilters;
84
+ private _priceFiltersLoadedAt;
49
85
  private _accountCache;
50
86
  private _positionsCache;
51
87
  private _ordersCache;
52
88
  private static readonly CACHE_TTL;
53
89
  private static readonly ACCOUNT_CACHE_TTL;
54
- private _nonceCounter;
90
+ /**
91
+ * Builder-fee gate (settings builder.aster + confirmed master approveBuilder); null = not
92
+ * configured. Set by createAster — the adapter never reads settings.
93
+ */
94
+ builderFee: BuilderFeeGate | null;
55
95
  constructor(privateKey?: string, testnet?: boolean);
56
96
  init(): Promise<void>;
57
97
  setAgent(meta: AgentMeta, strategy: AgentSigningStrategy): void;
58
98
  setMasterSigner(signer: EvmSigner): void;
59
99
  setPkSigner(signer: EvmSigner): void;
60
100
  setNoAgent(noAgent: boolean): void;
101
+ /** Builder decision for the next perp order (cached approval read; never throws). */
102
+ builderDecision(): Promise<BuilderDecision>;
103
+ /** `builder` + `feeRate` (decimal) order params, or none (not configured / not approved). */
104
+ private _builderParams;
105
+ /** Owner (`user`) address of the active signer — the account a builder approval belongs to. */
106
+ get userAddress(): string;
107
+ /**
108
+ * Builder approvals of this account: GET /fapi/v3/builder (asterdex/api-docs demo
109
+ * `getBuilders`, signed by the API wallet). The response shape is not documented, so
110
+ * anything but a list of rows carrying an address + maxFeeRate is "unknown" (never guessed).
111
+ */
112
+ builderApprovalOf(target: BuilderTarget): Promise<BuilderApproval>;
61
113
  get isReadOnly(): boolean;
62
114
  get activeSignerTier(): "agent" | "master" | "pk" | null;
115
+ /**
116
+ * Aster spot REST host. Spot shares the perp EIP-712 Domain B signing
117
+ * (chainId 1666 mainnet / 714 testnet) and the per-agent nonce space.
118
+ * Hosts per the official spot V3 docs (mainnet + testnet variants).
119
+ */
120
+ get spotBaseUrl(): string;
121
+ /**
122
+ * Signed request against an arbitrary Aster host with the active signer.
123
+ * POST is single-shot; GET/DELETE use the same 429 retry loop as perp.
124
+ */
125
+ signedRequest(host: string, method: "GET" | "POST" | "DELETE", path: string, params: Record<string, string | number | boolean>): Promise<unknown>;
126
+ /**
127
+ * Agent meta of the active signer, or null when the active signer is not an
128
+ * agent. Throws exactly like signed calls when no signer is usable.
129
+ */
130
+ activeAgentMeta(): AgentMeta | null;
63
131
  /** CLI symbol → Aster API symbol (ETH → ETHUSDT) */
64
132
  private _toApi;
65
133
  /** Aster API symbol → CLI symbol (ETHUSDT → ETH) */
66
134
  private _fromApi;
67
- /** Get funding interval for a symbol (lazy bootstrap). */
135
+ /**
136
+ * Get funding interval for a symbol.
137
+ *
138
+ * Source of truth is `GET /fapi/v3/fundingInfo` (weight 1), which states
139
+ * `fundingIntervalHours` per symbol for the whole venue in a single call.
140
+ * This previously inferred the interval by differencing the last two
141
+ * `fundingRate` timestamps and bucketing to 1/4/8h — an estimate that is
142
+ * wrong for a newly listed symbol (fewer than two settlements), across a
143
+ * schedule change, or whenever a settlement is skipped/delayed, and Aster
144
+ * really does mix 1h, 4h and 8h symbols. Funding-interval misconfiguration is
145
+ * exactly what produced the v0.7.23 Aster funding bug, so it is read, not
146
+ * guessed.
147
+ */
68
148
  getFundingHours(symbol: string): Promise<number | undefined>;
149
+ /** Populate the funding-interval cache for every symbol in one call. */
150
+ private _loadFundingInfo;
69
151
  getMarkets(): Promise<ExchangeMarketInfo[]>;
152
+ /** Parse PRICE_FILTER + PERCENT_PRICE for every exchangeInfo symbol into the cache. */
153
+ private _ingestPriceFilters;
154
+ /** PRICE_FILTER / PERCENT_PRICE of an API symbol (exchangeInfo, cached CACHE_TTL). */
155
+ private _symbolPriceFilters;
156
+ /**
157
+ * Declared protection-price reference (§13.10 #5): the venue mark price from
158
+ * GET /fapi/v3/premiumIndex — the same price PERCENT_PRICE is evaluated against.
159
+ * No runtime substitute (no mid / last fallback): unavailable → PRICE_STALE.
160
+ */
161
+ referencePrice(symbol: string): Promise<string>;
162
+ /**
163
+ * Reject (never clamp) a price outside PRICE_FILTER min/max or the side's PERCENT_PRICE
164
+ * bound around `mark` — checked before anything is sent.
165
+ */
166
+ private _checkPriceBand;
167
+ /**
168
+ * Protection price an IOC market order on `symbol` would be sent with now:
169
+ * mark ± slippage.bps, aligned toward crossing on PRICE_FILTER.tickSize, validated
170
+ * against PRICE_FILTER / PERCENT_PRICE. appliedBps = the bound after tick alignment.
171
+ */
172
+ computeProtectionPrice(symbol: string, side: "buy" | "sell", slippage: ResolvedSlippage): Promise<{
173
+ referencePrice: string;
174
+ protectionPrice: string;
175
+ appliedBps: number;
176
+ }>;
177
+ /** Definite IOC outcome of a raw order response (see asterIocOutcome). */
178
+ iocOutcomeOf(raw: unknown): {
179
+ filledSize: string;
180
+ final: true;
181
+ } | null;
70
182
  getOrderbook(symbol: string): Promise<{
71
183
  bids: [string, string][];
72
184
  asks: [string, string][];
@@ -79,30 +191,120 @@ export declare class AsterAdapter implements ExchangeAdapter {
79
191
  }[]>;
80
192
  getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
81
193
  getBalance(): Promise<ExchangeBalance>;
194
+ /**
195
+ * How much of ONE asset the perp account can transfer out: that asset's row of
196
+ * GET /fapi/v3/accountWithJoinMargin `assets[]` — `maxWithdrawAmount` ("maximum amount for
197
+ * transfer out", Aster futures API v3 "Account Information v3"). The account-level
198
+ * `availableBalance` (getBalance) is margin across ALL collateral assets in multi-asset mode
199
+ * and is not an amount of any one asset. Read uncached. A missing row / field is an error,
200
+ * never 0.
201
+ */
202
+ getPerpAssetTransferable(asset: string): Promise<number>;
82
203
  getPositions(): Promise<ExchangePosition[]>;
204
+ /**
205
+ * Drop the in-process open-orders snapshot (after any order write, or before a verifying
206
+ * re-list). An order write also changes positions and balances, so those snapshots go too.
207
+ */
208
+ invalidateOpenOrdersCache(): void;
83
209
  getOpenOrders(): Promise<ExchangeOrder[]>;
84
210
  getOrderHistory(limit?: number): Promise<ExchangeOrder[]>;
85
211
  getTradeHistory(limit?: number): Promise<ExchangeTrade[]>;
86
212
  getFundingPayments(limit?: number): Promise<ExchangeFundingPayment[]>;
87
- marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
88
- reduceOnly?: boolean;
213
+ /**
214
+ * Per-market leverage / margin mode: every row of GET /fapi/v3/positionRisk ("Position
215
+ * Information v3", one row per symbol, position or not — docs example:
216
+ * `"marginType": "isolated"`, `"leverage": "10"`, `"positionAmt": "0.000"`; rows[].marginType
217
+ * "Margin type: `isolated` or `cross`"). An unreadable row throws — never a default.
218
+ */
219
+ getMarketSettings(): Promise<Array<{
220
+ symbol: string;
221
+ leverage: number;
222
+ marginMode: "cross" | "isolated";
223
+ }>>;
224
+ marketOrder(symbol: string, side: "buy" | "sell", size: string, opts: {
225
+ reduceOnly: boolean;
226
+ slippage: ResolvedSlippage;
227
+ clientOrderId?: string;
89
228
  }): Promise<unknown>;
90
229
  limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
91
230
  reduceOnly?: boolean;
92
231
  tif?: string;
232
+ clientOrderId?: string;
93
233
  }): Promise<unknown>;
234
+ /**
235
+ * Native modify (PUT /fapi/v3/order, V3 futures docs "Modify Order"): LIMIT orders
236
+ * only; TIF (incl. GTX) and reduceOnly stay on the order. `size` is the NEW UNFILLED
237
+ * quantity (§13.10 #10); the venue's `quantity` is the order total, so
238
+ * quantity = size + executedQty (read just before). A fill landing between the read
239
+ * and the PUT can only shrink the remainder, never over-size it. A venue rejection
240
+ * leaves the original order untouched (docs).
241
+ */
94
242
  editOrder(symbol: string, orderId: string, price: string, size: string): Promise<unknown>;
95
243
  cancelOrder(symbol: string, orderId: string): Promise<unknown>;
244
+ /**
245
+ * Cancel one order by client order id — V3 futures "Cancel Order" (DELETE /fapi/v3/order):
246
+ * "Either `orderId` or `origClientOrderId` must be sent."
247
+ */
248
+ cancelOrderByClientId(symbol: string, clientOrderId: string): Promise<unknown>;
249
+ /**
250
+ * One order's row — V3 futures "Query Order" (GET /fapi/v3/order, symbol + orderId or
251
+ * origClientOrderId). Docs: CANCELED / EXPIRED orders with no fill older than 7 days "will not
252
+ * be found". -2013 NO_SUCH_ORDER → ORDER_NOT_FOUND; any other failure throws as is.
253
+ */
254
+ queryOrderRow(symbol: string, ref: {
255
+ kind: "orderId" | "clientOrderId";
256
+ value: string;
257
+ }): Promise<Record<string, unknown>>;
258
+ private _cancelOne;
96
259
  cancelAllOrders(symbol?: string): Promise<unknown>;
97
260
  setLeverage(symbol: string, leverage: number, marginMode?: "cross" | "isolated"): Promise<unknown>;
261
+ /**
262
+ * Trigger order. Type follows the venue trigger rules (V3 docs, "Condition orders"):
263
+ * STOP*: BUY fires at price >= stopPrice, SELL at <= ; TAKE_PROFIT*: the reverse. So the
264
+ * type is chosen from the trigger vs the current trigger-source price and the order side
265
+ * (the side closing a long is SELL): BUY above / SELL below → STOP, otherwise
266
+ * TAKE_PROFIT. (Always STOP_MARKET made every TP fail with -2021.)
267
+ * Trigger source: workingType MARK_PRICE compared with the premiumIndex mark (default),
268
+ * or CONTRACT_PRICE with the last price when triggerType is "last".
269
+ * size "0" = whole position → closePosition=true (STOP_MARKET / TAKE_PROFIT_MARKET only;
270
+ * the venue forbids quantity and reduceOnly with it).
271
+ * `opts.kind` (TP/SL legs): sl → STOP(_MARKET), tp → TAKE_PROFIT(_MARKET) as given, with
272
+ * no price read; a trigger already crossed is rejected by the venue (-2021).
273
+ */
98
274
  stopOrder(symbol: string, side: "buy" | "sell", size: string, triggerPrice: string, opts?: {
99
275
  limitPrice?: string;
100
276
  reduceOnly?: boolean;
277
+ triggerType?: "mark" | "last" | "mid";
278
+ kind?: "tp" | "sl";
101
279
  }): Promise<unknown>;
102
- withdraw(amount: string, _destination: string, _opts?: {
280
+ /** Last traded price (GET /fapi/v3/ticker/price) — the CONTRACT_PRICE trigger source. */
281
+ private _lastPrice;
282
+ /** Asset withdrawn by `withdraw`: `requested` (must be in capabilities.withdrawAssets), else withdrawAssets[0]. */
283
+ private _withdrawAsset;
284
+ /**
285
+ * Withdrawable perp balance + fee for the withdraw asset on `chain`
286
+ * (POST /fapi/v3/aster/user-withdraw-info, signed by the API wallet). Read-only.
287
+ */
288
+ withdrawLimits(chain: AsterFundsChain, asset?: string): Promise<AsterWithdrawLimits>;
289
+ /** Deposit / withdraw history (POST /fapi/v3/aster/deposit-withdraw-history, signed by the API wallet). Read-only. */
290
+ depositWithdrawHistory(): Promise<unknown>;
291
+ /**
292
+ * Withdraw the venue collateral (USDT) from the perp account to the account owner's OWN address
293
+ * on BNB Chain (default) or Arbitrum. Two signatures (asterdex/api-docs
294
+ * demo/aster-deposit-withdrawal.md, API-demo futures-v3-demo/58_withdrawEvm.js):
295
+ * 1. `userSignature` — the master wallet's EIP-712 "Aster" Action over receiver / chain / token /
296
+ * amount / fee / nonce, recovered locally and compared to the account owner before sending;
297
+ * 2. the V3 envelope signed by the API wallet, which must have canWithdraw (and an IP whitelist).
298
+ * The fee and the maximum come from user-withdraw-info; the identical amount / fee strings go
299
+ * into the signature and the request. Once the request left, an unreadable result is
300
+ * ORDER_PENDING (never resubmit).
301
+ */
302
+ withdraw(amount: string, destination: string, opts?: {
103
303
  assetId?: number;
104
304
  routeType?: number;
105
- }): Promise<unknown>;
305
+ chain?: AsterFundsChain;
306
+ asset?: string;
307
+ }): Promise<AsterWithdrawResult>;
106
308
  /**
107
309
  * Resolve the active signer per the three-tier policy.
108
310
  *
@@ -110,6 +312,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
110
312
  * from production code outside this class.
111
313
  */
112
314
  _resolveSigner(): ResolvedSigner;
315
+ /** Monotonic µs nonce per signer, persisted across processes (aster-nonce.ts). */
113
316
  private _nextNonce;
114
317
  /**
115
318
  * Build the canonical signed-request URL per Aster v3 spec.
@@ -138,6 +341,15 @@ export declare class AsterAdapter implements ExchangeAdapter {
138
341
  * Sign and POST to a path using EIP-712 Domain B.
139
342
  */
140
343
  private _signedPostEip712;
344
+ /**
345
+ * A perp account WRITE (order / modify / cancel / margin type / leverage). Once the request is
346
+ * on the wire, a transport failure, an HTTP 5xx or an unreadable 2xx body leaves the outcome
347
+ * unknown → ORDER_PENDING (never the retryable EXCHANGE_ERROR / EXCHANGE_UNREACHABLE); no
348
+ * connection at all → not sent. Venue refusals (4xx, error envelopes) pass through unchanged.
349
+ */
350
+ private _perpWrite;
351
+ /** Sign and POST (or PUT) to `host + path` (perp `fapi` or spot `sapi` — same Domain B signing). */
352
+ private _signedPostTo;
141
353
  /**
142
354
  * Sign and GET from a path using EIP-712 Domain B.
143
355
  *
@@ -162,6 +374,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
162
374
  * Codex v0.12.12 final QA #3: previously MAX_ATTEMPTS = 3 truncated the
163
375
  * documented curve so the 8s backoff was never reachable in practice. */
164
376
  private _signedRequestWithRetry;
377
+ private _signedRequestLoop;
165
378
  /**
166
379
  * Unified response validator for ALL signed Aster requests.
167
380
  *