perp-cli 0.14.2 → 0.15.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 (313) hide show
  1. package/README.md +152 -13
  2. package/dist/agent-wallet/store.d.ts +3 -2
  3. package/dist/agent-wallet/store.js +2 -2
  4. package/dist/api/public/hyperliquid.js +4 -0
  5. package/dist/api/public/pacifica.js +83 -13
  6. package/dist/api/public/urls.d.ts +2 -0
  7. package/dist/api/public/urls.js +3 -0
  8. package/dist/arb/utils.d.ts +1 -2
  9. package/dist/arb/utils.js +1 -2
  10. package/dist/bot/apex/pulse.js +3 -0
  11. package/dist/bot/apex/radar.js +2 -1
  12. package/dist/bot/engine.d.ts +10 -1
  13. package/dist/bot/engine.js +14 -6
  14. package/dist/bot/indicators.d.ts +7 -0
  15. package/dist/bot/indicators.js +16 -0
  16. package/dist/bot/perp-order.d.ts +4 -4
  17. package/dist/bot/perp-order.js +5 -5
  18. package/dist/bot/quarantine.d.ts +1 -1
  19. package/dist/bot/quarantine.js +1 -1
  20. package/dist/bot/strategies/apex-strategy.js +3 -2
  21. package/dist/bot/strategies/engine-mm.js +6 -5
  22. package/dist/bot/strategies/funding-arb-strategy.js +9 -9
  23. package/dist/bot/strategies/funding-arb-utils.d.ts +15 -2
  24. package/dist/bot/strategies/funding-arb-utils.js +43 -24
  25. package/dist/bot/strategies/funding-auto.js +2 -2
  26. package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
  27. package/dist/bot/strategies/liquidation-mm.js +8 -2
  28. package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
  29. package/dist/bot/strategies/momentum-breakout.js +11 -3
  30. package/dist/bot/strategies/spot-perp-arb-strategy.js +23 -12
  31. package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
  32. package/dist/bot/strategies/spot-perp-executor.js +1 -1
  33. package/dist/bot/strategy-types.d.ts +2 -1
  34. package/dist/bot/tui/BotDashboard.d.ts +1 -1
  35. package/dist/bot/tui/BotDashboard.js +1 -1
  36. package/dist/cache.js +12 -6
  37. package/dist/cli-program.d.ts +15 -0
  38. package/dist/cli-program.js +125 -5
  39. package/dist/commands/agent-import.d.ts +7 -0
  40. package/dist/commands/agent-import.js +30 -1
  41. package/dist/commands/agent.d.ts +6 -3
  42. package/dist/commands/agent.js +160 -12
  43. package/dist/commands/arb/index.js +4 -4
  44. package/dist/commands/arb-auto.js +21 -17
  45. package/dist/commands/arb.d.ts +12 -0
  46. package/dist/commands/arb.js +61 -143
  47. package/dist/commands/bot.js +1 -1
  48. package/dist/commands/builder.js +1 -1
  49. package/dist/commands/funds.js +113 -3
  50. package/dist/commands/init.d.ts +1 -1
  51. package/dist/commands/init.js +27 -7
  52. package/dist/commands/manage.js +23 -21
  53. package/dist/commands/market.js +168 -36
  54. package/dist/commands/options.d.ts +9 -0
  55. package/dist/commands/options.js +134 -0
  56. package/dist/commands/pacifica-earn.d.ts +5 -0
  57. package/dist/commands/pacifica-earn.js +468 -0
  58. package/dist/commands/pacifica-orders.d.ts +14 -0
  59. package/dist/commands/pacifica-orders.js +142 -0
  60. package/dist/commands/portfolio.js +32 -47
  61. package/dist/commands/rebalance.d.ts +1 -0
  62. package/dist/commands/rebalance.js +15 -0
  63. package/dist/commands/risk.d.ts +11 -2
  64. package/dist/commands/risk.js +39 -44
  65. package/dist/commands/trade.d.ts +1 -0
  66. package/dist/commands/trade.js +63 -58
  67. package/dist/commands/wallet.js +1 -1
  68. package/dist/config.d.ts +2 -2
  69. package/dist/config.js +15 -4
  70. package/dist/constants.js +6 -0
  71. package/dist/dashboard/server.js +1 -1
  72. package/dist/dashboard/ui.js +1 -1
  73. package/dist/errors.d.ts +24 -1
  74. package/dist/errors.js +25 -3
  75. package/dist/exchanges/arcus/adapter.d.ts +7 -7
  76. package/dist/exchanges/arcus/adapter.js +12 -12
  77. package/dist/exchanges/arcus/agent.d.ts +1 -1
  78. package/dist/exchanges/arcus/agent.js +1 -1
  79. package/dist/exchanges/arcus/client.js +1 -1
  80. package/dist/exchanges/arcus/signing.d.ts +2 -3
  81. package/dist/exchanges/arcus/signing.js +1 -1
  82. package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
  83. package/dist/exchanges/arcus/spot-chain.js +1 -1
  84. package/dist/exchanges/arcus/spot-router.d.ts +1 -1
  85. package/dist/exchanges/arcus/spot-router.js +2 -2
  86. package/dist/exchanges/arcus/spot.d.ts +2 -3
  87. package/dist/exchanges/arcus/spot.js +2 -3
  88. package/dist/exchanges/aster-spot.d.ts +3 -3
  89. package/dist/exchanges/aster-spot.js +6 -9
  90. package/dist/exchanges/aster-typed-data.d.ts +1 -1
  91. package/dist/exchanges/aster-typed-data.js +1 -1
  92. package/dist/exchanges/aster.d.ts +9 -4
  93. package/dist/exchanges/aster.js +125 -55
  94. package/dist/exchanges/builder-fee.d.ts +1 -1
  95. package/dist/exchanges/builder-fee.js +13 -2
  96. package/dist/exchanges/canonical-symbols.d.ts +1 -2
  97. package/dist/exchanges/canonical-symbols.js +26 -2
  98. package/dist/exchanges/derive/client.d.ts +37 -0
  99. package/dist/exchanges/derive/client.js +135 -0
  100. package/dist/exchanges/derive/options.d.ts +68 -0
  101. package/dist/exchanges/derive/options.js +360 -0
  102. package/dist/exchanges/extended/adapter.d.ts +82 -0
  103. package/dist/exchanges/extended/adapter.js +179 -0
  104. package/dist/exchanges/extended/client.d.ts +38 -0
  105. package/dist/exchanges/extended/client.js +88 -0
  106. package/dist/exchanges/extended/public.d.ts +130 -0
  107. package/dist/exchanges/extended/public.js +429 -0
  108. package/dist/exchanges/grvt/adapter.d.ts +86 -0
  109. package/dist/exchanges/grvt/adapter.js +206 -0
  110. package/dist/exchanges/grvt/client.d.ts +25 -0
  111. package/dist/exchanges/grvt/client.js +86 -0
  112. package/dist/exchanges/grvt/public.d.ts +151 -0
  113. package/dist/exchanges/grvt/public.js +438 -0
  114. package/dist/exchanges/hyperliquid-spot.d.ts +1 -1
  115. package/dist/exchanges/hyperliquid-spot.js +5 -5
  116. package/dist/exchanges/hyperliquid.d.ts +22 -16
  117. package/dist/exchanges/hyperliquid.js +80 -55
  118. package/dist/exchanges/index.d.ts +1 -1
  119. package/dist/exchanges/index.js +1 -1
  120. package/dist/exchanges/interface.d.ts +97 -8
  121. package/dist/exchanges/interface.js +19 -2
  122. package/dist/exchanges/ioc-outcome.d.ts +1 -1
  123. package/dist/exchanges/ioc-outcome.js +1 -1
  124. package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
  125. package/dist/exchanges/legacy-trading-v2.js +7 -2
  126. package/dist/exchanges/lighter-public.d.ts +2 -2
  127. package/dist/exchanges/lighter-public.js +2 -2
  128. package/dist/exchanges/lighter-signer.d.ts +1 -1
  129. package/dist/exchanges/lighter-signer.js +1 -1
  130. package/dist/exchanges/lighter-spot.d.ts +3 -4
  131. package/dist/exchanges/lighter-spot.js +6 -7
  132. package/dist/exchanges/lighter.d.ts +11 -11
  133. package/dist/exchanges/lighter.js +28 -14
  134. package/dist/exchanges/ondo/adapter.d.ts +5 -6
  135. package/dist/exchanges/ondo/adapter.js +16 -14
  136. package/dist/exchanges/ondo/agent.d.ts +1 -1
  137. package/dist/exchanges/ondo/agent.js +1 -1
  138. package/dist/exchanges/ondo/client.d.ts +1 -1
  139. package/dist/exchanges/ondo/client.js +2 -2
  140. package/dist/exchanges/ondo/public.d.ts +8 -1
  141. package/dist/exchanges/ondo/public.js +13 -2
  142. package/dist/exchanges/ondo/spot.d.ts +2 -2
  143. package/dist/exchanges/ondo/spot.js +3 -3
  144. package/dist/exchanges/options-interface.d.ts +158 -0
  145. package/dist/exchanges/options-interface.js +17 -0
  146. package/dist/exchanges/options-venues.d.ts +12 -0
  147. package/dist/exchanges/options-venues.js +35 -0
  148. package/dist/exchanges/pacifica-atomic.d.ts +211 -0
  149. package/dist/exchanges/pacifica-atomic.js +440 -0
  150. package/dist/exchanges/pacifica-decimal.d.ts +10 -0
  151. package/dist/exchanges/pacifica-decimal.js +51 -0
  152. package/dist/exchanges/pacifica-presigned.d.ts +53 -0
  153. package/dist/exchanges/pacifica-presigned.js +141 -0
  154. package/dist/exchanges/pacifica-print.d.ts +200 -0
  155. package/dist/exchanges/pacifica-print.js +417 -0
  156. package/dist/exchanges/pacifica-spot.d.ts +2 -2
  157. package/dist/exchanges/pacifica-spot.js +3 -3
  158. package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
  159. package/dist/exchanges/pacifica-typed-data.js +1 -1
  160. package/dist/exchanges/pacifica-vaults.d.ts +121 -0
  161. package/dist/exchanges/pacifica-vaults.js +264 -0
  162. package/dist/exchanges/pacifica.d.ts +32 -5
  163. package/dist/exchanges/pacifica.js +114 -48
  164. package/dist/exchanges/precision.d.ts +3 -1
  165. package/dist/exchanges/precision.js +9 -2
  166. package/dist/exchanges/qfex/adapter.d.ts +18 -5
  167. package/dist/exchanges/qfex/adapter.js +32 -12
  168. package/dist/exchanges/qfex/agent.d.ts +1 -1
  169. package/dist/exchanges/qfex/agent.js +1 -1
  170. package/dist/exchanges/qfex/client.d.ts +1 -1
  171. package/dist/exchanges/qfex/client.js +1 -1
  172. package/dist/exchanges/qfex/errors.d.ts +1 -1
  173. package/dist/exchanges/qfex/errors.js +2 -2
  174. package/dist/exchanges/qfex/public.d.ts +3 -3
  175. package/dist/exchanges/qfex/public.js +3 -3
  176. package/dist/exchanges/qfex/signing.d.ts +2 -2
  177. package/dist/exchanges/qfex/signing.js +4 -5
  178. package/dist/exchanges/qfex/ws-transport.d.ts +2 -2
  179. package/dist/exchanges/qfex/ws-transport.js +3 -3
  180. package/dist/exchanges/rate-limiter.d.ts +1 -1
  181. package/dist/exchanges/rate-limiter.js +5 -2
  182. package/dist/exchanges/registry.d.ts +1 -1
  183. package/dist/exchanges/registry.js +1 -1
  184. package/dist/exchanges/risex/adapter.d.ts +148 -0
  185. package/dist/exchanges/risex/adapter.js +796 -0
  186. package/dist/exchanges/risex/agent.d.ts +154 -0
  187. package/dist/exchanges/risex/agent.js +384 -0
  188. package/dist/exchanges/risex/client.d.ts +47 -0
  189. package/dist/exchanges/risex/client.js +174 -0
  190. package/dist/exchanges/risex/nonce.d.ts +43 -0
  191. package/dist/exchanges/risex/nonce.js +212 -0
  192. package/dist/exchanges/risex/public.d.ts +64 -0
  193. package/dist/exchanges/risex/public.js +150 -0
  194. package/dist/exchanges/risex/session.d.ts +71 -0
  195. package/dist/exchanges/risex/session.js +171 -0
  196. package/dist/exchanges/risex/typed-data.d.ts +173 -0
  197. package/dist/exchanges/risex/typed-data.js +240 -0
  198. package/dist/exchanges/risex/units.d.ts +29 -0
  199. package/dist/exchanges/risex/units.js +104 -0
  200. package/dist/exchanges/slippage.d.ts +1 -1
  201. package/dist/exchanges/slippage.js +1 -1
  202. package/dist/exchanges/spot-factory.d.ts +3 -3
  203. package/dist/exchanges/spot-factory.js +7 -7
  204. package/dist/exchanges/spot-interface.d.ts +5 -5
  205. package/dist/exchanges/spot-interface.js +2 -2
  206. package/dist/exchanges/spot-result.d.ts +3 -3
  207. package/dist/exchanges/spot-result.js +3 -3
  208. package/dist/exchanges/trading-v2.d.ts +3 -3
  209. package/dist/exchanges/trading-v2.js +9 -6
  210. package/dist/exchanges/txflow/adapter.d.ts +54 -0
  211. package/dist/exchanges/txflow/adapter.js +118 -0
  212. package/dist/exchanges/txflow/client.d.ts +47 -0
  213. package/dist/exchanges/txflow/client.js +153 -0
  214. package/dist/exchanges/txflow/public.d.ts +76 -0
  215. package/dist/exchanges/txflow/public.js +284 -0
  216. package/dist/exchanges/unknown-symbol.d.ts +29 -0
  217. package/dist/exchanges/unknown-symbol.js +51 -0
  218. package/dist/exchanges/variational/adapter.d.ts +71 -0
  219. package/dist/exchanges/variational/adapter.js +137 -0
  220. package/dist/exchanges/variational/client.d.ts +21 -0
  221. package/dist/exchanges/variational/client.js +66 -0
  222. package/dist/exchanges/variational/public.d.ts +126 -0
  223. package/dist/exchanges/variational/public.js +430 -0
  224. package/dist/exchanges/venue-types.d.ts +6 -7
  225. package/dist/exchanges/venue-types.js +2 -2
  226. package/dist/exchanges/venue.d.ts +51 -8
  227. package/dist/exchanges/venue.js +54 -4
  228. package/dist/exchanges/venues/arcus.d.ts +1 -2
  229. package/dist/exchanges/venues/arcus.js +5 -4
  230. package/dist/exchanges/venues/aster.d.ts +2 -2
  231. package/dist/exchanges/venues/aster.js +6 -4
  232. package/dist/exchanges/venues/create-helpers.d.ts +1 -1
  233. package/dist/exchanges/venues/create-helpers.js +3 -3
  234. package/dist/exchanges/venues/extended.d.ts +21 -0
  235. package/dist/exchanges/venues/extended.js +96 -0
  236. package/dist/exchanges/venues/grvt.d.ts +30 -0
  237. package/dist/exchanges/venues/grvt.js +98 -0
  238. package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
  239. package/dist/exchanges/venues/hyperliquid.js +10 -8
  240. package/dist/exchanges/venues/index.d.ts +7 -2
  241. package/dist/exchanges/venues/index.js +8 -2
  242. package/dist/exchanges/venues/lighter-family.d.ts +7 -9
  243. package/dist/exchanges/venues/lighter-family.js +9 -11
  244. package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
  245. package/dist/exchanges/venues/lighter-rh.js +7 -5
  246. package/dist/exchanges/venues/lighter.d.ts +1 -1
  247. package/dist/exchanges/venues/lighter.js +5 -3
  248. package/dist/exchanges/venues/ondo.d.ts +1 -1
  249. package/dist/exchanges/venues/ondo.js +5 -3
  250. package/dist/exchanges/venues/pacifica.d.ts +2 -2
  251. package/dist/exchanges/venues/pacifica.js +6 -4
  252. package/dist/exchanges/venues/qfex.d.ts +1 -1
  253. package/dist/exchanges/venues/qfex.js +4 -2
  254. package/dist/exchanges/venues/risex-release.d.ts +14 -0
  255. package/dist/exchanges/venues/risex-release.js +14 -0
  256. package/dist/exchanges/venues/risex.d.ts +31 -0
  257. package/dist/exchanges/venues/risex.js +116 -0
  258. package/dist/exchanges/venues/txflow.d.ts +18 -0
  259. package/dist/exchanges/venues/txflow.js +77 -0
  260. package/dist/exchanges/venues/variational.d.ts +21 -0
  261. package/dist/exchanges/venues/variational.js +85 -0
  262. package/dist/execution-log.d.ts +1 -1
  263. package/dist/funding/legacy-public.d.ts +1 -1
  264. package/dist/funding/legacy-public.js +9 -4
  265. package/dist/funding/normalize.d.ts +1 -1
  266. package/dist/funding/normalize.js +1 -1
  267. package/dist/funding/rates.d.ts +44 -4
  268. package/dist/funding/rates.js +56 -12
  269. package/dist/index.js +7 -6
  270. package/dist/jobs.d.ts +1 -0
  271. package/dist/jobs.js +25 -1
  272. package/dist/landing.d.ts +2 -0
  273. package/dist/landing.js +1 -1
  274. package/dist/mcp-pacifica-earn.d.ts +9 -0
  275. package/dist/mcp-pacifica-earn.js +58 -0
  276. package/dist/mcp-server.js +113 -59
  277. package/dist/pacifica/client.d.ts +67 -4
  278. package/dist/pacifica/client.js +170 -8
  279. package/dist/pacifica/rate-limit.d.ts +144 -0
  280. package/dist/pacifica/rate-limit.js +267 -0
  281. package/dist/pacifica/types/order.d.ts +2 -1
  282. package/dist/plan-executor.js +7 -2
  283. package/dist/rebalance.js +1 -1
  284. package/dist/risk.d.ts +2 -1
  285. package/dist/risk.js +2 -4
  286. package/dist/settings.d.ts +32 -3
  287. package/dist/signer/ows-evm.d.ts +1 -1
  288. package/dist/signer/ows-evm.js +1 -1
  289. package/dist/smart-order.d.ts +1 -1
  290. package/dist/smart-order.js +1 -1
  291. package/dist/strategies/funding-arb.d.ts +1 -1
  292. package/dist/strategies/funding-arb.js +1 -1
  293. package/dist/trade-validator.d.ts +1 -1
  294. package/dist/trade-validator.js +9 -4
  295. package/dist/utils.d.ts +12 -3
  296. package/dist/utils.js +11 -3
  297. package/dist/venue-health.d.ts +40 -0
  298. package/dist/venue-health.js +75 -0
  299. package/dist/withdraw-gate.d.ts +1 -1
  300. package/dist/withdraw-gate.js +1 -1
  301. package/dist/ws/index.d.ts +959 -0
  302. package/dist/ws/index.js +4295 -0
  303. package/dist/ws/node.d.ts +975 -0
  304. package/dist/ws/node.js +4366 -0
  305. package/dist/ws/pacifica-instrument.d.ts +8 -0
  306. package/dist/ws/pacifica-instrument.js +8 -0
  307. package/dist/ws-cli/credentials.d.ts +62 -0
  308. package/dist/ws-cli/credentials.js +126 -0
  309. package/package.json +58 -10
  310. package/skills/perp-cli/SKILL.md +62 -9
  311. package/skills/perp-cli/references/agent-operations.md +7 -0
  312. package/skills/perp-cli/references/commands.md +76 -5
  313. package/skills/perp-cli/references/ws-library.md +492 -0
package/dist/errors.d.ts CHANGED
@@ -158,7 +158,7 @@ export declare const ERROR_CODES: {
158
158
  readonly status: 202;
159
159
  readonly retryable: false;
160
160
  };
161
- /** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent (design §12.3). */
161
+ /** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent. */
162
162
  readonly ORDER_REJECTED: {
163
163
  readonly code: "ORDER_REJECTED";
164
164
  readonly status: 422;
@@ -173,6 +173,29 @@ export declare const ERROR_CODES: {
173
173
  readonly status: 422;
174
174
  readonly retryable: false;
175
175
  };
176
+ /** A venue frame could not be parsed or classified (never silently dropped). */
177
+ readonly WS_PROTOCOL_ERROR: {
178
+ readonly code: "WS_PROTOCOL_ERROR";
179
+ readonly status: 502;
180
+ readonly retryable: false;
181
+ };
182
+ readonly WS_AUTH_FAILED: {
183
+ readonly code: "WS_AUTH_FAILED";
184
+ readonly status: 401;
185
+ readonly retryable: false;
186
+ };
187
+ /** A subscription / connection budget (venue limit or caller budget) would be exceeded. */
188
+ readonly SUBSCRIPTION_LIMIT: {
189
+ readonly code: "SUBSCRIPTION_LIMIT";
190
+ readonly status: 400;
191
+ readonly retryable: false;
192
+ };
193
+ /** An event stream's bounded buffer overflowed; the subscription was closed. */
194
+ readonly STREAM_OVERFLOW: {
195
+ readonly code: "STREAM_OVERFLOW";
196
+ readonly status: 507;
197
+ readonly retryable: false;
198
+ };
176
199
  readonly EXCHANGE_UNREACHABLE: {
177
200
  readonly code: "EXCHANGE_UNREACHABLE";
178
201
  readonly status: 503;
package/dist/errors.js CHANGED
@@ -25,7 +25,7 @@ export const ERROR_CODES = {
25
25
  PASSPHRASE_REQUIRED: { code: "PASSPHRASE_REQUIRED", status: 401, retryable: false },
26
26
  INVALID_PASSPHRASE: { code: "INVALID_PASSPHRASE", status: 401, retryable: false },
27
27
  NOT_IMPLEMENTED: { code: "NOT_IMPLEMENTED", status: 501, retryable: false },
28
- // Venue abstraction (docs/DESIGN-venue-abstraction.md §10)
28
+ // Venue abstraction
29
29
  UNKNOWN_VENUE: { code: "UNKNOWN_VENUE", status: 400, retryable: false },
30
30
  TIF_REQUIRED: { code: "TIF_REQUIRED", status: 400, retryable: false },
31
31
  INVALID_TICK: { code: "INVALID_TICK", status: 400, retryable: false },
@@ -36,13 +36,21 @@ export const ERROR_CODES = {
36
36
  ORDER_PARTIAL: { code: "ORDER_PARTIAL", status: 500, retryable: false },
37
37
  /** The order was submitted but its outcome is not confirmed; retrying could double-trade. */
38
38
  ORDER_PENDING: { code: "ORDER_PENDING", status: 202, retryable: false },
39
- /** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent (design §12.3). */
39
+ /** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent. */
40
40
  ORDER_REJECTED: { code: "ORDER_REJECTED", status: 422, retryable: false },
41
41
  /**
42
42
  * The venue explicitly refused a non-order account action (withdraw / transfer / approval) and
43
43
  * executed nothing — distinct from a network / unknown outcome (EXCHANGE_ERROR, UNKNOWN).
44
44
  */
45
45
  ACTION_REJECTED: { code: "ACTION_REJECTED", status: 422, retryable: false },
46
+ // WebSocket library (perp-cli/ws, src/ws/errors.ts keeps a parity-tested copy)
47
+ /** A venue frame could not be parsed or classified (never silently dropped). */
48
+ WS_PROTOCOL_ERROR: { code: "WS_PROTOCOL_ERROR", status: 502, retryable: false },
49
+ WS_AUTH_FAILED: { code: "WS_AUTH_FAILED", status: 401, retryable: false },
50
+ /** A subscription / connection budget (venue limit or caller budget) would be exceeded. */
51
+ SUBSCRIPTION_LIMIT: { code: "SUBSCRIPTION_LIMIT", status: 400, retryable: false },
52
+ /** An event stream's bounded buffer overflowed; the subscription was closed. */
53
+ STREAM_OVERFLOW: { code: "STREAM_OVERFLOW", status: 507, retryable: false },
46
54
  // 5xx - System / transient errors
47
55
  EXCHANGE_UNREACHABLE: { code: "EXCHANGE_UNREACHABLE", status: 503, retryable: true },
48
56
  RATE_LIMITED: { code: "RATE_LIMITED", status: 429, retryable: true, retryAfterMs: 1000 },
@@ -92,6 +100,12 @@ export function classifyError(err, exchange) {
92
100
  const ex = (err.structured.exchange ?? exchange);
93
101
  return ex !== undefined ? { ...err.structured, exchange: ex } : { ...err.structured };
94
102
  }
103
+ // Structural PerpError (perp-cli/ws WsError is a separate leaf class): keep its registered code.
104
+ if (err instanceof Error && isStructuredLike(err)) {
105
+ const s = err.structured;
106
+ const ex = s.exchange ?? exchange;
107
+ return ex !== undefined ? { ...s, exchange: ex } : { ...s };
108
+ }
95
109
  const message = extractErrorMessage(err);
96
110
  const lower = message.toLowerCase();
97
111
  // Margin-specific checks first (before generic "insufficient" catch)
@@ -216,6 +230,14 @@ export function classifyError(err, exchange) {
216
230
  }
217
231
  return { ...ERROR_CODES.UNKNOWN, message };
218
232
  }
233
+ function isStructuredLike(err) {
234
+ const s = err.structured;
235
+ if (s === null || typeof s !== "object")
236
+ return false;
237
+ const { code, message, status, retryable } = s;
238
+ return typeof code === "string" && Object.prototype.hasOwnProperty.call(ERROR_CODES, code)
239
+ && typeof message === "string" && typeof status === "number" && typeof retryable === "boolean";
240
+ }
219
241
  /** Custom error class that carries a structured error code */
220
242
  export class PerpError extends Error {
221
243
  structured;
@@ -235,7 +257,7 @@ export class PerpError extends Error {
235
257
  };
236
258
  }
237
259
  }
238
- // ── Order outcome classification (design §12.3) ──
260
+ // ── Order outcome classification ──
239
261
  /**
240
262
  * Codes that mean "the order was definitely not placed / filled nothing": a validation
241
263
  * or policy failure before sending (incl. PRICE_STALE: no price to build the order), or an
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim (design §10.7).
2
+ * Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim.
3
3
  *
4
4
  * Signing: the agent API key is an Ed25519 key in OWS wallet
5
5
  * `meta.agentWalletName` (raw signMessage on the Solana account — no prefix).
@@ -7,12 +7,12 @@
7
7
  * (master creds only, for spot swaps) every perp private call throws
8
8
  * AGENT_NOT_REGISTERED from requireAccount().
9
9
  *
10
- * Order entry rules (docs.arcus.xyz, design §10.10):
10
+ * Order entry rules (docs.arcus.xyz):
11
11
  * - every order carries goodTilTime ≥ 1 month ahead (ARCUS_GOOD_TIL_HORIZON_MS),
12
12
  * body in µs, signed `g` in ns;
13
13
  * - market orders = IOC LIMIT at a protection price derived from mark and an
14
14
  * explicit slippage bound, rejected locally when > 10 % from mark;
15
- * - TIF (design §13.3): common GTC is sent as GTT with goodTil = now +
15
+ * - TIF: common GTC is sent as GTT with goodTil = now +
16
16
  * ARCUS_GOOD_TIL_HORIZON_MS (recorded as execution.expiresAt); IOC / FOK / ALO
17
17
  * are native; a limit order without a TIF is GTC;
18
18
  * - clientId is always sent (orderAck async) and every OrderResult from a
@@ -22,7 +22,7 @@
22
22
  * an `entryTpsl` bundle.
23
23
  */
24
24
  import type { EvmSigner } from "../../signer/interface.js";
25
- import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade } from "../interface.js";
25
+ import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade, ExchangePublicTrade } from "../interface.js";
26
26
  import type { ResolvedSlippage } from "../slippage.js";
27
27
  import { type TradingV2 } from "../trading-v2.js";
28
28
  import type { VenueCreateContext, VenueDefinition } from "../venue.js";
@@ -92,7 +92,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
92
92
  /**
93
93
  * modifyOrder (docs modify-order / authentication).
94
94
  *
95
- * Size: the CLI's `req.size` is the new OPEN (unfilled) size (design §13.4), while
95
+ * Size: the CLI's `req.size` is the new OPEN (unfilled) size, while
96
96
  * Arcus modifies take the order's new TOTAL size, filled quantity included
97
97
  * (OrderRejectionReason MODIFY_SIZE_ALREADY_FILLED: "the order's new TOTAL size,
98
98
  * filled quantity included"). So body `quantity` and signed `q` are
@@ -143,7 +143,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
143
143
  bids: [string, string][];
144
144
  asks: [string, string][];
145
145
  }>;
146
- getRecentTrades(symbol: string, limit?: number): Promise<ExchangeTrade[]>;
146
+ getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
147
147
  getFundingHistory(symbol: string, limit?: number): Promise<{
148
148
  time: number;
149
149
  rate: string;
@@ -182,7 +182,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
182
182
  }): Promise<unknown>;
183
183
  private masterSigner;
184
184
  private requireMasterKey;
185
- /** Master EVM signer for on-chain actions outside the Arcus API (spot swaps, design §12.4 #7). */
185
+ /** Master EVM signer for on-chain actions outside the Arcus API (spot swaps). */
186
186
  masterEvmSigner(): Promise<EvmSigner>;
187
187
  /** Sign an unsigned EVM transaction with the master key (digest derived here). Returns a 65-byte 0x signature. */
188
188
  signMasterTransaction(tx: import("ethers").Transaction): Promise<string>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim (design §10.7).
2
+ * Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim.
3
3
  *
4
4
  * Signing: the agent API key is an Ed25519 key in OWS wallet
5
5
  * `meta.agentWalletName` (raw signMessage on the Solana account — no prefix).
@@ -7,12 +7,12 @@
7
7
  * (master creds only, for spot swaps) every perp private call throws
8
8
  * AGENT_NOT_REGISTERED from requireAccount().
9
9
  *
10
- * Order entry rules (docs.arcus.xyz, design §10.10):
10
+ * Order entry rules (docs.arcus.xyz):
11
11
  * - every order carries goodTilTime ≥ 1 month ahead (ARCUS_GOOD_TIL_HORIZON_MS),
12
12
  * body in µs, signed `g` in ns;
13
13
  * - market orders = IOC LIMIT at a protection price derived from mark and an
14
14
  * explicit slippage bound, rejected locally when > 10 % from mark;
15
- * - TIF (design §13.3): common GTC is sent as GTT with goodTil = now +
15
+ * - TIF: common GTC is sent as GTT with goodTil = now +
16
16
  * ARCUS_GOOD_TIL_HORIZON_MS (recorded as execution.expiresAt); IOC / FOK / ALO
17
17
  * are native; a limit order without a TIF is GTC;
18
18
  * - clientId is always sent (orderAck async) and every OrderResult from a
@@ -196,13 +196,13 @@ export class ArcusAdapter {
196
196
  const meta = ctx.noAgent ? null : ctx.credentials.agent;
197
197
  if (meta === null) {
198
198
  if (!hasMaster) {
199
- // §12.4 #7: no agent key and no master EVM key — nothing can sign.
199
+ // no agent key and no master EVM key — nothing can sign.
200
200
  throw new PerpError("NO_SIGNER_AVAILABLE", "No Arcus signer: no agent API key and no master EVM wallet / private key", {
201
201
  remediation: "Spot swaps: pass --wallet <ows-wallet> (master EVM key). Perp trading: perp wallet agent approve arcus --master <ows-wallet>",
202
202
  });
203
203
  }
204
204
  // Master-only (also --no-agent): spot swaps (master EVM signer) work; perp
205
- // private calls throw AGENT_NOT_REGISTERED in requireAccount() (design §12.4 #7).
205
+ // private calls throw AGENT_NOT_REGISTERED in requireAccount().
206
206
  this.client = new ArcusClient(ctx.network, null);
207
207
  this.account = null;
208
208
  return;
@@ -462,7 +462,7 @@ export class ArcusAdapter {
462
462
  return onlineArcusMarkets(raw).map(toArcusVenueMarket);
463
463
  }
464
464
  async placeOrder(input) {
465
- // §13.3: GTC is the uniform default for a limit order without a TIF.
465
+ // GTC is the uniform default for a limit order without a TIF.
466
466
  const tifRequested = input.tif;
467
467
  const req = input.type === "limit" && input.tif === null ? { ...input, tif: "GTC" } : input;
468
468
  validateOrderRequest(this.venue, this.caps, req);
@@ -609,7 +609,7 @@ export class ArcusAdapter {
609
609
  /**
610
610
  * modifyOrder (docs modify-order / authentication).
611
611
  *
612
- * Size: the CLI's `req.size` is the new OPEN (unfilled) size (design §13.4), while
612
+ * Size: the CLI's `req.size` is the new OPEN (unfilled) size, while
613
613
  * Arcus modifies take the order's new TOTAL size, filled quantity included
614
614
  * (OrderRejectionReason MODIFY_SIZE_ALREADY_FILLED: "the order's new TOTAL size,
615
615
  * filled quantity included"). So body `quantity` and signed `q` are
@@ -886,7 +886,7 @@ export class ArcusAdapter {
886
886
  const m = await this.market(symbol);
887
887
  const res = await this.client.get("/v1/trades", "trades", { market: m.marketDisplayName, limit });
888
888
  // Public tape carries no fee; "0" follows the legacy ExchangeTrade convention for public trades.
889
- return res.trades.map(t => ({ time: usToMs(t.timestamp), symbol: m.baseAsset, side: sideLower(t.side), price: t.price, size: t.size, fee: "0" }));
889
+ return res.trades.map(t => ({ time: usToMs(t.timestamp), symbol: m.baseAsset, side: sideLower(t.side), price: t.price, size: t.size, fee: null }));
890
890
  }
891
891
  async getFundingHistory(symbol, limit = 100) {
892
892
  const m = await this.market(symbol);
@@ -915,7 +915,7 @@ export class ArcusAdapter {
915
915
  const res = await this.client.get("/v1/candles", "candles", { market: m.marketDisplayName, timeframe: interval, from: from * 1000, to: to * 1000 });
916
916
  for (const c of res.candles) {
917
917
  const time = usToMs(c.openTime);
918
- byTime.set(time, { time, open: c.open, high: c.high, low: c.low, close: c.close, volume: c.volume, trades: c.tradeCount });
918
+ byTime.set(time, { time, open: c.open, high: c.high, low: c.low, close: c.close, volume: c.volume, quoteVolume: null, trades: c.tradeCount });
919
919
  }
920
920
  }
921
921
  return [...byTime.values()].sort((x, y) => x.time - y.time);
@@ -995,7 +995,7 @@ export class ArcusAdapter {
995
995
  out.push({ time: usToMs(p.time), symbol: await this.symbolOf(p.marketId), payment: p.payment });
996
996
  return out;
997
997
  }
998
- // ── Legacy: trading shims (§10.7) ──
998
+ // ── Legacy: trading shims ──
999
999
  /** `clientOrderId`: the caller's id when given; otherwise one is generated (orderAck async needs one). */
1000
1000
  async marketOrder(symbol, side, size, opts) {
1001
1001
  return this.placeOrder({
@@ -1036,7 +1036,7 @@ export class ArcusAdapter {
1036
1036
  tif: isLimit ? "GTC" : null, // sent as GTT at the max horizon
1037
1037
  reduceOnly: opts?.reduceOnly === true, // non-reduce-only → CAPABILITY_UNSUPPORTED in validation
1038
1038
  clientOrderId: newClientOrderId(),
1039
- // The caller's resolved bound (the adapter never reads settings, §13.10 #1);
1039
+ // The caller's resolved bound (the adapter never reads settings);
1040
1040
  // a stop-market without it → INVALID_PARAMS in placeOrder.
1041
1041
  slippage: isLimit ? null : opts?.slippage ?? null,
1042
1042
  tpsl: null,
@@ -1060,7 +1060,7 @@ export class ArcusAdapter {
1060
1060
  });
1061
1061
  }
1062
1062
  }
1063
- /** Master EVM signer for on-chain actions outside the Arcus API (spot swaps, design §12.4 #7). */
1063
+ /** Master EVM signer for on-chain actions outside the Arcus API (spot swaps). */
1064
1064
  async masterEvmSigner() {
1065
1065
  this.requireMasterKey();
1066
1066
  return this.masterSigner();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus agent (API key) lifecycle — design §10.4.
2
+ * Arcus agent (API key) lifecycle.
3
3
  *
4
4
  * approve:
5
5
  * 1. Resolve the master EVM signer from OWS (`masterOwsWallet`).
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus agent (API key) lifecycle — design §10.4.
2
+ * Arcus agent (API key) lifecycle.
3
3
  *
4
4
  * approve:
5
5
  * 1. Resolve the master EVM signer from OWS (`masterOwsWallet`).
@@ -198,7 +198,7 @@ export class ArcusClient {
198
198
  async send(method, url, endpoint, headers, body) {
199
199
  // Timeout covers fetch + body read. A GET failure is definite (TIMEOUT /
200
200
  // EXCHANGE_UNREACHABLE); a POST failure may have reached the venue → outcome
201
- // unknown (ORDER_PENDING, never resubmit — design §12.3).
201
+ // unknown (ORDER_PENDING, never resubmit).
202
202
  const signal = AbortSignal.timeout(TIMEOUT_MS);
203
203
  let res;
204
204
  let text;
@@ -14,7 +14,7 @@
14
14
  * "everything else" rule, scheduleCancel — unverified):
15
15
  * ed25519(timestampNs + action + canonicalJson(body))
16
16
  *
17
- * Time units (design §10.10): `ct` and X-Timestamp are Unix NANOseconds;
17
+ * Time units: `ct` and X-Timestamp are Unix NANOseconds;
18
18
  * signed `g` is NANOseconds; the request body `goodTilTime` is a MICROsecond
19
19
  * decimal string (g = goodTilTime × 1000).
20
20
  *
@@ -78,8 +78,7 @@ export declare function placePayload(f: ArcusPlaceFields, untriggered: boolean):
78
78
  * - authentication page: always `id`, plus `c` "only if the resting order was placed
79
79
  * with a client id … the engine rejects a mismatch".
80
80
  * Default follows the openapi spec ("idOnly": sign `id`, never `c`; the body sends
81
- * orderId only). "idAndClientId" is the authentication-page variant. Settled by the
82
- * docs/TEST-PLAN.md step "Arcus modify signature identity" on testnet.
81
+ * orderId only). "idAndClientId" is the authentication-page variant. Settled by the "Arcus modify signature identity" testnet check.
83
82
  */
84
83
  export type ArcusModifyIdentity = "idOnly" | "idAndClientId";
85
84
  export declare const ARCUS_MODIFY_SIGNED_IDENTITY: ArcusModifyIdentity;
@@ -14,7 +14,7 @@
14
14
  * "everything else" rule, scheduleCancel — unverified):
15
15
  * ed25519(timestampNs + action + canonicalJson(body))
16
16
  *
17
- * Time units (design §10.10): `ct` and X-Timestamp are Unix NANOseconds;
17
+ * Time units: `ct` and X-Timestamp are Unix NANOseconds;
18
18
  * signed `g` is NANOseconds; the request body `goodTilTime` is a MICROsecond
19
19
  * decimal string (g = goodTilTime × 1000).
20
20
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Robinhood Chain reads/txs for Arcus spot (design §12.4 #7), over
2
+ * Robinhood Chain reads/txs for Arcus spot, over
3
3
  * `VenueNetworkConfig.rpcUrl` with ethers.
4
4
  *
5
5
  * Permit2 allowance logic ported from @arcus-xyz/arcus-spot-sdk@1.0.2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Robinhood Chain reads/txs for Arcus spot (design §12.4 #7), over
2
+ * Robinhood Chain reads/txs for Arcus spot, over
3
3
  * `VenueNetworkConfig.rpcUrl` with ethers.
4
4
  *
5
5
  * Permit2 allowance logic ported from @arcus-xyz/arcus-spot-sdk@1.0.2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus Spot Router HTTP client + wire types (design §12, §12.4 #7).
2
+ * Arcus Spot Router HTTP client + wire types.
3
3
  *
4
4
  * Ported from @arcus-xyz/arcus-spot-sdk@1.0.2 (src/client.ts, src/types.ts,
5
5
  * src/chains.ts) — Copyright Arcus, licensed under the Apache License 2.0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Arcus Spot Router HTTP client + wire types (design §12, §12.4 #7).
2
+ * Arcus Spot Router HTTP client + wire types.
3
3
  *
4
4
  * Ported from @arcus-xyz/arcus-spot-sdk@1.0.2 (src/client.ts, src/types.ts,
5
5
  * src/chains.ts) — Copyright Arcus, licensed under the Apache License 2.0
@@ -167,7 +167,7 @@ export class ArcusSpotRouter {
167
167
  sellAmount: p.sellAmount.toString(),
168
168
  taker: p.taker,
169
169
  slippageBps: String(p.slippageBps),
170
- allowWrapped: "false", // §12.4 #7 — never accept a wrapped placeholder
170
+ allowWrapped: "false", // never accept a wrapped placeholder
171
171
  });
172
172
  }
173
173
  /** Single attempt — never retried (a resend could double-execute). Throws RouterHttpError / PerpError. */
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Arcus spot = Stock Token swaps through the Arcus Spot Router (design §12,
3
- * §12.4 #5 #7). Not an exchange account: balances are the master wallet's
2
+ * Arcus spot = Stock Token swaps through the Arcus Spot Router. Not an exchange account: balances are the master wallet's
4
3
  * ERC-20 balances on Robinhood Chain, and every trade is an exact-input swap
5
4
  * settled on-chain (Permit2 `PermitWitnessTransferFrom` + `TakerIntent`).
6
5
  *
@@ -79,7 +78,7 @@ export declare class ArcusSpotAdapter implements SpotAdapter, SpotPricesCapable
79
78
  * all-in buy price at that notional. The signed intent must then carry
80
79
  * minBuyAmount ≥ size × (1 − slippageBps), else nothing is signed.
81
80
  * Both sides also require minBuyAmount ≥ quote.buyAmount × (1 − slippageBps).
82
- * slippageBps = the caller's resolveSlippage() value (design §13.2); the router
81
+ * slippageBps = the caller's resolveSlippage() value; the router
83
82
  * takes an integer bound.
84
83
  */
85
84
  spotMarketOrder(symbol: string, side: "buy" | "sell", size: string, opts: {
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Arcus spot = Stock Token swaps through the Arcus Spot Router (design §12,
3
- * §12.4 #5 #7). Not an exchange account: balances are the master wallet's
2
+ * Arcus spot = Stock Token swaps through the Arcus Spot Router. Not an exchange account: balances are the master wallet's
4
3
  * ERC-20 balances on Robinhood Chain, and every trade is an exact-input swap
5
4
  * settled on-chain (Permit2 `PermitWitnessTransferFrom` + `TakerIntent`).
6
5
  *
@@ -335,7 +334,7 @@ export class ArcusSpotAdapter {
335
334
  * all-in buy price at that notional. The signed intent must then carry
336
335
  * minBuyAmount ≥ size × (1 − slippageBps), else nothing is signed.
337
336
  * Both sides also require minBuyAmount ≥ quote.buyAmount × (1 − slippageBps).
338
- * slippageBps = the caller's resolveSlippage() value (design §13.2); the router
337
+ * slippageBps = the caller's resolveSlippage() value; the router
339
338
  * takes an integer bound.
340
339
  */
341
340
  async spotMarketOrder(symbol, side, size, opts) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Aster Spot Adapter (design §12, §12.4 #8).
2
+ * Aster Spot Adapter.
3
3
  *
4
4
  * Host `sapi.asterdex.com` (testnet `sapi.asterdex-testnet.com`), paths
5
5
  * `/api/v3/*`. Signing is the perp EIP-712 Domain B scheme, reused through
@@ -11,7 +11,7 @@
11
11
  * Venue rules enforced locally (official spot V3 docs):
12
12
  * - TIF GTC | IOC | GTX (post-only). FOK is rejected by the venue (-1115).
13
13
  * - LIMIT price must be on PRICE_FILTER.tickSize (never rounded).
14
- * - Market orders are IOC LIMIT at a protection price (design §13.2): bookTicker
14
+ * - Market orders are IOC LIMIT at a protection price: bookTicker
15
15
  * mid ± slippage, aligned toward crossing on tickSize, inside PRICE_FILTER
16
16
  * min/max and PERCENT_PRICE (venue native MARKET is never sent).
17
17
  * - quantity on LOT_SIZE step, min, max (MARKET_LOT_SIZE only for native MARKET).
@@ -95,7 +95,7 @@ export declare class AsterSpotAdapter implements SpotAdapter, SpotTransferCapabl
95
95
  /** Effective minimum notional, or null when no filter applies. */
96
96
  private _minNotional;
97
97
  private _checkNotional;
98
- /** §12.4 #8: gate only when the active signer is an agent lacking canSpotTrade. */
98
+ /** gate only when the active signer is an agent lacking canSpotTrade. */
99
99
  private _requireSpotPermission;
100
100
  private _signed;
101
101
  private _publicGet;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Aster Spot Adapter (design §12, §12.4 #8).
2
+ * Aster Spot Adapter.
3
3
  *
4
4
  * Host `sapi.asterdex.com` (testnet `sapi.asterdex-testnet.com`), paths
5
5
  * `/api/v3/*`. Signing is the perp EIP-712 Domain B scheme, reused through
@@ -11,7 +11,7 @@
11
11
  * Venue rules enforced locally (official spot V3 docs):
12
12
  * - TIF GTC | IOC | GTX (post-only). FOK is rejected by the venue (-1115).
13
13
  * - LIMIT price must be on PRICE_FILTER.tickSize (never rounded).
14
- * - Market orders are IOC LIMIT at a protection price (design §13.2): bookTicker
14
+ * - Market orders are IOC LIMIT at a protection price: bookTicker
15
15
  * mid ± slippage, aligned toward crossing on tickSize, inside PRICE_FILTER
16
16
  * min/max and PERCENT_PRICE (venue native MARKET is never sent).
17
17
  * - quantity on LOT_SIZE step, min, max (MARKET_LOT_SIZE only for native MARKET).
@@ -24,7 +24,7 @@
24
24
  import { unsupported } from "./trading-v2.js";
25
25
  import { asterIocOutcome } from "./aster.js";
26
26
  import { PerpError, isTransportFailure, orderNotSent, orderOutcomeUnknown, sendFailure, unknownActionRemediation } from "../errors.js";
27
- import { alignProtectionPrice, exactUnits, floorSize, requireOnTick, requirePositive, slippagePrice, subDecimal } from "./precision.js";
27
+ import { addDecimal, alignProtectionPrice, exactUnits, floorSize, requireOnTick, requirePositive, slippagePrice, subDecimal } from "./precision.js";
28
28
  /** Default quote for a bare base symbol (= venue spot quoteAssets[0]). */
29
29
  const DEFAULT_QUOTE = "USDT";
30
30
  const SPOT_REMEDIATION = "perp wallet agent rotate aster --can-spot";
@@ -41,9 +41,6 @@ function cmp(a, b) {
41
41
  return -1;
42
42
  return d === "0" ? 0 : 1;
43
43
  }
44
- function addDecimal(a, b) {
45
- return subDecimal(a, b.startsWith("-") ? b.slice(1) : `-${b}`);
46
- }
47
44
  function isZero(v) {
48
45
  return cmp(v, "0") === 0;
49
46
  }
@@ -150,7 +147,7 @@ export class AsterSpotAdapter {
150
147
  }
151
148
  // ── Trading ──
152
149
  async spotMarketOrder(symbol, side, size, opts) {
153
- // §13.2: IOC LIMIT at the protection price, never native MARKET (no price cap).
150
+ // IOC LIMIT at the protection price, never native MARKET (no price cap).
154
151
  // Pre-send (market, size, price, min notional, permission): a failure is a definite "not placed".
155
152
  let m;
156
153
  let qty;
@@ -246,7 +243,7 @@ export class AsterSpotAdapter {
246
243
  }
247
244
  async spotLimitOrder(symbol, side, price, size, opts) {
248
245
  const m = this._resolveTrading(symbol);
249
- // Aster is a legacy family: limit orders keep the GTC default (design §10.7 #6).
246
+ // Aster is a legacy family: limit orders keep the GTC default.
250
247
  const tif = this._mapTif(opts?.tif === undefined ? "GTC" : opts.tif);
251
248
  const px = requireOnTick(price, m.tickSize);
252
249
  const qty = this._sizeFor(m, size, false);
@@ -517,7 +514,7 @@ export class AsterSpotAdapter {
517
514
  });
518
515
  }
519
516
  }
520
- /** §12.4 #8: gate only when the active signer is an agent lacking canSpotTrade. */
517
+ /** gate only when the active signer is an agent lacking canSpotTrade. */
521
518
  _requireSpotPermission() {
522
519
  const meta = this._perp.activeAgentMeta();
523
520
  if (meta !== null && meta.permissions?.canSpotTrade !== true) {
@@ -95,7 +95,7 @@ export interface DelAgentParams {
95
95
  /**
96
96
  * Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
97
97
  *
98
- * OPEN ITEM (docs/TEST-PLAN.md "Aster DelAgent struct — mainnet verification"): the
98
+ * OPEN ITEM (Aster DelAgent struct — mainnet verification): the
99
99
  * public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
100
100
  * document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
101
101
  * revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
@@ -99,7 +99,7 @@ export function buildApproveAgentTypedData(params) {
99
99
  /**
100
100
  * Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
101
101
  *
102
- * OPEN ITEM (docs/TEST-PLAN.md "Aster DelAgent struct — mainnet verification"): the
102
+ * OPEN ITEM (Aster DelAgent struct — mainnet verification): the
103
103
  * public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
104
104
  * document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
105
105
  * revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
@@ -18,7 +18,7 @@
18
18
  * Docs: https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation
19
19
  * Base: https://fapi.asterdex.com
20
20
  */
21
- import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
21
+ import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangePublicTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
22
22
  import type { ResolvedSlippage } from "./slippage.js";
23
23
  import type { EvmSigner } from "../signer/interface.js";
24
24
  import type { AgentMeta } from "../settings.js";
@@ -161,7 +161,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
161
161
  /** PRICE_FILTER / PERCENT_PRICE of an API symbol (exchangeInfo, cached CACHE_TTL). */
162
162
  private _symbolPriceFilters;
163
163
  /**
164
- * Declared protection-price reference (§13.10 #5): the venue mark price from
164
+ * Declared protection-price reference: the venue mark price from
165
165
  * GET /fapi/v3/premiumIndex — the same price PERCENT_PRICE is evaluated against.
166
166
  * No runtime substitute (no mid / last fallback): unavailable → PRICE_STALE.
167
167
  */
@@ -190,12 +190,17 @@ export declare class AsterAdapter implements ExchangeAdapter {
190
190
  bids: [string, string][];
191
191
  asks: [string, string][];
192
192
  }>;
193
- getRecentTrades(symbol: string, limit?: number): Promise<ExchangeTrade[]>;
193
+ getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
194
194
  getFundingHistory(symbol: string, limit?: number): Promise<{
195
195
  time: number;
196
196
  rate: string;
197
197
  price: string | null;
198
198
  }[]>;
199
+ /**
200
+ * Candles over [startTime, endTime]. GET /fapi/v3/klines returns at most 1500 bars per request
201
+ * (1501 → -1130), so the range is read in pages that start after the last bar returned — a long
202
+ * range is never cut to the first page. More than ASTER_KLINE_MAX_PAGES pages → INVALID_PARAMS.
203
+ */
199
204
  getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
200
205
  getBalance(): Promise<ExchangeBalance>;
201
206
  /**
@@ -267,7 +272,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
267
272
  /**
268
273
  * Native modify (PUT /fapi/v3/order, V3 futures docs "Modify Order"): LIMIT orders
269
274
  * only; TIF (incl. GTX) and reduceOnly stay on the order. `size` is the NEW UNFILLED
270
- * quantity (§13.10 #10); the venue's `quantity` is the order total, so
275
+ * quantity; the venue's `quantity` is the order total, so
271
276
  * quantity = size + executedQty (read just before). A fill landing between the read
272
277
  * and the PUT can only shrink the remainder, never over-size it. A venue rejection
273
278
  * leaves the original order untouched (docs).