perp-cli 0.12.17 → 0.14.1

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 (363) 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 +303 -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 +248 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +925 -245
  103. package/dist/commands/history.js +102 -54
  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 +357 -459
  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 +240 -6
  166. package/dist/exchanges/aster.js +1139 -195
  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 +152 -0
  200. package/dist/exchanges/ondo/adapter.js +811 -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 +95 -0
  206. package/dist/exchanges/ondo/funds.js +198 -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 +293 -4
  218. package/dist/exchanges/pacifica.js +1044 -90
  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 +1386 -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 +29 -0
  270. package/dist/exchanges/venues/ondo.js +136 -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 +39 -0
  274. package/dist/exchanges/venues/qfex.js +140 -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 +821 -403
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/onchain-balances.d.ts +40 -0
  293. package/dist/onchain-balances.js +173 -0
  294. package/dist/pacifica/client.d.ts +41 -10
  295. package/dist/pacifica/client.js +167 -63
  296. package/dist/pacifica/constants.d.ts +0 -1
  297. package/dist/pacifica/constants.js +0 -5
  298. package/dist/pacifica/deposit.d.ts +30 -3
  299. package/dist/pacifica/deposit.js +119 -2
  300. package/dist/pacifica/faucet.d.ts +29 -0
  301. package/dist/pacifica/faucet.js +100 -0
  302. package/dist/pacifica/sign-tx.d.ts +15 -0
  303. package/dist/pacifica/sign-tx.js +41 -0
  304. package/dist/pacifica/types/account.d.ts +28 -4
  305. package/dist/pacifica/types/lake.d.ts +20 -5
  306. package/dist/pacifica/types/lake.js +4 -0
  307. package/dist/pacifica/types/market.d.ts +5 -0
  308. package/dist/pacifica/types/order.d.ts +4 -1
  309. package/dist/pacifica/types/position.d.ts +9 -1
  310. package/dist/plan-executor.d.ts +10 -5
  311. package/dist/plan-executor.js +165 -54
  312. package/dist/position-history.js +13 -0
  313. package/dist/rebalance.d.ts +26 -2
  314. package/dist/rebalance.js +86 -7
  315. package/dist/relay-swap.d.ts +232 -0
  316. package/dist/relay-swap.js +630 -0
  317. package/dist/risk.js +5 -1
  318. package/dist/secret-env.d.ts +15 -0
  319. package/dist/secret-env.js +36 -0
  320. package/dist/settings.d.ts +169 -6
  321. package/dist/settings.js +219 -38
  322. package/dist/signer/ows-evm.d.ts +13 -0
  323. package/dist/signer/ows-evm.js +22 -0
  324. package/dist/smart-order.d.ts +9 -0
  325. package/dist/smart-order.js +53 -8
  326. package/dist/strategies/dca.d.ts +6 -2
  327. package/dist/strategies/dca.js +66 -26
  328. package/dist/strategies/funding-arb.d.ts +11 -1
  329. package/dist/strategies/funding-arb.js +202 -89
  330. package/dist/strategies/grid.d.ts +31 -0
  331. package/dist/strategies/grid.js +89 -11
  332. package/dist/strategies/pending-stop.d.ts +8 -0
  333. package/dist/strategies/pending-stop.js +12 -0
  334. package/dist/strategies/split-order.d.ts +45 -17
  335. package/dist/strategies/split-order.js +157 -91
  336. package/dist/strategies/trailing-stop.d.ts +2 -1
  337. package/dist/strategies/trailing-stop.js +52 -6
  338. package/dist/strategies/twap.d.ts +6 -1
  339. package/dist/strategies/twap.js +39 -11
  340. package/dist/trade-validator.d.ts +22 -0
  341. package/dist/trade-validator.js +119 -15
  342. package/dist/utils/numeric.d.ts +46 -0
  343. package/dist/utils/numeric.js +79 -0
  344. package/dist/utils.d.ts +19 -0
  345. package/dist/utils.js +96 -19
  346. package/dist/withdraw-gate.d.ts +49 -0
  347. package/dist/withdraw-gate.js +131 -0
  348. package/package.json +15 -6
  349. package/skills/perp-cli/SKILL.md +159 -55
  350. package/skills/perp-cli/references/agent-operations.md +112 -58
  351. package/skills/perp-cli/references/commands.md +269 -73
  352. package/skills/perp-cli/references/strategies.md +34 -31
  353. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  354. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  355. package/skills/perp-cli/scripts/preflight.sh +21 -14
  356. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  357. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  358. package/vendor/lighter-signer/SHA256SUMS +2 -0
  359. package/vendor/lighter-signer/VERSION +8 -0
  360. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  361. package/vendor/lighter-signer/wasm_exec.js +575 -0
  362. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  363. 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;
@@ -30,6 +61,8 @@ type ResolvedSigner = {
30
61
  /** EVM address of the owner/master — used as `user` field in Aster requests */
31
62
  userAddress: string;
32
63
  };
64
+ /** Max 1000-row pages of 7-day commission income read for symbol discovery (20 000 fills). */
65
+ export declare const ASTER_INCOME_MAX_PAGES = 20;
33
66
  export declare class AsterAdapter implements ExchangeAdapter {
34
67
  readonly name = "aster";
35
68
  readonly chain = "bnb";
@@ -46,27 +79,108 @@ export declare class AsterAdapter implements ExchangeAdapter {
46
79
  private _marketsCache;
47
80
  private _marketsCacheTime;
48
81
  private _fundingHoursCache;
82
+ /** When the venue-wide funding-interval table was last loaded (0 = never). */
83
+ private _fundingInfoLoadedAt;
84
+ /** API symbol → price filters; null = listed but PRICE_FILTER / PERCENT_PRICE unreadable. */
85
+ private _priceFilters;
86
+ private _priceFiltersLoadedAt;
49
87
  private _accountCache;
50
88
  private _positionsCache;
51
89
  private _ordersCache;
52
90
  private static readonly CACHE_TTL;
53
91
  private static readonly ACCOUNT_CACHE_TTL;
54
- private _nonceCounter;
92
+ /**
93
+ * Builder-fee gate (settings builder.aster + confirmed master approveBuilder); null = not
94
+ * configured. Set by createAster — the adapter never reads settings.
95
+ */
96
+ builderFee: BuilderFeeGate | null;
55
97
  constructor(privateKey?: string, testnet?: boolean);
56
98
  init(): Promise<void>;
57
99
  setAgent(meta: AgentMeta, strategy: AgentSigningStrategy): void;
58
100
  setMasterSigner(signer: EvmSigner): void;
59
101
  setPkSigner(signer: EvmSigner): void;
60
102
  setNoAgent(noAgent: boolean): void;
103
+ /** Builder decision for the next perp order (cached approval read; never throws). */
104
+ builderDecision(): Promise<BuilderDecision>;
105
+ /** `builder` + `feeRate` (decimal) order params, or none (not configured / not approved). */
106
+ private _builderParams;
107
+ /** Owner (`user`) address of the active signer — the account a builder approval belongs to. */
108
+ get userAddress(): string;
109
+ /**
110
+ * Builder approvals of this account: GET /fapi/v3/builder (asterdex/api-docs demo
111
+ * `getBuilders`, signed by the API wallet). The response shape is not documented, so
112
+ * anything but a list of rows carrying an address + maxFeeRate is "unknown" (never guessed).
113
+ */
114
+ builderApprovalOf(target: BuilderTarget): Promise<BuilderApproval>;
61
115
  get isReadOnly(): boolean;
62
116
  get activeSignerTier(): "agent" | "master" | "pk" | null;
117
+ /**
118
+ * Aster spot REST host. Spot shares the perp EIP-712 Domain B signing
119
+ * (chainId 1666 mainnet / 714 testnet) and the per-agent nonce space.
120
+ * Hosts per the official spot V3 docs (mainnet + testnet variants).
121
+ */
122
+ get spotBaseUrl(): string;
123
+ /**
124
+ * Signed request against an arbitrary Aster host with the active signer.
125
+ * POST is single-shot; GET/DELETE use the same 429 retry loop as perp.
126
+ */
127
+ signedRequest(host: string, method: "GET" | "POST" | "DELETE", path: string, params: Record<string, string | number | boolean>): Promise<unknown>;
128
+ /**
129
+ * Agent meta of the active signer, or null when the active signer is not an
130
+ * agent. Throws exactly like signed calls when no signer is usable.
131
+ */
132
+ activeAgentMeta(): AgentMeta | null;
63
133
  /** CLI symbol → Aster API symbol (ETH → ETHUSDT) */
64
134
  private _toApi;
65
135
  /** Aster API symbol → CLI symbol (ETHUSDT → ETH) */
66
136
  private _fromApi;
67
- /** Get funding interval for a symbol (lazy bootstrap). */
137
+ /**
138
+ * Get funding interval for a symbol.
139
+ *
140
+ * Source of truth is `GET /fapi/v3/fundingInfo` (weight 1), which states
141
+ * `fundingIntervalHours` per symbol for the whole venue in a single call.
142
+ * This previously inferred the interval by differencing the last two
143
+ * `fundingRate` timestamps and bucketing to 1/4/8h — an estimate that is
144
+ * wrong for a newly listed symbol (fewer than two settlements), across a
145
+ * schedule change, or whenever a settlement is skipped/delayed, and Aster
146
+ * really does mix 1h, 4h and 8h symbols. Funding-interval misconfiguration is
147
+ * exactly what produced the v0.7.23 Aster funding bug, so it is read, not
148
+ * guessed.
149
+ */
68
150
  getFundingHours(symbol: string): Promise<number | undefined>;
151
+ /** Populate the funding-interval cache for every symbol in one call. */
152
+ private _loadFundingInfo;
69
153
  getMarkets(): Promise<ExchangeMarketInfo[]>;
154
+ /** Parse PRICE_FILTER + PERCENT_PRICE for every exchangeInfo symbol into the cache. */
155
+ private _ingestPriceFilters;
156
+ /** PRICE_FILTER / PERCENT_PRICE of an API symbol (exchangeInfo, cached CACHE_TTL). */
157
+ private _symbolPriceFilters;
158
+ /**
159
+ * Declared protection-price reference (§13.10 #5): the venue mark price from
160
+ * GET /fapi/v3/premiumIndex — the same price PERCENT_PRICE is evaluated against.
161
+ * No runtime substitute (no mid / last fallback): unavailable → PRICE_STALE.
162
+ */
163
+ referencePrice(symbol: string): Promise<string>;
164
+ /**
165
+ * Reject (never clamp) a price outside PRICE_FILTER min/max or the side's PERCENT_PRICE
166
+ * bound around `mark` — checked before anything is sent.
167
+ */
168
+ private _checkPriceBand;
169
+ /**
170
+ * Protection price an IOC market order on `symbol` would be sent with now:
171
+ * mark ± slippage.bps, aligned toward crossing on PRICE_FILTER.tickSize, validated
172
+ * against PRICE_FILTER / PERCENT_PRICE. appliedBps = the bound after tick alignment.
173
+ */
174
+ computeProtectionPrice(symbol: string, side: "buy" | "sell", slippage: ResolvedSlippage): Promise<{
175
+ referencePrice: string;
176
+ protectionPrice: string;
177
+ appliedBps: number;
178
+ }>;
179
+ /** Definite IOC outcome of a raw order response (see asterIocOutcome). */
180
+ iocOutcomeOf(raw: unknown): {
181
+ filledSize: string;
182
+ final: true;
183
+ } | null;
70
184
  getOrderbook(symbol: string): Promise<{
71
185
  bids: [string, string][];
72
186
  asks: [string, string][];
@@ -79,30 +193,139 @@ export declare class AsterAdapter implements ExchangeAdapter {
79
193
  }[]>;
80
194
  getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
81
195
  getBalance(): Promise<ExchangeBalance>;
196
+ /**
197
+ * How much of ONE asset the perp account can transfer out: that asset's row of
198
+ * GET /fapi/v3/accountWithJoinMargin `assets[]` — `maxWithdrawAmount` ("maximum amount for
199
+ * transfer out", Aster futures API v3 "Account Information v3"). The account-level
200
+ * `availableBalance` (getBalance) is margin across ALL collateral assets in multi-asset mode
201
+ * and is not an amount of any one asset. Read uncached. A missing row / field is an error,
202
+ * never 0.
203
+ */
204
+ getPerpAssetTransferable(asset: string): Promise<number>;
82
205
  getPositions(): Promise<ExchangePosition[]>;
206
+ /**
207
+ * Drop the in-process open-orders snapshot (after any order write, or before a verifying
208
+ * re-list). An order write also changes positions and balances, so those snapshots go too.
209
+ */
210
+ invalidateOpenOrdersCache(): void;
83
211
  getOpenOrders(): Promise<ExchangeOrder[]>;
212
+ /**
213
+ * Symbols with account activity: open positions, open orders, and every symbol with a
214
+ * COMMISSION income row in the last 7 days (the venue's default window). Aster's userTrades /
215
+ * allOrders both require `symbol`, so this is the per-symbol fan-out set. Income is read in
216
+ * pages of 1000 (the endpoint max; startTime / endTime are inclusive) walking back from now;
217
+ * more than ASTER_INCOME_MAX_PAGES pages → EXCHANGE_ERROR, never a partial set. Orders on a
218
+ * symbol that never filled, is not open and has no position cannot be found (allOrders needs it).
219
+ */
220
+ private _tradedApiSymbols;
221
+ /**
222
+ * Recent orders across the symbols with account activity (see _tradedApiSymbols), newest first.
223
+ * A failed read throws (never an empty list); a row without a readable field → EXCHANGE_ERROR.
224
+ */
84
225
  getOrderHistory(limit?: number): Promise<ExchangeOrder[]>;
226
+ /**
227
+ * Recent fills. `GET /fapi/v3/userTrades` requires a symbol (asterdex/api-docs V3), so the
228
+ * symbols come from the open positions plus every symbol with a COMMISSION income row in the
229
+ * venue's default window (`GET /fapi/v3/income`: "the recent 7-day data" when no time is sent).
230
+ * A failed read throws (never an empty list); a row without a readable field → EXCHANGE_ERROR.
231
+ */
85
232
  getTradeHistory(limit?: number): Promise<ExchangeTrade[]>;
86
233
  getFundingPayments(limit?: number): Promise<ExchangeFundingPayment[]>;
87
- marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
88
- reduceOnly?: boolean;
234
+ /**
235
+ * Per-market leverage / margin mode: every row of GET /fapi/v3/positionRisk ("Position
236
+ * Information v3", one row per symbol, position or not — docs example:
237
+ * `"marginType": "isolated"`, `"leverage": "10"`, `"positionAmt": "0.000"`; rows[].marginType
238
+ * "Margin type: `isolated` or `cross`"). An unreadable row throws — never a default.
239
+ */
240
+ getMarketSettings(): Promise<Array<{
241
+ symbol: string;
242
+ leverage: number;
243
+ marginMode: "cross" | "isolated";
244
+ }>>;
245
+ marketOrder(symbol: string, side: "buy" | "sell", size: string, opts: {
246
+ reduceOnly: boolean;
247
+ slippage: ResolvedSlippage;
248
+ clientOrderId?: string;
89
249
  }): Promise<unknown>;
90
250
  limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
91
251
  reduceOnly?: boolean;
92
252
  tif?: string;
253
+ clientOrderId?: string;
93
254
  }): Promise<unknown>;
255
+ /**
256
+ * Native modify (PUT /fapi/v3/order, V3 futures docs "Modify Order"): LIMIT orders
257
+ * only; TIF (incl. GTX) and reduceOnly stay on the order. `size` is the NEW UNFILLED
258
+ * quantity (§13.10 #10); the venue's `quantity` is the order total, so
259
+ * quantity = size + executedQty (read just before). A fill landing between the read
260
+ * and the PUT can only shrink the remainder, never over-size it. A venue rejection
261
+ * leaves the original order untouched (docs).
262
+ */
94
263
  editOrder(symbol: string, orderId: string, price: string, size: string): Promise<unknown>;
95
264
  cancelOrder(symbol: string, orderId: string): Promise<unknown>;
265
+ /**
266
+ * Cancel one order by client order id — V3 futures "Cancel Order" (DELETE /fapi/v3/order):
267
+ * "Either `orderId` or `origClientOrderId` must be sent."
268
+ */
269
+ cancelOrderByClientId(symbol: string, clientOrderId: string): Promise<unknown>;
270
+ /**
271
+ * One order's row — V3 futures "Query Order" (GET /fapi/v3/order, symbol + orderId or
272
+ * origClientOrderId). Docs: CANCELED / EXPIRED orders with no fill older than 7 days "will not
273
+ * be found". -2013 NO_SUCH_ORDER → ORDER_NOT_FOUND; any other failure throws as is.
274
+ */
275
+ queryOrderRow(symbol: string, ref: {
276
+ kind: "orderId" | "clientOrderId";
277
+ value: string;
278
+ }): Promise<Record<string, unknown>>;
279
+ private _cancelOne;
96
280
  cancelAllOrders(symbol?: string): Promise<unknown>;
97
281
  setLeverage(symbol: string, leverage: number, marginMode?: "cross" | "isolated"): Promise<unknown>;
282
+ /**
283
+ * Trigger order. Type follows the venue trigger rules (V3 docs, "Condition orders"):
284
+ * STOP*: BUY fires at price >= stopPrice, SELL at <= ; TAKE_PROFIT*: the reverse. So the
285
+ * type is chosen from the trigger vs the current trigger-source price and the order side
286
+ * (the side closing a long is SELL): BUY above / SELL below → STOP, otherwise
287
+ * TAKE_PROFIT. (Always STOP_MARKET made every TP fail with -2021.)
288
+ * Trigger source: workingType MARK_PRICE compared with the premiumIndex mark (default),
289
+ * or CONTRACT_PRICE with the last price when triggerType is "last".
290
+ * size "0" = whole position → closePosition=true (STOP_MARKET / TAKE_PROFIT_MARKET only;
291
+ * the venue forbids quantity and reduceOnly with it).
292
+ * `opts.kind` (TP/SL legs): sl → STOP(_MARKET), tp → TAKE_PROFIT(_MARKET) as given, with
293
+ * no price read; a trigger already crossed is rejected by the venue (-2021).
294
+ */
98
295
  stopOrder(symbol: string, side: "buy" | "sell", size: string, triggerPrice: string, opts?: {
99
296
  limitPrice?: string;
100
297
  reduceOnly?: boolean;
298
+ triggerType?: "mark" | "last" | "mid";
299
+ kind?: "tp" | "sl";
101
300
  }): Promise<unknown>;
102
- withdraw(amount: string, _destination: string, _opts?: {
301
+ /** Last traded price (GET /fapi/v3/ticker/price) — the CONTRACT_PRICE trigger source. */
302
+ private _lastPrice;
303
+ /** Asset withdrawn by `withdraw`: `requested` (must be in capabilities.withdrawAssets), else withdrawAssets[0]. */
304
+ private _withdrawAsset;
305
+ /**
306
+ * Withdrawable perp balance + fee for the withdraw asset on `chain`
307
+ * (POST /fapi/v3/aster/user-withdraw-info, signed by the API wallet). Read-only.
308
+ */
309
+ withdrawLimits(chain: AsterFundsChain, asset?: string): Promise<AsterWithdrawLimits>;
310
+ /** Deposit / withdraw history (POST /fapi/v3/aster/deposit-withdraw-history, signed by the API wallet). Read-only. */
311
+ depositWithdrawHistory(): Promise<unknown>;
312
+ /**
313
+ * Withdraw the venue collateral (USDT) from the perp account to the account owner's OWN address
314
+ * on BNB Chain (default) or Arbitrum. Two signatures (asterdex/api-docs
315
+ * demo/aster-deposit-withdrawal.md, API-demo futures-v3-demo/58_withdrawEvm.js):
316
+ * 1. `userSignature` — the master wallet's EIP-712 "Aster" Action over receiver / chain / token /
317
+ * amount / fee / nonce, recovered locally and compared to the account owner before sending;
318
+ * 2. the V3 envelope signed by the API wallet, which must have canWithdraw (and an IP whitelist).
319
+ * The fee and the maximum come from user-withdraw-info; the identical amount / fee strings go
320
+ * into the signature and the request. Once the request left, an unreadable result is
321
+ * ORDER_PENDING (never resubmit).
322
+ */
323
+ withdraw(amount: string, destination: string, opts?: {
103
324
  assetId?: number;
104
325
  routeType?: number;
105
- }): Promise<unknown>;
326
+ chain?: AsterFundsChain;
327
+ asset?: string;
328
+ }): Promise<AsterWithdrawResult>;
106
329
  /**
107
330
  * Resolve the active signer per the three-tier policy.
108
331
  *
@@ -110,6 +333,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
110
333
  * from production code outside this class.
111
334
  */
112
335
  _resolveSigner(): ResolvedSigner;
336
+ /** Monotonic µs nonce per signer, persisted across processes (aster-nonce.ts). */
113
337
  private _nextNonce;
114
338
  /**
115
339
  * Build the canonical signed-request URL per Aster v3 spec.
@@ -138,6 +362,15 @@ export declare class AsterAdapter implements ExchangeAdapter {
138
362
  * Sign and POST to a path using EIP-712 Domain B.
139
363
  */
140
364
  private _signedPostEip712;
365
+ /**
366
+ * A perp account WRITE (order / modify / cancel / margin type / leverage). Once the request is
367
+ * on the wire, a transport failure, an HTTP 5xx or an unreadable 2xx body leaves the outcome
368
+ * unknown → ORDER_PENDING (never the retryable EXCHANGE_ERROR / EXCHANGE_UNREACHABLE); no
369
+ * connection at all → not sent. Venue refusals (4xx, error envelopes) pass through unchanged.
370
+ */
371
+ private _perpWrite;
372
+ /** Sign and POST (or PUT) to `host + path` (perp `fapi` or spot `sapi` — same Domain B signing). */
373
+ private _signedPostTo;
141
374
  /**
142
375
  * Sign and GET from a path using EIP-712 Domain B.
143
376
  *
@@ -162,6 +395,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
162
395
  * Codex v0.12.12 final QA #3: previously MAX_ATTEMPTS = 3 truncated the
163
396
  * documented curve so the 8s backoff was never reachable in practice. */
164
397
  private _signedRequestWithRetry;
398
+ private _signedRequestLoop;
165
399
  /**
166
400
  * Unified response validator for ALL signed Aster requests.
167
401
  *