perp-cli 0.12.17 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +247 -27
  2. package/dist/_stderr-filter.js +0 -1
  3. package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
  4. package/dist/agent-wallet/lighter-keystore.js +92 -10
  5. package/dist/agent-wallet/passphrase.d.ts +1 -1
  6. package/dist/agent-wallet/passphrase.js +16 -3
  7. package/dist/agent-wallet/store.d.ts +37 -4
  8. package/dist/agent-wallet/store.js +132 -0
  9. package/dist/agent-wallet/venue-keystore.d.ts +14 -0
  10. package/dist/agent-wallet/venue-keystore.js +121 -0
  11. package/dist/api/public/hyperliquid.js +4 -4
  12. package/dist/api/public/lighter.js +5 -5
  13. package/dist/api/public/pacifica.d.ts +0 -1
  14. package/dist/api/public/pacifica.js +4 -13
  15. package/dist/api/public/urls.d.ts +9 -1
  16. package/dist/api/public/urls.js +35 -13
  17. package/dist/arb/file-lock.d.ts +11 -0
  18. package/dist/arb/file-lock.js +74 -0
  19. package/dist/arb/index.d.ts +2 -2
  20. package/dist/arb/index.js +2 -2
  21. package/dist/arb/pending-entry.d.ts +32 -0
  22. package/dist/arb/pending-entry.js +77 -0
  23. package/dist/arb/sizing.d.ts +6 -13
  24. package/dist/arb/sizing.js +12 -51
  25. package/dist/arb/state.d.ts +45 -12
  26. package/dist/arb/state.js +214 -42
  27. package/dist/arb/utils.d.ts +20 -6
  28. package/dist/arb/utils.js +43 -39
  29. package/dist/bot/conditions.d.ts +4 -4
  30. package/dist/bot/conditions.js +11 -6
  31. package/dist/bot/config.d.ts +17 -1
  32. package/dist/bot/config.js +48 -12
  33. package/dist/bot/engine.d.ts +61 -2
  34. package/dist/bot/engine.js +610 -144
  35. package/dist/bot/fill-size.d.ts +7 -0
  36. package/dist/bot/fill-size.js +18 -0
  37. package/dist/bot/index.d.ts +1 -1
  38. package/dist/bot/index.js +1 -1
  39. package/dist/bot/perp-order.d.ts +99 -0
  40. package/dist/bot/perp-order.js +299 -0
  41. package/dist/bot/presets.d.ts +7 -0
  42. package/dist/bot/presets.js +17 -0
  43. package/dist/bot/quarantine.d.ts +75 -0
  44. package/dist/bot/quarantine.js +190 -0
  45. package/dist/bot/quote-rules.d.ts +23 -0
  46. package/dist/bot/quote-rules.js +69 -0
  47. package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
  48. package/dist/bot/strategies/avellaneda-mm.js +72 -70
  49. package/dist/bot/strategies/basis-arb.js +2 -0
  50. package/dist/bot/strategies/dca-strategy.d.ts +2 -0
  51. package/dist/bot/strategies/dca-strategy.js +5 -0
  52. package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
  53. package/dist/bot/strategies/funding-arb-strategy.js +571 -380
  54. package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
  55. package/dist/bot/strategies/funding-arb-utils.js +159 -195
  56. package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
  57. package/dist/bot/strategies/funding-arb-v2.js +258 -47
  58. package/dist/bot/strategies/funding-auto.js +215 -194
  59. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
  60. package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
  61. package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
  62. package/dist/bot/strategies/spot-perp-executor.js +319 -120
  63. package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
  64. package/dist/bot/strategies/spot-perp-state.js +70 -0
  65. package/dist/bot/strategy-types.d.ts +6 -0
  66. package/dist/bot/tui/BotDashboard.d.ts +7 -2
  67. package/dist/bot/tui/BotDashboard.js +6 -3
  68. package/dist/bridge-engine.d.ts +120 -19
  69. package/dist/bridge-engine.js +710 -422
  70. package/dist/bridge-signers.d.ts +54 -0
  71. package/dist/bridge-signers.js +161 -0
  72. package/dist/cache.d.ts +4 -1
  73. package/dist/cache.js +11 -0
  74. package/dist/cli-flags.d.ts +50 -0
  75. package/dist/cli-flags.js +104 -0
  76. package/dist/cli-program.d.ts +35 -0
  77. package/dist/cli-program.js +286 -0
  78. package/dist/cli-spec.js +1 -1
  79. package/dist/client-id-tracker.js +11 -2
  80. package/dist/commands/account.d.ts +7 -1
  81. package/dist/commands/account.js +70 -92
  82. package/dist/commands/agent-import.d.ts +114 -0
  83. package/dist/commands/agent-import.js +794 -0
  84. package/dist/commands/agent.d.ts +232 -2
  85. package/dist/commands/agent.js +1858 -955
  86. package/dist/commands/alerts.d.ts +1 -0
  87. package/dist/commands/alerts.js +31 -28
  88. package/dist/commands/arb/index.d.ts +60 -1
  89. package/dist/commands/arb/index.js +381 -384
  90. package/dist/commands/arb-auto.d.ts +132 -4
  91. package/dist/commands/arb-auto.js +1474 -967
  92. package/dist/commands/arb.d.ts +3 -1
  93. package/dist/commands/arb.js +62 -30
  94. package/dist/commands/bot.js +127 -47
  95. package/dist/commands/bridge.d.ts +2 -1
  96. package/dist/commands/bridge.js +339 -192
  97. package/dist/commands/builder.d.ts +55 -0
  98. package/dist/commands/builder.js +387 -0
  99. package/dist/commands/funds-onchain.d.ts +32 -0
  100. package/dist/commands/funds-onchain.js +286 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +939 -245
  103. package/dist/commands/history.js +72 -45
  104. package/dist/commands/init.d.ts +107 -15
  105. package/dist/commands/init.js +1116 -249
  106. package/dist/commands/jobs.d.ts +2 -1
  107. package/dist/commands/jobs.js +77 -15
  108. package/dist/commands/manage.js +136 -91
  109. package/dist/commands/market.d.ts +4 -1
  110. package/dist/commands/market.js +35 -32
  111. package/dist/commands/outcome.d.ts +10 -0
  112. package/dist/commands/outcome.js +396 -0
  113. package/dist/commands/plan.js +52 -12
  114. package/dist/commands/portfolio.d.ts +1 -0
  115. package/dist/commands/portfolio.js +60 -72
  116. package/dist/commands/rebalance.d.ts +2 -1
  117. package/dist/commands/rebalance.js +33 -43
  118. package/dist/commands/risk.js +46 -19
  119. package/dist/commands/settings.d.ts +1 -0
  120. package/dist/commands/settings.js +246 -51
  121. package/dist/commands/trade.d.ts +50 -0
  122. package/dist/commands/trade.js +1943 -695
  123. package/dist/commands/wallet.d.ts +30 -1
  124. package/dist/commands/wallet.js +316 -337
  125. package/dist/config.d.ts +60 -9
  126. package/dist/config.js +252 -82
  127. package/dist/constants.d.ts +29 -4
  128. package/dist/constants.js +62 -20
  129. package/dist/dashboard/server.d.ts +2 -0
  130. package/dist/dashboard/server.js +9 -6
  131. package/dist/dashboard/ui.js +6 -4
  132. package/dist/dashboard/ws-feeds.js +20 -8
  133. package/dist/dex-asset-map.js +5 -3
  134. package/dist/errors.d.ts +122 -0
  135. package/dist/errors.js +194 -0
  136. package/dist/event-stream.js +75 -19
  137. package/dist/evm-master-tx.d.ts +59 -0
  138. package/dist/evm-master-tx.js +154 -0
  139. package/dist/exchanges/adapter-network.d.ts +10 -0
  140. package/dist/exchanges/adapter-network.js +10 -0
  141. package/dist/exchanges/arcus/adapter.d.ts +196 -0
  142. package/dist/exchanges/arcus/adapter.js +1092 -0
  143. package/dist/exchanges/arcus/agent.d.ts +55 -0
  144. package/dist/exchanges/arcus/agent.js +188 -0
  145. package/dist/exchanges/arcus/client.d.ts +63 -0
  146. package/dist/exchanges/arcus/client.js +285 -0
  147. package/dist/exchanges/arcus/public.d.ts +65 -0
  148. package/dist/exchanges/arcus/public.js +138 -0
  149. package/dist/exchanges/arcus/signing.d.ts +176 -0
  150. package/dist/exchanges/arcus/signing.js +288 -0
  151. package/dist/exchanges/arcus/spot-chain.d.ts +60 -0
  152. package/dist/exchanges/arcus/spot-chain.js +241 -0
  153. package/dist/exchanges/arcus/spot-router.d.ts +177 -0
  154. package/dist/exchanges/arcus/spot-router.js +183 -0
  155. package/dist/exchanges/arcus/spot.d.ts +109 -0
  156. package/dist/exchanges/arcus/spot.js +645 -0
  157. package/dist/exchanges/aster-funds.d.ts +127 -0
  158. package/dist/exchanges/aster-funds.js +252 -0
  159. package/dist/exchanges/aster-nonce.d.ts +2 -0
  160. package/dist/exchanges/aster-nonce.js +107 -0
  161. package/dist/exchanges/aster-spot.d.ts +117 -0
  162. package/dist/exchanges/aster-spot.js +686 -0
  163. package/dist/exchanges/aster-typed-data.d.ts +133 -7
  164. package/dist/exchanges/aster-typed-data.js +121 -7
  165. package/dist/exchanges/aster.d.ts +219 -6
  166. package/dist/exchanges/aster.js +1023 -153
  167. package/dist/exchanges/builder-fee.d.ts +254 -0
  168. package/dist/exchanges/builder-fee.js +421 -0
  169. package/dist/exchanges/canonical-symbols.d.ts +32 -0
  170. package/dist/exchanges/canonical-symbols.js +96 -0
  171. package/dist/exchanges/capabilities.d.ts +7 -1
  172. package/dist/exchanges/capabilities.js +7 -0
  173. package/dist/exchanges/hl-signing.d.ts +165 -0
  174. package/dist/exchanges/hl-signing.js +158 -0
  175. package/dist/exchanges/hyperliquid-outcome.d.ts +211 -0
  176. package/dist/exchanges/hyperliquid-outcome.js +646 -0
  177. package/dist/exchanges/hyperliquid-spot.d.ts +44 -5
  178. package/dist/exchanges/hyperliquid-spot.js +308 -117
  179. package/dist/exchanges/hyperliquid.d.ts +462 -57
  180. package/dist/exchanges/hyperliquid.js +1575 -449
  181. package/dist/exchanges/index.d.ts +6 -0
  182. package/dist/exchanges/index.js +4 -0
  183. package/dist/exchanges/interface.d.ts +63 -10
  184. package/dist/exchanges/interface.js +18 -3
  185. package/dist/exchanges/ioc-outcome.d.ts +44 -0
  186. package/dist/exchanges/ioc-outcome.js +57 -0
  187. package/dist/exchanges/legacy-trading-v2.d.ts +39 -0
  188. package/dist/exchanges/legacy-trading-v2.js +940 -0
  189. package/dist/exchanges/lighter-public.d.ts +43 -0
  190. package/dist/exchanges/lighter-public.js +276 -0
  191. package/dist/exchanges/lighter-rh-deposit.d.ts +62 -0
  192. package/dist/exchanges/lighter-rh-deposit.js +185 -0
  193. package/dist/exchanges/lighter-signer.d.ts +123 -0
  194. package/dist/exchanges/lighter-signer.js +215 -0
  195. package/dist/exchanges/lighter-spot.d.ts +91 -13
  196. package/dist/exchanges/lighter-spot.js +595 -233
  197. package/dist/exchanges/lighter.d.ts +611 -39
  198. package/dist/exchanges/lighter.js +1890 -649
  199. package/dist/exchanges/ondo/adapter.d.ts +166 -0
  200. package/dist/exchanges/ondo/adapter.js +835 -0
  201. package/dist/exchanges/ondo/agent.d.ts +31 -0
  202. package/dist/exchanges/ondo/agent.js +101 -0
  203. package/dist/exchanges/ondo/client.d.ts +60 -0
  204. package/dist/exchanges/ondo/client.js +297 -0
  205. package/dist/exchanges/ondo/funds.d.ts +122 -0
  206. package/dist/exchanges/ondo/funds.js +290 -0
  207. package/dist/exchanges/ondo/public.d.ts +95 -0
  208. package/dist/exchanges/ondo/public.js +214 -0
  209. package/dist/exchanges/ondo/spot.d.ts +127 -0
  210. package/dist/exchanges/ondo/spot.js +392 -0
  211. package/dist/exchanges/outcome-interface.d.ts +140 -0
  212. package/dist/exchanges/outcome-interface.js +16 -0
  213. package/dist/exchanges/pacifica-spot.d.ts +83 -0
  214. package/dist/exchanges/pacifica-spot.js +324 -0
  215. package/dist/exchanges/pacifica-typed-data.d.ts +30 -13
  216. package/dist/exchanges/pacifica-typed-data.js +57 -9
  217. package/dist/exchanges/pacifica.d.ts +288 -4
  218. package/dist/exchanges/pacifica.js +1013 -76
  219. package/dist/exchanges/precision.d.ts +47 -0
  220. package/dist/exchanges/precision.js +209 -0
  221. package/dist/exchanges/qfex/adapter.d.ts +341 -0
  222. package/dist/exchanges/qfex/adapter.js +1383 -0
  223. package/dist/exchanges/qfex/agent.d.ts +58 -0
  224. package/dist/exchanges/qfex/agent.js +188 -0
  225. package/dist/exchanges/qfex/client.d.ts +54 -0
  226. package/dist/exchanges/qfex/client.js +138 -0
  227. package/dist/exchanges/qfex/errors.d.ts +70 -0
  228. package/dist/exchanges/qfex/errors.js +236 -0
  229. package/dist/exchanges/qfex/public.d.ts +122 -0
  230. package/dist/exchanges/qfex/public.js +268 -0
  231. package/dist/exchanges/qfex/signing.d.ts +160 -0
  232. package/dist/exchanges/qfex/signing.js +283 -0
  233. package/dist/exchanges/qfex/ws-transport.d.ts +294 -0
  234. package/dist/exchanges/qfex/ws-transport.js +798 -0
  235. package/dist/exchanges/rate-limiter.d.ts +12 -0
  236. package/dist/exchanges/rate-limiter.js +64 -0
  237. package/dist/exchanges/registry.d.ts +14 -2
  238. package/dist/exchanges/registry.js +20 -32
  239. package/dist/exchanges/slippage.d.ts +37 -0
  240. package/dist/exchanges/slippage.js +70 -0
  241. package/dist/exchanges/spot-factory.d.ts +166 -0
  242. package/dist/exchanges/spot-factory.js +431 -0
  243. package/dist/exchanges/spot-interface.d.ts +98 -4
  244. package/dist/exchanges/spot-interface.js +27 -1
  245. package/dist/exchanges/spot-result.d.ts +79 -0
  246. package/dist/exchanges/spot-result.js +273 -0
  247. package/dist/exchanges/trading-v2.d.ts +117 -0
  248. package/dist/exchanges/trading-v2.js +301 -0
  249. package/dist/exchanges/venue-types.d.ts +231 -0
  250. package/dist/exchanges/venue-types.js +87 -0
  251. package/dist/exchanges/venue.d.ts +211 -0
  252. package/dist/exchanges/venue.js +132 -0
  253. package/dist/exchanges/venues/arcus.d.ts +8 -0
  254. package/dist/exchanges/venues/arcus.js +109 -0
  255. package/dist/exchanges/venues/aster.d.ts +49 -0
  256. package/dist/exchanges/venues/aster.js +176 -0
  257. package/dist/exchanges/venues/create-helpers.d.ts +18 -0
  258. package/dist/exchanges/venues/create-helpers.js +199 -0
  259. package/dist/exchanges/venues/hyperliquid.d.ts +23 -0
  260. package/dist/exchanges/venues/hyperliquid.js +126 -0
  261. package/dist/exchanges/venues/index.d.ts +16 -0
  262. package/dist/exchanges/venues/index.js +26 -0
  263. package/dist/exchanges/venues/lighter-family.d.ts +92 -0
  264. package/dist/exchanges/venues/lighter-family.js +166 -0
  265. package/dist/exchanges/venues/lighter-rh.d.ts +7 -0
  266. package/dist/exchanges/venues/lighter-rh.js +58 -0
  267. package/dist/exchanges/venues/lighter.d.ts +6 -0
  268. package/dist/exchanges/venues/lighter.js +55 -0
  269. package/dist/exchanges/venues/ondo.d.ts +34 -0
  270. package/dist/exchanges/venues/ondo.js +140 -0
  271. package/dist/exchanges/venues/pacifica.d.ts +8 -0
  272. package/dist/exchanges/venues/pacifica.js +95 -0
  273. package/dist/exchanges/venues/qfex.d.ts +28 -0
  274. package/dist/exchanges/venues/qfex.js +132 -0
  275. package/dist/execution-log.js +10 -2
  276. package/dist/funding/legacy-public.d.ts +31 -0
  277. package/dist/funding/legacy-public.js +369 -0
  278. package/dist/funding/normalize.d.ts +28 -16
  279. package/dist/funding/normalize.js +61 -29
  280. package/dist/funding/rates.d.ts +46 -11
  281. package/dist/funding/rates.js +228 -277
  282. package/dist/guardrail/perp-guardrail.js +0 -0
  283. package/dist/index.js +156 -684
  284. package/dist/jobs.d.ts +84 -6
  285. package/dist/jobs.js +239 -41
  286. package/dist/landing.d.ts +7 -2
  287. package/dist/landing.js +19 -3
  288. package/dist/mcp-server.d.ts +14 -4
  289. package/dist/mcp-server.js +820 -402
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/pacifica/client.d.ts +41 -10
  293. package/dist/pacifica/client.js +167 -63
  294. package/dist/pacifica/constants.d.ts +0 -1
  295. package/dist/pacifica/constants.js +0 -5
  296. package/dist/pacifica/deposit.d.ts +30 -3
  297. package/dist/pacifica/deposit.js +119 -2
  298. package/dist/pacifica/faucet.d.ts +29 -0
  299. package/dist/pacifica/faucet.js +100 -0
  300. package/dist/pacifica/sign-tx.d.ts +15 -0
  301. package/dist/pacifica/sign-tx.js +41 -0
  302. package/dist/pacifica/types/account.d.ts +28 -4
  303. package/dist/pacifica/types/lake.d.ts +20 -5
  304. package/dist/pacifica/types/lake.js +4 -0
  305. package/dist/pacifica/types/market.d.ts +5 -0
  306. package/dist/pacifica/types/order.d.ts +4 -1
  307. package/dist/pacifica/types/position.d.ts +9 -1
  308. package/dist/plan-executor.d.ts +10 -5
  309. package/dist/plan-executor.js +165 -54
  310. package/dist/position-history.js +13 -0
  311. package/dist/rebalance.d.ts +26 -2
  312. package/dist/rebalance.js +86 -7
  313. package/dist/relay-swap.d.ts +232 -0
  314. package/dist/relay-swap.js +630 -0
  315. package/dist/risk.js +5 -1
  316. package/dist/secret-env.d.ts +15 -0
  317. package/dist/secret-env.js +36 -0
  318. package/dist/settings.d.ts +169 -6
  319. package/dist/settings.js +219 -38
  320. package/dist/signer/ows-evm.d.ts +13 -0
  321. package/dist/signer/ows-evm.js +22 -0
  322. package/dist/smart-order.d.ts +9 -0
  323. package/dist/smart-order.js +53 -8
  324. package/dist/strategies/dca.d.ts +6 -2
  325. package/dist/strategies/dca.js +66 -26
  326. package/dist/strategies/funding-arb.d.ts +11 -1
  327. package/dist/strategies/funding-arb.js +202 -89
  328. package/dist/strategies/grid.d.ts +31 -0
  329. package/dist/strategies/grid.js +89 -11
  330. package/dist/strategies/pending-stop.d.ts +8 -0
  331. package/dist/strategies/pending-stop.js +12 -0
  332. package/dist/strategies/split-order.d.ts +45 -17
  333. package/dist/strategies/split-order.js +157 -91
  334. package/dist/strategies/trailing-stop.d.ts +2 -1
  335. package/dist/strategies/trailing-stop.js +52 -6
  336. package/dist/strategies/twap.d.ts +6 -1
  337. package/dist/strategies/twap.js +39 -11
  338. package/dist/trade-validator.d.ts +22 -0
  339. package/dist/trade-validator.js +119 -15
  340. package/dist/utils/numeric.d.ts +46 -0
  341. package/dist/utils/numeric.js +79 -0
  342. package/dist/utils.d.ts +19 -0
  343. package/dist/utils.js +96 -19
  344. package/dist/withdraw-gate.d.ts +49 -0
  345. package/dist/withdraw-gate.js +131 -0
  346. package/package.json +15 -6
  347. package/skills/perp-cli/SKILL.md +142 -55
  348. package/skills/perp-cli/references/agent-operations.md +110 -56
  349. package/skills/perp-cli/references/commands.md +266 -71
  350. package/skills/perp-cli/references/strategies.md +34 -31
  351. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  352. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  353. package/skills/perp-cli/scripts/preflight.sh +21 -14
  354. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  355. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  356. package/vendor/lighter-signer/SHA256SUMS +2 -0
  357. package/vendor/lighter-signer/VERSION +8 -0
  358. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  359. package/vendor/lighter-signer/wasm_exec.js +575 -0
  360. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  361. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Aster venue definition (design §10.1, §10.8, §10.13 #4).
3
+ * Adapter + public-data code are loaded lazily (§10.10).
4
+ */
5
+ import { BUILDER_FEE_CAPABILITIES } from "../builder-fee.js";
6
+ /** Aster client order id (V3 futures "New Order" `newClientOrderId` rule). */
7
+ export const ASTER_CLIENT_ID_RE = /^[.A-Z:/a-z0-9_-]{1,36}$/;
8
+ const publicData = {
9
+ async fetchFundingRates(net) {
10
+ return (await import("../../funding/legacy-public.js")).legacyPublicData("aster").fetchFundingRates(net);
11
+ },
12
+ async fetchMarkets(net) {
13
+ return (await import("../../funding/legacy-public.js")).legacyPublicData("aster").fetchMarkets(net);
14
+ },
15
+ };
16
+ /**
17
+ * PINNED Aster vault + token addresses (mainnet). A deposit is `approve(vault, exact amount)` then
18
+ * `deposit(address currency, uint256 amount, uint256 broker)` on the vault — never a plain token
19
+ * transfer. Verified 2026-10-05 against:
20
+ * - github.com/asterdex/api-docs demo/aster-deposit-withdrawal.md "Mainnet contract addresses"
21
+ * (BSC 0x1284…7974, Arbitrum 0x9E36…E1d5) and its ethers example (BSC USDT 0x55d3…7955)
22
+ * - docs.asterdex.com/overview/smart-contracts
23
+ * - the verified AstherusVault source on BscScan / Arbiscan (`deposit(address,uint256,uint256)`
24
+ * selector 0x0efe6a8b, `supportToken(address)`, `paused()`, event Deposit)
25
+ * - live `supportToken(token)` non-zero for all four tokens below
26
+ * Token decimals are NOT pinned: they are read on-chain (`decimals()`) before every deposit
27
+ * (BSC USDT / USDC have 18, Arbitrum USDC / USDT have 6).
28
+ */
29
+ export const ASTER_FUNDS_CHAINS = {
30
+ bsc: {
31
+ chainId: 56,
32
+ label: "BNB Chain",
33
+ withdrawChainName: "BSC",
34
+ rpcUrl: "https://bsc-dataseed.bnbchain.org",
35
+ vault: "0x128463A60784c4D3f46c23Af3f65Ed859Ba87974",
36
+ tokens: {
37
+ USDT: "0x55d398326f99059fF775485246999027B3197955",
38
+ USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
39
+ },
40
+ sources: [
41
+ "https://github.com/asterdex/api-docs/blob/master/demo/aster-deposit-withdrawal.md",
42
+ "https://docs.asterdex.com/overview/smart-contracts",
43
+ "https://bscscan.com/address/0x128463A60784c4D3f46c23Af3f65Ed859Ba87974#code",
44
+ ],
45
+ },
46
+ arbitrum: {
47
+ chainId: 42161,
48
+ label: "Arbitrum",
49
+ withdrawChainName: "Arbitrum",
50
+ rpcUrl: "https://arb1.arbitrum.io/rpc",
51
+ vault: "0x9E36CB86a159d479cEd94Fa05036f235Ac40E1d5",
52
+ tokens: {
53
+ USDT: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
54
+ USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
55
+ },
56
+ sources: [
57
+ "https://github.com/asterdex/api-docs/blob/master/demo/aster-deposit-withdrawal.md",
58
+ "https://docs.asterdex.com/overview/smart-contracts",
59
+ "https://arbiscan.io/address/0x9E36CB86a159d479cEd94Fa05036f235Ac40E1d5#code",
60
+ ],
61
+ },
62
+ };
63
+ /** Vault `broker` argument: 1 = perp (futures) account; 1000 = spot account (never used here). */
64
+ export const ASTER_DEPOSIT_BROKER_PERP = 1n;
65
+ /**
66
+ * Why deposit / withdraw are mainnet only (uniform CAPABILITY_UNSUPPORTED on testnet): the vault
67
+ * addresses above are mainnet deployments, and the withdraw signature's `aster chain` is the
68
+ * fixed string "Mainnet" (no testnet value is documented).
69
+ */
70
+ export const ASTER_FUNDS_TESTNET_UNSUPPORTED = {
71
+ reason: "the pinned vault contracts are mainnet deployments and the withdraw signature is defined for \"Mainnet\" only",
72
+ remediation: "Run without -n testnet; fund the Aster testnet account from the testnet app faucet",
73
+ };
74
+ export const asterVenue = {
75
+ id: "aster",
76
+ aliases: ["ast"],
77
+ displayName: "Aster",
78
+ family: "aster",
79
+ masterKeyKind: "evm",
80
+ agentKeyKind: "evm",
81
+ secretStorage: { kind: "ows-wallet", dir: null },
82
+ // Hosts per github.com/asterdex/api-docs V3 (aster-finance-futures-api-v3.md / -testnet.md):
83
+ // REST base "https://fapi.asterdex.com" / "https://fapi.asterdex-testnet.com",
84
+ // WS "wss://fstream.asterdex.com" / "wss://fstream.asterdex-testnet.com"
85
+ // (live 2026-10-02: testnet /fapi/v3/time 200, both WS handshakes open). The old
86
+ // testnet host testnet.asterdex.com does not resolve. AsterAdapter and the public
87
+ // data path (api/public/urls.ts) both read these values — no env override.
88
+ // No explorer / signing chain id in code → null. Markets quote in USDT (aster.ts symbol mapping).
89
+ networks: {
90
+ mainnet: {
91
+ restUrl: "https://fapi.asterdex.com",
92
+ wsUrl: "wss://fstream.asterdex.com",
93
+ explorerUrl: null,
94
+ signingChainId: null,
95
+ settlementChain: "bnb",
96
+ collateral: ["USDT"],
97
+ collateralAssetIndex: null,
98
+ // Default deposit route (BNB Chain USDT); the Arbitrum route is in ASTER_FUNDS_CHAINS.
99
+ rpcUrl: ASTER_FUNDS_CHAINS.bsc.rpcUrl,
100
+ depositPins: {
101
+ chainId: ASTER_FUNDS_CHAINS.bsc.chainId,
102
+ contract: ASTER_FUNDS_CHAINS.bsc.vault,
103
+ token: ASTER_FUNDS_CHAINS.bsc.tokens.USDT,
104
+ sources: ASTER_FUNDS_CHAINS.bsc.sources,
105
+ },
106
+ },
107
+ testnet: {
108
+ restUrl: "https://fapi.asterdex-testnet.com",
109
+ wsUrl: "wss://fstream.asterdex-testnet.com",
110
+ explorerUrl: null,
111
+ signingChainId: null,
112
+ settlementChain: "bnb",
113
+ collateral: ["USDT"],
114
+ collateralAssetIndex: null,
115
+ rpcUrl: null,
116
+ depositPins: null,
117
+ },
118
+ },
119
+ // Per symbol: GET /fapi/v3/fundingInfo lists fundingIntervalHours per market
120
+ // (live 2026-09-30: 4h, 8h, 1h and 2h markets). A flat venue value would be wrong.
121
+ fundingRateBasis: "perMarket",
122
+ settlementIntervalHours: "perMarket",
123
+ fundingVerified: true,
124
+ roles: ["marketData", "account", "trading"],
125
+ capabilities: {
126
+ // Market = IOC LIMIT at mark ± slippage (adapter marketOrder), never native MARKET.
127
+ marketOrder: "slippageBounded",
128
+ // Live exchangeInfo timeInForce: GTC/IOC/GTX/HIDDEN — no FOK. ALO is the common name for GTX.
129
+ timeInForce: ["GTC", "IOC", "ALO", "GTX"],
130
+ reduceOnlyTif: null,
131
+ // V3 futures "New Order": `newClientOrderId` "A unique id among open orders. Automatically
132
+ // generated if not sent. Can only be string following the rule: ^[\\.A-Z\\:/a-z0-9_-]{1,36}$";
133
+ // "Query Order" / "Cancel Order": "Either `orderId` or `origClientOrderId` must be sent."
134
+ clientOrderId: true,
135
+ orderAck: "sync",
136
+ tpsl: "separateOrders",
137
+ // PUT /fapi/v3/order (V3 "Modify Order", LIMIT only).
138
+ amend: "native",
139
+ batchPlaceMax: null,
140
+ marginModes: ["cross", "isolated"],
141
+ // POST /fapi/v3/aster/user-withdraw (mainnet only — exchanges/aster-funds.ts): USDT (default)
142
+ // or USDC to the account owner's own address on BNB Chain or Arbitrum. Needs an API wallet
143
+ // with canWithdraw. USDC: listed by POST /fapi/v3/aster/user-withdraw-info (live 2026-10-13:
144
+ // USDC on chains 1 / 56 / 4663 / 5042 / 42161 with perpMaxWithdrawAmount + withdrawFee).
145
+ withdrawAssets: ["USDT", "USDC"],
146
+ },
147
+ // GET /fapi/v1/exchangeInfo rateLimits: REQUEST_WEIGHT 2400/min
148
+ // (ORDERS 1200/min and 300/10s are separate order-count limits, not modeled).
149
+ // Declared only — per §10.9 the limiter is applied to new venues + lighter-rh.
150
+ rateLimit: { capacity: 2400, refillPerSec: 40, weights: null },
151
+ restrictedRegions: [],
152
+ symbolIdentity: "baseTicker",
153
+ publicData,
154
+ // §12: separate spot account (sapi /api/v3) + /asset/wallet/transfer. Agent signer needs canSpotTrade.
155
+ spot: {
156
+ accountModel: "separate",
157
+ quoteAssets: { mainnet: ["USDT", "USD1"], testnet: ["USDT", "USD1"] },
158
+ capabilities: { limitOrder: true, orderbook: true, cancel: true, transfer: true },
159
+ async createSpot(perp) {
160
+ const [{ AsterAdapter }, { AsterSpotAdapter }] = await Promise.all([
161
+ import("../aster.js"), import("../aster-spot.js"),
162
+ ]);
163
+ if (!(perp instanceof AsterAdapter))
164
+ throw new Error(`aster spot needs an AsterAdapter (got ${perp.name})`);
165
+ const spot = new AsterSpotAdapter(perp);
166
+ await spot.init();
167
+ return spot;
168
+ },
169
+ },
170
+ // PERCENT_PRICE is per symbol (live 2026-10-02: multiplierUp 1.02..1.15), not a venue
171
+ // constant — the adapter rejects a protection price outside the symbol's band
172
+ // (INVALID_PARAMS) at order time; this is only the outer venue-wide bound.
173
+ maxSlippageBps: 5000,
174
+ builderFee: BUILDER_FEE_CAPABILITIES["aster"],
175
+ create: async (ctx) => (await import("./create-helpers.js")).createAster(ctx),
176
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Adapter construction for the pre-existing venues (pacifica / hyperliquid /
3
+ * lighter / lighter-rh / aster) — the single creation path that replaced the
4
+ * three copies in src/index.ts (getAdapter / _initWithOws / getAdapterForExchange)
5
+ * and the MCP server's getOrCreateAdapter (design §10.2).
6
+ *
7
+ * Signer tiers, as before: agent (Tier 1) → OWS master (Tier 2) → raw PK (Tier 3).
8
+ * Which tier signs a given request is still decided inside each adapter.
9
+ *
10
+ * Adapter modules are imported lazily so venue definitions stay cheap to load.
11
+ */
12
+ import type { ExchangeAdapter } from "../interface.js";
13
+ import type { VenueCreateContext } from "../venue.js";
14
+ import type { LighterVenueId } from "./lighter-family.js";
15
+ export declare function createPacifica(ctx: VenueCreateContext): Promise<ExchangeAdapter>;
16
+ export declare function createHyperliquid(ctx: VenueCreateContext): Promise<ExchangeAdapter>;
17
+ export declare function createLighterFamily(venue: LighterVenueId, ctx: VenueCreateContext): Promise<ExchangeAdapter>;
18
+ export declare function createAster(ctx: VenueCreateContext): Promise<ExchangeAdapter>;
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Adapter construction for the pre-existing venues (pacifica / hyperliquid /
3
+ * lighter / lighter-rh / aster) — the single creation path that replaced the
4
+ * three copies in src/index.ts (getAdapter / _initWithOws / getAdapterForExchange)
5
+ * and the MCP server's getOrCreateAdapter (design §10.2).
6
+ *
7
+ * Signer tiers, as before: agent (Tier 1) → OWS master (Tier 2) → raw PK (Tier 3).
8
+ * Which tier signs a given request is still decided inside each adapter.
9
+ *
10
+ * Adapter modules are imported lazily so venue definitions stay cheap to load.
11
+ */
12
+ import { PerpError } from "../../errors.js";
13
+ import { resolveBuilderGate } from "../builder-fee.js";
14
+ /**
15
+ * Legacy-shaped agent meta (aster/hl/pac/lighter/lighter-rh), or null. An agent
16
+ * registered on another network is never attached: --no-agent drops it,
17
+ * otherwise AGENT_NOT_REGISTERED (a mainnet agent must not sign on testnet).
18
+ */
19
+ async function legacyAgentOf(ctx, creds, venue) {
20
+ const agent = creds.agent;
21
+ if (agent === null)
22
+ return null;
23
+ if ("kind" in agent) {
24
+ throw new PerpError("INVALID_PARAMS", `${venue}: agent meta of kind "${agent.kind}" cannot sign for this venue`);
25
+ }
26
+ const { agentNetworkOf, assertAgentNetwork } = await import("../../agent-wallet/store.js");
27
+ if (ctx.noAgent && agentNetworkOf(venue, agent) !== ctx.network)
28
+ return null;
29
+ assertAgentNetwork(venue, agent, ctx.network);
30
+ return agent;
31
+ }
32
+ /**
33
+ * An imported agent (key created on the venue website) belongs to the master address on its
34
+ * record. If a DIFFERENT master wallet is loaded, account reads would show that wallet while the
35
+ * agent trades for its own master — refuse instead of mixing two accounts (Rule #2).
36
+ */
37
+ async function assertImportedAgentMaster(venue, agent, masterAddress) {
38
+ const { agentSourceOf } = await import("../../agent-wallet/store.js");
39
+ if (agentSourceOf(venue, agent) !== "imported")
40
+ return;
41
+ // Pacifica records the master as a Solana address (base58, case-sensitive); EVM venues as 0x hex.
42
+ const recorded = venue === "pacifica" ? agent.userSolanaAddress : agent.userEvmAddress;
43
+ if (recorded === undefined || recorded === "") {
44
+ throw new PerpError("INVALID_PARAMS", `${venue} agent "${agent.agentName}" was imported without a master address`, {
45
+ remediation: `Re-import it: perp wallet agent import ${venue} --agent-name ${agent.agentName} --master-address <master> --replace`,
46
+ });
47
+ }
48
+ const same = venue === "pacifica" ? masterAddress === recorded : masterAddress.toLowerCase() === recorded.toLowerCase();
49
+ if (same)
50
+ return;
51
+ throw new PerpError("INVALID_PARAMS", `${venue} agent "${agent.agentName}" was imported for master ${recorded}, but the loaded master wallet is ${masterAddress}`, {
52
+ remediation: `Select the matching master (--ows <wallet>), or run with --no-agent to use ${masterAddress} directly`,
53
+ });
54
+ }
55
+ function effectiveCredentials(ctx) {
56
+ return ctx.readOnly
57
+ ? { pk: null, owsWallet: null, owsPassphrase: null, owsKeyToken: ctx.credentials.owsKeyToken, agent: null }
58
+ : ctx.credentials;
59
+ }
60
+ /** Passphrase that opens the OWS master wallet. resolveCredentials sets it whenever owsWallet is set. */
61
+ function owsMasterPassphrase(creds) {
62
+ if (creds.owsPassphrase === null) {
63
+ throw new PerpError("PASSPHRASE_REQUIRED", `OWS wallet "${creds.owsWallet}" has no resolved passphrase`, {
64
+ remediation: "Pass --passphrase, set OWS_PASSPHRASE, or --ows-key <token>",
65
+ });
66
+ }
67
+ return creds.owsPassphrase;
68
+ }
69
+ // ── Pacifica ──
70
+ export async function createPacifica(ctx) {
71
+ const creds = effectiveCredentials(ctx);
72
+ const { PacificaAdapter } = await import("../pacifica.js");
73
+ const { parseSolanaKeypair } = await import("../../config.js");
74
+ const { Keypair } = await import("@solana/web3.js");
75
+ const { loadSettings } = await import("../../settings.js");
76
+ const { OwsSolanaSigner } = await import("../../signer/ows-solana.js");
77
+ let adapter;
78
+ if (creds.owsWallet !== null) {
79
+ // Tier 2: OWS master. The keypair is unused for signing once a signer is injected.
80
+ adapter = new PacificaAdapter(Keypair.generate(), ctx.network, true);
81
+ adapter.setSigner(OwsSolanaSigner.create(creds.owsWallet, owsMasterPassphrase(creds)));
82
+ }
83
+ else if (creds.pk !== null) {
84
+ adapter = new PacificaAdapter(parseSolanaKeypair(creds.pk), ctx.network, true);
85
+ }
86
+ else {
87
+ // Read-only: no key material. index.ts:143 Keypair.generate() recorded as out of scope (§10.11).
88
+ adapter = new PacificaAdapter(Keypair.generate(), ctx.network, false);
89
+ }
90
+ const agent = await legacyAgentOf(ctx, creds, "pacifica");
91
+ if (agent !== null && !ctx.noAgent) {
92
+ // A loaded master (OWS / raw key) must be the master the imported agent was created for.
93
+ if (creds.owsWallet !== null || creds.pk !== null)
94
+ await assertImportedAgentMaster("pacifica", agent, adapter.publicKey);
95
+ // Pacifica agent wallets are created with an empty passphrase (runPacApproveFlow).
96
+ adapter.setAgentSigner(agent, OwsSolanaSigner.create(agent.agentWalletName, ""));
97
+ }
98
+ if (ctx.noAgent)
99
+ adapter.setNoAgent(true);
100
+ // Builder code: only settings builder.pacifica (off by default) + a confirmed approval.
101
+ const pac = adapter;
102
+ pac.builderFee = resolveBuilderGate("pacifica", ctx, loadSettings().builder, t => pac.builderApprovalOf(t), () => pac.publicKey);
103
+ return adapter;
104
+ }
105
+ // ── Hyperliquid ──
106
+ export async function createHyperliquid(ctx) {
107
+ const creds = effectiveCredentials(ctx);
108
+ const { HyperliquidAdapter } = await import("../hyperliquid.js");
109
+ const { OwsEvmSigner } = await import("../../signer/ows-evm.js");
110
+ const isTestnet = ctx.network === "testnet";
111
+ const adapter = new HyperliquidAdapter(creds.pk ?? undefined, isTestnet);
112
+ if (ctx.hlDex !== null)
113
+ adapter.setDex(ctx.hlDex);
114
+ if (creds.owsWallet !== null)
115
+ adapter.setSigner(OwsEvmSigner.create(creds.owsWallet, owsMasterPassphrase(creds)));
116
+ const agent = await legacyAgentOf(ctx, creds, "hyperliquid");
117
+ // No master on this machine (e.g. an agent imported from the HL website): account reads use the
118
+ // master's public address from the agent record; the agent key signs trades.
119
+ if (agent !== null && !ctx.noAgent && creds.owsWallet === null && creds.pk === null)
120
+ adapter.setAddress(agent.userEvmAddress);
121
+ await adapter.init();
122
+ if (agent !== null && !ctx.noAgent && adapter.address)
123
+ await assertImportedAgentMaster("hyperliquid", agent, adapter.address);
124
+ // No implicit referral signing on creation (read-only paths share this path):
125
+ // referral is the explicit `perp -e hyperliquid wallet manage referral set`.
126
+ if (agent !== null) {
127
+ // HL agent wallets are created with an empty passphrase (runHlApproveFlow).
128
+ adapter.setAgentSigner(agent, OwsEvmSigner.create(agent.agentWalletName, ""));
129
+ }
130
+ if (ctx.noAgent)
131
+ adapter.setNoAgent(true);
132
+ // Builder fee: only settings builder.hyperliquid (off by default) + a confirmed master approval.
133
+ const { loadSettings } = await import("../../settings.js");
134
+ adapter.builderFee = resolveBuilderGate("hyperliquid", ctx, loadSettings().builder, t => adapter.builderApprovalOf(t), () => adapter.address);
135
+ return adapter;
136
+ }
137
+ // ── Lighter family ──
138
+ export async function createLighterFamily(venue, ctx) {
139
+ const creds = effectiveCredentials(ctx);
140
+ if (venue === "lighter-rh" && creds.pk !== null) {
141
+ // Design §10.3: the Lighter RH master key is an OWS wallet only — no env / raw-PK tier.
142
+ throw new PerpError("NO_ENV_TIER", "Lighter RH does not accept a raw private key (env / --private-key / local wallet)", {
143
+ remediation: "Import the key into OWS (perp wallet import, key via hidden prompt / stdin) and run with --ows <wallet>, or register an agent: perp wallet agent approve lighter-rh",
144
+ });
145
+ }
146
+ const { LighterAdapter } = await import("../lighter.js");
147
+ const { OwsEvmSigner } = await import("../../signer/ows-evm.js");
148
+ const adapter = LighterAdapter.forVenue(venue, creds.pk ?? "", ctx.network === "testnet");
149
+ if (creds.owsWallet !== null)
150
+ adapter.setSigner(OwsEvmSigner.create(creds.owsWallet, owsMasterPassphrase(creds)));
151
+ const agent = await legacyAgentOf(ctx, creds, venue);
152
+ if (agent !== null && !ctx.noAgent) {
153
+ if (typeof agent.accountIndex !== "number" || typeof agent.apiKeyIndex !== "number") {
154
+ throw new PerpError("AGENT_NOT_REGISTERED", `${venue} agent "${agent.agentName}" has no accountIndex/apiKeyIndex`, {
155
+ remediation: `perp wallet agent approve ${venue} --rotate`,
156
+ });
157
+ }
158
+ // SSOT Rule #3: the agent L2 key lives only in the venue keystore.
159
+ const { loadLighterFamilyKey } = await import("../../agent-wallet/lighter-keystore.js");
160
+ adapter.setAgentSigner(agent, loadLighterFamilyKey(venue, ctx.network, agent.accountIndex, agent.apiKeyIndex, ""));
161
+ // No master on this machine (e.g. an API key imported from the website): account reads use the
162
+ // account owner's L1 address recorded on the agent; the API key signs trades.
163
+ if (creds.owsWallet === null && creds.pk === null)
164
+ adapter.setAddress(agent.userEvmAddress);
165
+ }
166
+ if (ctx.noAgent)
167
+ adapter.setNoAgent(true);
168
+ await adapter.init();
169
+ if (agent !== null && !ctx.noAgent && adapter.address)
170
+ await assertImportedAgentMaster(venue, agent, adapter.address);
171
+ // No implicit referral signing on creation: `perp -e lighter wallet manage referral set`.
172
+ return adapter;
173
+ }
174
+ // ── Aster ──
175
+ export async function createAster(ctx) {
176
+ const creds = effectiveCredentials(ctx);
177
+ const { AsterAdapter } = await import("../aster.js");
178
+ const adapter = new AsterAdapter(creds.pk ?? undefined, ctx.network === "testnet");
179
+ await adapter.init();
180
+ if (creds.owsWallet !== null) {
181
+ const { OwsEvmSigner } = await import("../../signer/ows-evm.js");
182
+ adapter.setMasterSigner(OwsEvmSigner.create(creds.owsWallet, owsMasterPassphrase(creds)));
183
+ }
184
+ const agent = await legacyAgentOf(ctx, creds, "aster");
185
+ if (agent !== null) {
186
+ const { agentSigningStrategyFor } = await import("../../agent-wallet/signing-strategy.js");
187
+ const { agentSourceOf } = await import("../../agent-wallet/store.js");
188
+ // Empty token = no OWS API-key policy gating (legacy behavior). An imported agent's OWS wallet
189
+ // has no API key / policy and an empty passphrase, so it is always opened with "".
190
+ const token = agentSourceOf("aster", agent) === "imported" ? "" : (creds.owsKeyToken ?? "");
191
+ adapter.setAgent(agent, agentSigningStrategyFor(agent, token));
192
+ }
193
+ if (ctx.noAgent)
194
+ adapter.setNoAgent(true);
195
+ // Builder fee: only settings builder.aster (off by default) + a confirmed master approval.
196
+ const { loadSettings } = await import("../../settings.js");
197
+ adapter.builderFee = resolveBuilderGate("aster", ctx, loadSettings().builder, t => adapter.builderApprovalOf(t), () => adapter.userAddress);
198
+ return adapter;
199
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Hyperliquid venue definition (design §10.1, §10.8, §10.13 #4).
3
+ * HIP-3 dexes are not venues: they are selected via VenueCreateContext.hlDex.
4
+ * Adapter + public-data code are loaded lazily (§10.10).
5
+ */
6
+ import type { Network, VenueDefinition } from "../venue.js";
7
+ /**
8
+ * Per-network parameters of Hyperliquid *user-signed* actions (approveAgent,
9
+ * userSetAbstraction, …) — EIP-712 domain "HyperliquidSignTransaction".
10
+ * `hyperliquidChain` selects the HL environment and prevents cross-network
11
+ * replay; `signatureChainId` is the wallet signing chain and must equal the
12
+ * domain chainId. Values mirror hyperliquid-python-sdk `sign_user_signed_action`
13
+ * ("Mainnet"/"Testnet") and the exchange-endpoint docs ("0xa4b1" Arbitrum One;
14
+ * testnet signs on Arbitrum Sepolia 0x66eee as the SDK does).
15
+ */
16
+ export declare const HL_USER_SIGNED: Record<Network, {
17
+ hyperliquidChain: "Mainnet" | "Testnet";
18
+ signatureChainIdHex: string;
19
+ signatureChainId: number;
20
+ }>;
21
+ /** Hyperliquid client order id (cloid): "0x" + 32 lowercase hex chars (128 bits). */
22
+ export declare const HL_CLOID_RE: RegExp;
23
+ export declare const hyperliquidVenue: VenueDefinition;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Hyperliquid venue definition (design §10.1, §10.8, §10.13 #4).
3
+ * HIP-3 dexes are not venues: they are selected via VenueCreateContext.hlDex.
4
+ * Adapter + public-data code are loaded lazily (§10.10).
5
+ */
6
+ import { BUILDER_FEE_CAPABILITIES } from "../builder-fee.js";
7
+ /**
8
+ * Per-network parameters of Hyperliquid *user-signed* actions (approveAgent,
9
+ * userSetAbstraction, …) — EIP-712 domain "HyperliquidSignTransaction".
10
+ * `hyperliquidChain` selects the HL environment and prevents cross-network
11
+ * replay; `signatureChainId` is the wallet signing chain and must equal the
12
+ * domain chainId. Values mirror hyperliquid-python-sdk `sign_user_signed_action`
13
+ * ("Mainnet"/"Testnet") and the exchange-endpoint docs ("0xa4b1" Arbitrum One;
14
+ * testnet signs on Arbitrum Sepolia 0x66eee as the SDK does).
15
+ */
16
+ export const HL_USER_SIGNED = {
17
+ mainnet: { hyperliquidChain: "Mainnet", signatureChainIdHex: "0xa4b1", signatureChainId: 42161 },
18
+ testnet: { hyperliquidChain: "Testnet", signatureChainIdHex: "0x66eee", signatureChainId: 421614 },
19
+ };
20
+ /** Hyperliquid client order id (cloid): "0x" + 32 lowercase hex chars (128 bits). */
21
+ export const HL_CLOID_RE = /^0x[0-9a-f]{32}$/;
22
+ const publicData = {
23
+ async fetchFundingRates(net) {
24
+ return (await import("../../funding/legacy-public.js")).legacyPublicData("hyperliquid").fetchFundingRates(net);
25
+ },
26
+ async fetchMarkets(net) {
27
+ return (await import("../../funding/legacy-public.js")).legacyPublicData("hyperliquid").fetchMarkets(net);
28
+ },
29
+ };
30
+ export const hyperliquidVenue = {
31
+ id: "hyperliquid",
32
+ aliases: ["hl"],
33
+ displayName: "Hyperliquid",
34
+ family: "hyperliquid",
35
+ masterKeyKind: "evm",
36
+ agentKeyKind: "evm",
37
+ secretStorage: { kind: "ows-wallet", dir: null },
38
+ // REST: src/exchanges/hyperliquid.ts; mainnet WS: src/dashboard/ws-feeds.ts.
39
+ // Testnet WS is not in code → null. signingChainId: L1 action phantom-agent domain (hyperliquid.ts).
40
+ networks: {
41
+ mainnet: {
42
+ restUrl: "https://api.hyperliquid.xyz",
43
+ wsUrl: "wss://api.hyperliquid.xyz/ws",
44
+ explorerUrl: null,
45
+ signingChainId: 1337,
46
+ settlementChain: "hyperliquid",
47
+ collateral: ["USDC"],
48
+ collateralAssetIndex: null,
49
+ rpcUrl: null,
50
+ depositPins: null,
51
+ },
52
+ testnet: {
53
+ restUrl: "https://api.hyperliquid-testnet.xyz",
54
+ wsUrl: null,
55
+ explorerUrl: null,
56
+ signingChainId: 1337,
57
+ settlementChain: "hyperliquid",
58
+ collateral: ["USDC"],
59
+ collateralAssetIndex: null,
60
+ rpcUrl: null,
61
+ depositPins: null,
62
+ },
63
+ },
64
+ fundingRateBasis: { kind: "perHours", hours: 1 },
65
+ settlementIntervalHours: 1,
66
+ fundingVerified: true,
67
+ roles: ["marketData", "account", "trading"],
68
+ // marketOrder: IOC limit at a protection price (§13.2/§13.10 #5). Declared reference
69
+ // price = l2Book mid ((best bid + best ask) / 2) for native perps, HIP-3 and spot —
70
+ // no runtime substitute; a one-sided/empty book → PRICE_STALE. Rounding: 5 significant
71
+ // figures, max 6 − szDecimals (perp) / 8 − szDecimals (spot) decimals, toward crossing.
72
+ // tpsl stays "separateOrders": HL `normalTpsl` grouping was evaluated (§13.10 #12) and not
73
+ // used — its children have a fixed size equal to the parent and are fully cancelled when
74
+ // a partially filled parent is cancelled (HL docs, TP/SL orders), so a partially filled
75
+ // IOC entry would be left unprotected; separateOrders sizes TP/SL to the verified fill.
76
+ capabilities: {
77
+ marketOrder: "slippageBounded",
78
+ timeInForce: ["GTC", "IOC", "ALO"],
79
+ reduceOnlyTif: null,
80
+ // HL docs exchange-endpoint "Place an order": `c` "Cloid (client order id)" — "an optional
81
+ // 128 bit hex string, e.g. 0x1234567890abcdef1234567890abcdef"; cancelled by `cancelByCloid`,
82
+ // queried by info `orderStatus` (`oid` "u64 … or 16-byte hex string representing the client
83
+ // order id"). Native perps and HIP-3 dexes alike (the global asset id selects the dex).
84
+ clientOrderId: true,
85
+ orderAck: "sync",
86
+ tpsl: "separateOrders",
87
+ amend: "native",
88
+ batchPlaceMax: null,
89
+ marginModes: ["cross", "isolated"],
90
+ withdrawAssets: ["USDC"],
91
+ },
92
+ // HL docs "Rate limits and user limits": REST requests share an aggregated
93
+ // weight of 1200/min per IP. Exchange actions weigh 1 (unbatched); light info
94
+ // requests 2; most info requests 20; userRole 60.
95
+ // Declared only — per §10.9 the limiter is applied to new venues + lighter-rh.
96
+ rateLimit: {
97
+ capacity: 1200,
98
+ refillPerSec: 20,
99
+ weights: {
100
+ l2Book: 2, allMids: 2, clearinghouseState: 2, orderStatus: 2, spotClearinghouseState: 2, exchangeStatus: 2,
101
+ userRole: 60,
102
+ },
103
+ },
104
+ restrictedRegions: [],
105
+ symbolIdentity: "baseTicker",
106
+ publicData,
107
+ // §12: spot USDC is shared with perp margin when the account is unified (isUnifiedAccount, read at init).
108
+ spot: {
109
+ accountModel: "runtime",
110
+ quoteAssets: { mainnet: ["USDC"], testnet: ["USDC"] },
111
+ capabilities: { limitOrder: true, orderbook: true, cancel: true, transfer: true },
112
+ async createSpot(perp) {
113
+ const [{ HyperliquidAdapter }, { HyperliquidSpotAdapter }] = await Promise.all([
114
+ import("../hyperliquid.js"), import("../hyperliquid-spot.js"),
115
+ ]);
116
+ if (!(perp instanceof HyperliquidAdapter))
117
+ throw new Error(`hyperliquid spot needs a HyperliquidAdapter (got ${perp.name})`);
118
+ const spot = new HyperliquidSpotAdapter(perp);
119
+ await spot.init();
120
+ return spot;
121
+ },
122
+ },
123
+ maxSlippageBps: 5000,
124
+ builderFee: BUILDER_FEE_CAPABILITIES["hyperliquid"],
125
+ create: async (ctx) => (await import("./create-helpers.js")).createHyperliquid(ctx),
126
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Venue registry bootstrap: registers every venue definition exactly once.
3
+ * Importing this module (for its side effect) makes getVenue()/listVenues() usable.
4
+ */
5
+ import { arcusVenue } from "./arcus.js";
6
+ import { asterVenue } from "./aster.js";
7
+ import { hyperliquidVenue } from "./hyperliquid.js";
8
+ import { lighterRhVenue } from "./lighter-rh.js";
9
+ import { lighterVenue } from "./lighter.js";
10
+ import { ondoVenue } from "./ondo.js";
11
+ import { pacificaVenue } from "./pacifica.js";
12
+ import { qfexVenue } from "./qfex.js";
13
+ export declare const ALL_VENUES: readonly [import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition];
14
+ /** Idempotent: registers all venues on first call, no-op afterwards. */
15
+ export declare function ensureVenuesRegistered(): void;
16
+ export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Venue registry bootstrap: registers every venue definition exactly once.
3
+ * Importing this module (for its side effect) makes getVenue()/listVenues() usable.
4
+ */
5
+ import { registerVenue, tryResolveVenueId } from "../venue.js";
6
+ import { arcusVenue } from "./arcus.js";
7
+ import { asterVenue } from "./aster.js";
8
+ import { hyperliquidVenue } from "./hyperliquid.js";
9
+ import { lighterRhVenue } from "./lighter-rh.js";
10
+ import { lighterVenue } from "./lighter.js";
11
+ import { ondoVenue } from "./ondo.js";
12
+ import { pacificaVenue } from "./pacifica.js";
13
+ import { qfexVenue } from "./qfex.js";
14
+ export const ALL_VENUES = [
15
+ pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue,
16
+ lighterRhVenue, ondoVenue, arcusVenue, qfexVenue,
17
+ ];
18
+ /** Idempotent: registers all venues on first call, no-op afterwards. */
19
+ export function ensureVenuesRegistered() {
20
+ for (const def of ALL_VENUES) {
21
+ if (tryResolveVenueId(def.id) === null)
22
+ registerVenue(def);
23
+ }
24
+ }
25
+ ensureVenuesRegistered();
26
+ export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, };