perp-cli 0.12.17 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/README.md +247 -27
  2. package/dist/_stderr-filter.js +0 -1
  3. package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
  4. package/dist/agent-wallet/lighter-keystore.js +92 -10
  5. package/dist/agent-wallet/passphrase.d.ts +1 -1
  6. package/dist/agent-wallet/passphrase.js +16 -3
  7. package/dist/agent-wallet/store.d.ts +37 -4
  8. package/dist/agent-wallet/store.js +132 -0
  9. package/dist/agent-wallet/venue-keystore.d.ts +14 -0
  10. package/dist/agent-wallet/venue-keystore.js +121 -0
  11. package/dist/api/public/hyperliquid.js +4 -4
  12. package/dist/api/public/lighter.js +5 -5
  13. package/dist/api/public/pacifica.d.ts +0 -1
  14. package/dist/api/public/pacifica.js +4 -13
  15. package/dist/api/public/urls.d.ts +9 -1
  16. package/dist/api/public/urls.js +35 -13
  17. package/dist/arb/file-lock.d.ts +11 -0
  18. package/dist/arb/file-lock.js +74 -0
  19. package/dist/arb/index.d.ts +2 -2
  20. package/dist/arb/index.js +2 -2
  21. package/dist/arb/pending-entry.d.ts +32 -0
  22. package/dist/arb/pending-entry.js +77 -0
  23. package/dist/arb/sizing.d.ts +6 -13
  24. package/dist/arb/sizing.js +12 -51
  25. package/dist/arb/state.d.ts +45 -12
  26. package/dist/arb/state.js +214 -42
  27. package/dist/arb/utils.d.ts +20 -6
  28. package/dist/arb/utils.js +43 -39
  29. package/dist/bot/conditions.d.ts +4 -4
  30. package/dist/bot/conditions.js +11 -6
  31. package/dist/bot/config.d.ts +17 -1
  32. package/dist/bot/config.js +48 -12
  33. package/dist/bot/engine.d.ts +61 -2
  34. package/dist/bot/engine.js +610 -144
  35. package/dist/bot/fill-size.d.ts +7 -0
  36. package/dist/bot/fill-size.js +18 -0
  37. package/dist/bot/index.d.ts +1 -1
  38. package/dist/bot/index.js +1 -1
  39. package/dist/bot/perp-order.d.ts +99 -0
  40. package/dist/bot/perp-order.js +299 -0
  41. package/dist/bot/presets.d.ts +7 -0
  42. package/dist/bot/presets.js +17 -0
  43. package/dist/bot/quarantine.d.ts +75 -0
  44. package/dist/bot/quarantine.js +190 -0
  45. package/dist/bot/quote-rules.d.ts +23 -0
  46. package/dist/bot/quote-rules.js +69 -0
  47. package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
  48. package/dist/bot/strategies/avellaneda-mm.js +72 -70
  49. package/dist/bot/strategies/basis-arb.js +2 -0
  50. package/dist/bot/strategies/dca-strategy.d.ts +2 -0
  51. package/dist/bot/strategies/dca-strategy.js +5 -0
  52. package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
  53. package/dist/bot/strategies/funding-arb-strategy.js +571 -380
  54. package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
  55. package/dist/bot/strategies/funding-arb-utils.js +159 -195
  56. package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
  57. package/dist/bot/strategies/funding-arb-v2.js +258 -47
  58. package/dist/bot/strategies/funding-auto.js +215 -194
  59. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
  60. package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
  61. package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
  62. package/dist/bot/strategies/spot-perp-executor.js +319 -120
  63. package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
  64. package/dist/bot/strategies/spot-perp-state.js +70 -0
  65. package/dist/bot/strategy-types.d.ts +6 -0
  66. package/dist/bot/tui/BotDashboard.d.ts +7 -2
  67. package/dist/bot/tui/BotDashboard.js +6 -3
  68. package/dist/bridge-engine.d.ts +120 -19
  69. package/dist/bridge-engine.js +710 -422
  70. package/dist/bridge-signers.d.ts +54 -0
  71. package/dist/bridge-signers.js +161 -0
  72. package/dist/cache.d.ts +4 -1
  73. package/dist/cache.js +11 -0
  74. package/dist/cli-flags.d.ts +50 -0
  75. package/dist/cli-flags.js +104 -0
  76. package/dist/cli-program.d.ts +35 -0
  77. package/dist/cli-program.js +303 -0
  78. package/dist/cli-spec.js +1 -1
  79. package/dist/client-id-tracker.js +11 -2
  80. package/dist/commands/account.d.ts +7 -1
  81. package/dist/commands/account.js +70 -92
  82. package/dist/commands/agent-import.d.ts +114 -0
  83. package/dist/commands/agent-import.js +794 -0
  84. package/dist/commands/agent.d.ts +232 -2
  85. package/dist/commands/agent.js +1858 -955
  86. package/dist/commands/alerts.d.ts +1 -0
  87. package/dist/commands/alerts.js +31 -28
  88. package/dist/commands/arb/index.d.ts +60 -1
  89. package/dist/commands/arb/index.js +381 -384
  90. package/dist/commands/arb-auto.d.ts +132 -4
  91. package/dist/commands/arb-auto.js +1474 -967
  92. package/dist/commands/arb.d.ts +3 -1
  93. package/dist/commands/arb.js +62 -30
  94. package/dist/commands/bot.js +127 -47
  95. package/dist/commands/bridge.d.ts +2 -1
  96. package/dist/commands/bridge.js +339 -192
  97. package/dist/commands/builder.d.ts +55 -0
  98. package/dist/commands/builder.js +387 -0
  99. package/dist/commands/funds-onchain.d.ts +32 -0
  100. package/dist/commands/funds-onchain.js +248 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +925 -245
  103. package/dist/commands/history.js +102 -54
  104. package/dist/commands/init.d.ts +107 -15
  105. package/dist/commands/init.js +1116 -249
  106. package/dist/commands/jobs.d.ts +2 -1
  107. package/dist/commands/jobs.js +77 -15
  108. package/dist/commands/manage.js +136 -91
  109. package/dist/commands/market.d.ts +4 -1
  110. package/dist/commands/market.js +35 -32
  111. package/dist/commands/outcome.d.ts +10 -0
  112. package/dist/commands/outcome.js +396 -0
  113. package/dist/commands/plan.js +52 -12
  114. package/dist/commands/portfolio.d.ts +1 -0
  115. package/dist/commands/portfolio.js +60 -72
  116. package/dist/commands/rebalance.d.ts +2 -1
  117. package/dist/commands/rebalance.js +33 -43
  118. package/dist/commands/risk.js +46 -19
  119. package/dist/commands/settings.d.ts +1 -0
  120. package/dist/commands/settings.js +246 -51
  121. package/dist/commands/trade.d.ts +50 -0
  122. package/dist/commands/trade.js +1943 -695
  123. package/dist/commands/wallet.d.ts +30 -1
  124. package/dist/commands/wallet.js +357 -459
  125. package/dist/config.d.ts +60 -9
  126. package/dist/config.js +252 -82
  127. package/dist/constants.d.ts +29 -4
  128. package/dist/constants.js +62 -20
  129. package/dist/dashboard/server.d.ts +2 -0
  130. package/dist/dashboard/server.js +9 -6
  131. package/dist/dashboard/ui.js +6 -4
  132. package/dist/dashboard/ws-feeds.js +20 -8
  133. package/dist/dex-asset-map.js +5 -3
  134. package/dist/errors.d.ts +122 -0
  135. package/dist/errors.js +194 -0
  136. package/dist/event-stream.js +75 -19
  137. package/dist/evm-master-tx.d.ts +59 -0
  138. package/dist/evm-master-tx.js +154 -0
  139. package/dist/exchanges/adapter-network.d.ts +10 -0
  140. package/dist/exchanges/adapter-network.js +10 -0
  141. package/dist/exchanges/arcus/adapter.d.ts +196 -0
  142. package/dist/exchanges/arcus/adapter.js +1092 -0
  143. package/dist/exchanges/arcus/agent.d.ts +55 -0
  144. package/dist/exchanges/arcus/agent.js +188 -0
  145. package/dist/exchanges/arcus/client.d.ts +63 -0
  146. package/dist/exchanges/arcus/client.js +285 -0
  147. package/dist/exchanges/arcus/public.d.ts +65 -0
  148. package/dist/exchanges/arcus/public.js +138 -0
  149. package/dist/exchanges/arcus/signing.d.ts +176 -0
  150. package/dist/exchanges/arcus/signing.js +288 -0
  151. package/dist/exchanges/arcus/spot-chain.d.ts +60 -0
  152. package/dist/exchanges/arcus/spot-chain.js +241 -0
  153. package/dist/exchanges/arcus/spot-router.d.ts +177 -0
  154. package/dist/exchanges/arcus/spot-router.js +183 -0
  155. package/dist/exchanges/arcus/spot.d.ts +109 -0
  156. package/dist/exchanges/arcus/spot.js +645 -0
  157. package/dist/exchanges/aster-funds.d.ts +127 -0
  158. package/dist/exchanges/aster-funds.js +252 -0
  159. package/dist/exchanges/aster-nonce.d.ts +2 -0
  160. package/dist/exchanges/aster-nonce.js +107 -0
  161. package/dist/exchanges/aster-spot.d.ts +117 -0
  162. package/dist/exchanges/aster-spot.js +686 -0
  163. package/dist/exchanges/aster-typed-data.d.ts +133 -7
  164. package/dist/exchanges/aster-typed-data.js +121 -7
  165. package/dist/exchanges/aster.d.ts +240 -6
  166. package/dist/exchanges/aster.js +1139 -195
  167. package/dist/exchanges/builder-fee.d.ts +254 -0
  168. package/dist/exchanges/builder-fee.js +421 -0
  169. package/dist/exchanges/canonical-symbols.d.ts +32 -0
  170. package/dist/exchanges/canonical-symbols.js +96 -0
  171. package/dist/exchanges/capabilities.d.ts +7 -1
  172. package/dist/exchanges/capabilities.js +7 -0
  173. package/dist/exchanges/hl-signing.d.ts +165 -0
  174. package/dist/exchanges/hl-signing.js +158 -0
  175. package/dist/exchanges/hyperliquid-outcome.d.ts +211 -0
  176. package/dist/exchanges/hyperliquid-outcome.js +646 -0
  177. package/dist/exchanges/hyperliquid-spot.d.ts +44 -5
  178. package/dist/exchanges/hyperliquid-spot.js +308 -117
  179. package/dist/exchanges/hyperliquid.d.ts +462 -57
  180. package/dist/exchanges/hyperliquid.js +1575 -449
  181. package/dist/exchanges/index.d.ts +6 -0
  182. package/dist/exchanges/index.js +4 -0
  183. package/dist/exchanges/interface.d.ts +63 -10
  184. package/dist/exchanges/interface.js +18 -3
  185. package/dist/exchanges/ioc-outcome.d.ts +44 -0
  186. package/dist/exchanges/ioc-outcome.js +57 -0
  187. package/dist/exchanges/legacy-trading-v2.d.ts +39 -0
  188. package/dist/exchanges/legacy-trading-v2.js +940 -0
  189. package/dist/exchanges/lighter-public.d.ts +43 -0
  190. package/dist/exchanges/lighter-public.js +276 -0
  191. package/dist/exchanges/lighter-rh-deposit.d.ts +62 -0
  192. package/dist/exchanges/lighter-rh-deposit.js +185 -0
  193. package/dist/exchanges/lighter-signer.d.ts +123 -0
  194. package/dist/exchanges/lighter-signer.js +215 -0
  195. package/dist/exchanges/lighter-spot.d.ts +91 -13
  196. package/dist/exchanges/lighter-spot.js +595 -233
  197. package/dist/exchanges/lighter.d.ts +611 -39
  198. package/dist/exchanges/lighter.js +1890 -649
  199. package/dist/exchanges/ondo/adapter.d.ts +152 -0
  200. package/dist/exchanges/ondo/adapter.js +811 -0
  201. package/dist/exchanges/ondo/agent.d.ts +31 -0
  202. package/dist/exchanges/ondo/agent.js +101 -0
  203. package/dist/exchanges/ondo/client.d.ts +60 -0
  204. package/dist/exchanges/ondo/client.js +297 -0
  205. package/dist/exchanges/ondo/funds.d.ts +95 -0
  206. package/dist/exchanges/ondo/funds.js +198 -0
  207. package/dist/exchanges/ondo/public.d.ts +95 -0
  208. package/dist/exchanges/ondo/public.js +214 -0
  209. package/dist/exchanges/ondo/spot.d.ts +127 -0
  210. package/dist/exchanges/ondo/spot.js +392 -0
  211. package/dist/exchanges/outcome-interface.d.ts +140 -0
  212. package/dist/exchanges/outcome-interface.js +16 -0
  213. package/dist/exchanges/pacifica-spot.d.ts +83 -0
  214. package/dist/exchanges/pacifica-spot.js +324 -0
  215. package/dist/exchanges/pacifica-typed-data.d.ts +30 -13
  216. package/dist/exchanges/pacifica-typed-data.js +57 -9
  217. package/dist/exchanges/pacifica.d.ts +293 -4
  218. package/dist/exchanges/pacifica.js +1044 -90
  219. package/dist/exchanges/precision.d.ts +47 -0
  220. package/dist/exchanges/precision.js +209 -0
  221. package/dist/exchanges/qfex/adapter.d.ts +341 -0
  222. package/dist/exchanges/qfex/adapter.js +1386 -0
  223. package/dist/exchanges/qfex/agent.d.ts +58 -0
  224. package/dist/exchanges/qfex/agent.js +188 -0
  225. package/dist/exchanges/qfex/client.d.ts +54 -0
  226. package/dist/exchanges/qfex/client.js +138 -0
  227. package/dist/exchanges/qfex/errors.d.ts +70 -0
  228. package/dist/exchanges/qfex/errors.js +236 -0
  229. package/dist/exchanges/qfex/public.d.ts +122 -0
  230. package/dist/exchanges/qfex/public.js +268 -0
  231. package/dist/exchanges/qfex/signing.d.ts +160 -0
  232. package/dist/exchanges/qfex/signing.js +283 -0
  233. package/dist/exchanges/qfex/ws-transport.d.ts +294 -0
  234. package/dist/exchanges/qfex/ws-transport.js +798 -0
  235. package/dist/exchanges/rate-limiter.d.ts +12 -0
  236. package/dist/exchanges/rate-limiter.js +64 -0
  237. package/dist/exchanges/registry.d.ts +14 -2
  238. package/dist/exchanges/registry.js +20 -32
  239. package/dist/exchanges/slippage.d.ts +37 -0
  240. package/dist/exchanges/slippage.js +70 -0
  241. package/dist/exchanges/spot-factory.d.ts +166 -0
  242. package/dist/exchanges/spot-factory.js +431 -0
  243. package/dist/exchanges/spot-interface.d.ts +98 -4
  244. package/dist/exchanges/spot-interface.js +27 -1
  245. package/dist/exchanges/spot-result.d.ts +79 -0
  246. package/dist/exchanges/spot-result.js +273 -0
  247. package/dist/exchanges/trading-v2.d.ts +117 -0
  248. package/dist/exchanges/trading-v2.js +301 -0
  249. package/dist/exchanges/venue-types.d.ts +231 -0
  250. package/dist/exchanges/venue-types.js +87 -0
  251. package/dist/exchanges/venue.d.ts +211 -0
  252. package/dist/exchanges/venue.js +132 -0
  253. package/dist/exchanges/venues/arcus.d.ts +8 -0
  254. package/dist/exchanges/venues/arcus.js +109 -0
  255. package/dist/exchanges/venues/aster.d.ts +49 -0
  256. package/dist/exchanges/venues/aster.js +176 -0
  257. package/dist/exchanges/venues/create-helpers.d.ts +18 -0
  258. package/dist/exchanges/venues/create-helpers.js +199 -0
  259. package/dist/exchanges/venues/hyperliquid.d.ts +23 -0
  260. package/dist/exchanges/venues/hyperliquid.js +126 -0
  261. package/dist/exchanges/venues/index.d.ts +16 -0
  262. package/dist/exchanges/venues/index.js +26 -0
  263. package/dist/exchanges/venues/lighter-family.d.ts +92 -0
  264. package/dist/exchanges/venues/lighter-family.js +166 -0
  265. package/dist/exchanges/venues/lighter-rh.d.ts +7 -0
  266. package/dist/exchanges/venues/lighter-rh.js +58 -0
  267. package/dist/exchanges/venues/lighter.d.ts +6 -0
  268. package/dist/exchanges/venues/lighter.js +55 -0
  269. package/dist/exchanges/venues/ondo.d.ts +29 -0
  270. package/dist/exchanges/venues/ondo.js +136 -0
  271. package/dist/exchanges/venues/pacifica.d.ts +8 -0
  272. package/dist/exchanges/venues/pacifica.js +95 -0
  273. package/dist/exchanges/venues/qfex.d.ts +39 -0
  274. package/dist/exchanges/venues/qfex.js +140 -0
  275. package/dist/execution-log.js +10 -2
  276. package/dist/funding/legacy-public.d.ts +31 -0
  277. package/dist/funding/legacy-public.js +369 -0
  278. package/dist/funding/normalize.d.ts +28 -16
  279. package/dist/funding/normalize.js +61 -29
  280. package/dist/funding/rates.d.ts +46 -11
  281. package/dist/funding/rates.js +228 -277
  282. package/dist/guardrail/perp-guardrail.js +0 -0
  283. package/dist/index.js +156 -684
  284. package/dist/jobs.d.ts +84 -6
  285. package/dist/jobs.js +239 -41
  286. package/dist/landing.d.ts +7 -2
  287. package/dist/landing.js +19 -3
  288. package/dist/mcp-server.d.ts +14 -4
  289. package/dist/mcp-server.js +821 -403
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/onchain-balances.d.ts +40 -0
  293. package/dist/onchain-balances.js +173 -0
  294. package/dist/pacifica/client.d.ts +41 -10
  295. package/dist/pacifica/client.js +167 -63
  296. package/dist/pacifica/constants.d.ts +0 -1
  297. package/dist/pacifica/constants.js +0 -5
  298. package/dist/pacifica/deposit.d.ts +30 -3
  299. package/dist/pacifica/deposit.js +119 -2
  300. package/dist/pacifica/faucet.d.ts +29 -0
  301. package/dist/pacifica/faucet.js +100 -0
  302. package/dist/pacifica/sign-tx.d.ts +15 -0
  303. package/dist/pacifica/sign-tx.js +41 -0
  304. package/dist/pacifica/types/account.d.ts +28 -4
  305. package/dist/pacifica/types/lake.d.ts +20 -5
  306. package/dist/pacifica/types/lake.js +4 -0
  307. package/dist/pacifica/types/market.d.ts +5 -0
  308. package/dist/pacifica/types/order.d.ts +4 -1
  309. package/dist/pacifica/types/position.d.ts +9 -1
  310. package/dist/plan-executor.d.ts +10 -5
  311. package/dist/plan-executor.js +165 -54
  312. package/dist/position-history.js +13 -0
  313. package/dist/rebalance.d.ts +26 -2
  314. package/dist/rebalance.js +86 -7
  315. package/dist/relay-swap.d.ts +232 -0
  316. package/dist/relay-swap.js +630 -0
  317. package/dist/risk.js +5 -1
  318. package/dist/secret-env.d.ts +15 -0
  319. package/dist/secret-env.js +36 -0
  320. package/dist/settings.d.ts +169 -6
  321. package/dist/settings.js +219 -38
  322. package/dist/signer/ows-evm.d.ts +13 -0
  323. package/dist/signer/ows-evm.js +22 -0
  324. package/dist/smart-order.d.ts +9 -0
  325. package/dist/smart-order.js +53 -8
  326. package/dist/strategies/dca.d.ts +6 -2
  327. package/dist/strategies/dca.js +66 -26
  328. package/dist/strategies/funding-arb.d.ts +11 -1
  329. package/dist/strategies/funding-arb.js +202 -89
  330. package/dist/strategies/grid.d.ts +31 -0
  331. package/dist/strategies/grid.js +89 -11
  332. package/dist/strategies/pending-stop.d.ts +8 -0
  333. package/dist/strategies/pending-stop.js +12 -0
  334. package/dist/strategies/split-order.d.ts +45 -17
  335. package/dist/strategies/split-order.js +157 -91
  336. package/dist/strategies/trailing-stop.d.ts +2 -1
  337. package/dist/strategies/trailing-stop.js +52 -6
  338. package/dist/strategies/twap.d.ts +6 -1
  339. package/dist/strategies/twap.js +39 -11
  340. package/dist/trade-validator.d.ts +22 -0
  341. package/dist/trade-validator.js +119 -15
  342. package/dist/utils/numeric.d.ts +46 -0
  343. package/dist/utils/numeric.js +79 -0
  344. package/dist/utils.d.ts +19 -0
  345. package/dist/utils.js +96 -19
  346. package/dist/withdraw-gate.d.ts +49 -0
  347. package/dist/withdraw-gate.js +131 -0
  348. package/package.json +15 -6
  349. package/skills/perp-cli/SKILL.md +159 -55
  350. package/skills/perp-cli/references/agent-operations.md +112 -58
  351. package/skills/perp-cli/references/commands.md +269 -73
  352. package/skills/perp-cli/references/strategies.md +34 -31
  353. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  354. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  355. package/skills/perp-cli/scripts/preflight.sh +21 -14
  356. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  357. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  358. package/vendor/lighter-signer/SHA256SUMS +2 -0
  359. package/vendor/lighter-signer/VERSION +8 -0
  360. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  361. package/vendor/lighter-signer/wasm_exec.js +575 -0
  362. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  363. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Hyperliquid signing — L1 actions (phantom agent, agent- or master-signable) and
3
+ * user-signed actions (HyperliquidSignTransaction EIP-712, master only). Mirrors
4
+ * hyperliquid-python-sdk `utils/signing.py` (action_hash, sign_l1_action,
5
+ * sign_user_signed_action and the *_SIGN_TYPES tables).
6
+ *
7
+ * Note: src/commands/agent.ts (approveAgent / userSetAbstraction) and
8
+ * src/commands/builder.ts (approveBuilderFee) still carry their own copies of the
9
+ * user-signed domain; they produce the same payload as signHlUserSignedAction.
10
+ */
11
+ import type { EvmSigner } from "../signer/index.js";
12
+ import type { Network } from "./venue.js";
13
+ export interface HlSignature {
14
+ r: string;
15
+ s: string;
16
+ v: number;
17
+ }
18
+ type Eip712Field = {
19
+ name: string;
20
+ type: string;
21
+ };
22
+ /**
23
+ * keccak(msgpack(action) ‖ nonce u64be ‖ vault flag [‖ vault 20B] [‖ 0x00 ‖ expiresAfter u64be])
24
+ * — python SDK `action_hash`.
25
+ */
26
+ export declare function hlL1ActionHash(action: Record<string, unknown>, nonce: number, vaultAddress: string | null, expiresAfter: number | null): Promise<string>;
27
+ /** Sign an L1 action (phantom agent, domain "Exchange"/1337) — python `sign_l1_action`. */
28
+ export declare function signHlL1Action(signer: EvmSigner, action: Record<string, unknown>, nonce: number, isMainnet: boolean, vaultAddress?: string | null, expiresAfter?: number | null): Promise<HlSignature>;
29
+ /**
30
+ * User-signed action types (python SDK *_SIGN_TYPES). `hyperliquidChain` is always
31
+ * the first field; the remaining fields are copied from the action into the message.
32
+ */
33
+ export declare const HL_USER_SIGNED_TYPES: {
34
+ readonly withdraw3: {
35
+ readonly primaryType: "HyperliquidTransaction:Withdraw";
36
+ readonly fields: readonly [{
37
+ readonly name: "hyperliquidChain";
38
+ readonly type: "string";
39
+ }, {
40
+ readonly name: "destination";
41
+ readonly type: "string";
42
+ }, {
43
+ readonly name: "amount";
44
+ readonly type: "string";
45
+ }, {
46
+ readonly name: "time";
47
+ readonly type: "uint64";
48
+ }];
49
+ };
50
+ readonly usdSend: {
51
+ readonly primaryType: "HyperliquidTransaction:UsdSend";
52
+ readonly fields: readonly [{
53
+ readonly name: "hyperliquidChain";
54
+ readonly type: "string";
55
+ }, {
56
+ readonly name: "destination";
57
+ readonly type: "string";
58
+ }, {
59
+ readonly name: "amount";
60
+ readonly type: "string";
61
+ }, {
62
+ readonly name: "time";
63
+ readonly type: "uint64";
64
+ }];
65
+ };
66
+ readonly approveBuilderFee: {
67
+ readonly primaryType: "HyperliquidTransaction:ApproveBuilderFee";
68
+ readonly fields: readonly [{
69
+ readonly name: "hyperliquidChain";
70
+ readonly type: "string";
71
+ }, {
72
+ readonly name: "maxFeeRate";
73
+ readonly type: "string";
74
+ }, {
75
+ readonly name: "builder";
76
+ readonly type: "address";
77
+ }, {
78
+ readonly name: "nonce";
79
+ readonly type: "uint64";
80
+ }];
81
+ };
82
+ readonly tokenDelegate: {
83
+ readonly primaryType: "HyperliquidTransaction:TokenDelegate";
84
+ readonly fields: readonly [{
85
+ readonly name: "hyperliquidChain";
86
+ readonly type: "string";
87
+ }, {
88
+ readonly name: "validator";
89
+ readonly type: "address";
90
+ }, {
91
+ readonly name: "wei";
92
+ readonly type: "uint64";
93
+ }, {
94
+ readonly name: "isUndelegate";
95
+ readonly type: "bool";
96
+ }, {
97
+ readonly name: "nonce";
98
+ readonly type: "uint64";
99
+ }];
100
+ };
101
+ readonly sendToEvmWithData: {
102
+ readonly primaryType: "HyperliquidTransaction:SendToEvmWithData";
103
+ readonly fields: readonly [{
104
+ readonly name: "hyperliquidChain";
105
+ readonly type: "string";
106
+ }, {
107
+ readonly name: "token";
108
+ readonly type: "string";
109
+ }, {
110
+ readonly name: "amount";
111
+ readonly type: "string";
112
+ }, {
113
+ readonly name: "sourceDex";
114
+ readonly type: "string";
115
+ }, {
116
+ readonly name: "destinationRecipient";
117
+ readonly type: "string";
118
+ }, {
119
+ readonly name: "addressEncoding";
120
+ readonly type: "string";
121
+ }, {
122
+ readonly name: "destinationChainId";
123
+ readonly type: "uint32";
124
+ }, {
125
+ readonly name: "gasLimit";
126
+ readonly type: "uint64";
127
+ }, {
128
+ readonly name: "data";
129
+ readonly type: "bytes";
130
+ }, {
131
+ readonly name: "nonce";
132
+ readonly type: "uint64";
133
+ }];
134
+ };
135
+ readonly usdClassTransfer: {
136
+ readonly primaryType: "HyperliquidTransaction:UsdClassTransfer";
137
+ readonly fields: readonly [{
138
+ readonly name: "hyperliquidChain";
139
+ readonly type: "string";
140
+ }, {
141
+ readonly name: "amount";
142
+ readonly type: "string";
143
+ }, {
144
+ readonly name: "toPerp";
145
+ readonly type: "bool";
146
+ }, {
147
+ readonly name: "nonce";
148
+ readonly type: "uint64";
149
+ }];
150
+ };
151
+ };
152
+ export type HlUserSignedType = keyof typeof HL_USER_SIGNED_TYPES;
153
+ /** The action field that carries the nonce (withdraw3/usdSend use `time`). */
154
+ export declare function hlUserSignedNonceField(type: HlUserSignedType): "time" | "nonce";
155
+ /** Action object for a user-signed type: type + signatureChainId + hyperliquidChain + fields. */
156
+ export declare function buildHlUserSignedAction(type: HlUserSignedType, network: Network, fields: Record<string, unknown>): Record<string, unknown>;
157
+ /** EIP-712 domain/types/message for a user-signed action (python `user_signed_payload`). */
158
+ export declare function hlUserSignedTypedData(action: Record<string, unknown>): {
159
+ domain: Record<string, unknown>;
160
+ types: Record<string, Eip712Field[]>;
161
+ message: Record<string, unknown>;
162
+ };
163
+ /** Sign a user-signed action with the MASTER signer (python `sign_user_signed_action`). */
164
+ export declare function signHlUserSignedAction(signer: EvmSigner, action: Record<string, unknown>): Promise<HlSignature>;
165
+ export {};
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Hyperliquid signing — L1 actions (phantom agent, agent- or master-signable) and
3
+ * user-signed actions (HyperliquidSignTransaction EIP-712, master only). Mirrors
4
+ * hyperliquid-python-sdk `utils/signing.py` (action_hash, sign_l1_action,
5
+ * sign_user_signed_action and the *_SIGN_TYPES tables).
6
+ *
7
+ * Note: src/commands/agent.ts (approveAgent / userSetAbstraction) and
8
+ * src/commands/builder.ts (approveBuilderFee) still carry their own copies of the
9
+ * user-signed domain; they produce the same payload as signHlUserSignedAction.
10
+ */
11
+ import { HL_USER_SIGNED } from "./venues/hyperliquid.js";
12
+ import { PerpError } from "../errors.js";
13
+ /**
14
+ * keccak(msgpack(action) ‖ nonce u64be ‖ vault flag [‖ vault 20B] [‖ 0x00 ‖ expiresAfter u64be])
15
+ * — python SDK `action_hash`.
16
+ */
17
+ export async function hlL1ActionHash(action, nonce, vaultAddress, expiresAfter) {
18
+ const { encode } = await import("@msgpack/msgpack");
19
+ const { keccak256, getBytes } = await import("ethers");
20
+ const packed = encode(action);
21
+ const vault = vaultAddress === null ? new Uint8Array(0) : getBytes(vaultAddress);
22
+ const len = packed.length + 8 + 1 + vault.length + (expiresAfter === null ? 0 : 9);
23
+ const data = new Uint8Array(len);
24
+ const view = new DataView(data.buffer);
25
+ data.set(packed);
26
+ let off = packed.length;
27
+ view.setBigUint64(off, BigInt(nonce), false);
28
+ off += 8;
29
+ data[off] = vaultAddress === null ? 0 : 1;
30
+ off += 1;
31
+ data.set(vault, off);
32
+ off += vault.length;
33
+ if (expiresAfter !== null) {
34
+ data[off] = 0;
35
+ off += 1;
36
+ view.setBigUint64(off, BigInt(expiresAfter), false);
37
+ }
38
+ return keccak256(data);
39
+ }
40
+ /** Sign an L1 action (phantom agent, domain "Exchange"/1337) — python `sign_l1_action`. */
41
+ export async function signHlL1Action(signer, action, nonce, isMainnet, vaultAddress = null, expiresAfter = null) {
42
+ const { ethers } = await import("ethers");
43
+ const connectionId = await hlL1ActionHash(action, nonce, vaultAddress, expiresAfter);
44
+ const sig = await signer.signTypedData({ name: "Exchange", version: "1", chainId: 1337, verifyingContract: "0x0000000000000000000000000000000000000000" }, { Agent: [{ name: "source", type: "string" }, { name: "connectionId", type: "bytes32" }] }, { source: isMainnet ? "a" : "b", connectionId });
45
+ const p = ethers.Signature.from(sig);
46
+ return { r: p.r, s: p.s, v: p.v };
47
+ }
48
+ /**
49
+ * User-signed action types (python SDK *_SIGN_TYPES). `hyperliquidChain` is always
50
+ * the first field; the remaining fields are copied from the action into the message.
51
+ */
52
+ export const HL_USER_SIGNED_TYPES = {
53
+ withdraw3: {
54
+ primaryType: "HyperliquidTransaction:Withdraw",
55
+ fields: [
56
+ { name: "hyperliquidChain", type: "string" },
57
+ { name: "destination", type: "string" },
58
+ { name: "amount", type: "string" },
59
+ { name: "time", type: "uint64" },
60
+ ],
61
+ },
62
+ usdSend: {
63
+ primaryType: "HyperliquidTransaction:UsdSend",
64
+ fields: [
65
+ { name: "hyperliquidChain", type: "string" },
66
+ { name: "destination", type: "string" },
67
+ { name: "amount", type: "string" },
68
+ { name: "time", type: "uint64" },
69
+ ],
70
+ },
71
+ approveBuilderFee: {
72
+ primaryType: "HyperliquidTransaction:ApproveBuilderFee",
73
+ fields: [
74
+ { name: "hyperliquidChain", type: "string" },
75
+ { name: "maxFeeRate", type: "string" },
76
+ { name: "builder", type: "address" },
77
+ { name: "nonce", type: "uint64" },
78
+ ],
79
+ },
80
+ tokenDelegate: {
81
+ primaryType: "HyperliquidTransaction:TokenDelegate",
82
+ fields: [
83
+ { name: "hyperliquidChain", type: "string" },
84
+ { name: "validator", type: "address" },
85
+ { name: "wei", type: "uint64" },
86
+ { name: "isUndelegate", type: "bool" },
87
+ { name: "nonce", type: "uint64" },
88
+ ],
89
+ },
90
+ // CCTP withdrawal (native USDC): HyperCore → HyperEVM burn → CCTP mint on the destination chain.
91
+ // Field order per the Circle guide "Withdraw USDC from HyperCore to EVM chains"
92
+ // (developers.circle.com/cctp/howtos/withdraw-usdc-from-hypercore-to-evm) and the HL exchange endpoint docs.
93
+ sendToEvmWithData: {
94
+ primaryType: "HyperliquidTransaction:SendToEvmWithData",
95
+ fields: [
96
+ { name: "hyperliquidChain", type: "string" },
97
+ { name: "token", type: "string" },
98
+ { name: "amount", type: "string" },
99
+ { name: "sourceDex", type: "string" },
100
+ { name: "destinationRecipient", type: "string" },
101
+ { name: "addressEncoding", type: "string" },
102
+ { name: "destinationChainId", type: "uint32" },
103
+ { name: "gasLimit", type: "uint64" },
104
+ { name: "data", type: "bytes" },
105
+ { name: "nonce", type: "uint64" },
106
+ ],
107
+ },
108
+ usdClassTransfer: {
109
+ primaryType: "HyperliquidTransaction:UsdClassTransfer",
110
+ fields: [
111
+ { name: "hyperliquidChain", type: "string" },
112
+ { name: "amount", type: "string" },
113
+ { name: "toPerp", type: "bool" },
114
+ { name: "nonce", type: "uint64" },
115
+ ],
116
+ },
117
+ };
118
+ /** The action field that carries the nonce (withdraw3/usdSend use `time`). */
119
+ export function hlUserSignedNonceField(type) {
120
+ return type === "withdraw3" || type === "usdSend" ? "time" : "nonce";
121
+ }
122
+ /** Action object for a user-signed type: type + signatureChainId + hyperliquidChain + fields. */
123
+ export function buildHlUserSignedAction(type, network, fields) {
124
+ const { hyperliquidChain, signatureChainIdHex } = HL_USER_SIGNED[network];
125
+ return { type, signatureChainId: signatureChainIdHex, hyperliquidChain, ...fields };
126
+ }
127
+ /** EIP-712 domain/types/message for a user-signed action (python `user_signed_payload`). */
128
+ export function hlUserSignedTypedData(action) {
129
+ const type = action.type;
130
+ const spec = HL_USER_SIGNED_TYPES[type];
131
+ if (spec === undefined) {
132
+ throw new PerpError("INVALID_PARAMS", `Not a Hyperliquid user-signed action type: ${String(action.type)}`, { exchange: "hyperliquid" });
133
+ }
134
+ const message = {};
135
+ for (const f of spec.fields) {
136
+ if (action[f.name] === undefined) {
137
+ throw new PerpError("INVALID_PARAMS", `Hyperliquid ${type}: missing field ${f.name}`, { exchange: "hyperliquid" });
138
+ }
139
+ message[f.name] = action[f.name];
140
+ }
141
+ return {
142
+ domain: {
143
+ name: "HyperliquidSignTransaction",
144
+ version: "1",
145
+ chainId: parseInt(String(action.signatureChainId), 16),
146
+ verifyingContract: "0x0000000000000000000000000000000000000000",
147
+ },
148
+ types: { [spec.primaryType]: spec.fields.map(f => ({ ...f })) },
149
+ message,
150
+ };
151
+ }
152
+ /** Sign a user-signed action with the MASTER signer (python `sign_user_signed_action`). */
153
+ export async function signHlUserSignedAction(signer, action) {
154
+ const { ethers } = await import("ethers");
155
+ const { domain, types, message } = hlUserSignedTypedData(action);
156
+ const p = ethers.Signature.from(await signer.signTypedData(domain, types, message));
157
+ return { r: p.r, s: p.s, v: p.v };
158
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Hyperliquid Outcome Adapter (HIP-4).
3
+ *
4
+ * Composes with HyperliquidAdapter for signing. Asset id encoding:
5
+ * 100,000,000 + (10 * outcome + side)
6
+ *
7
+ * Coin name conventions:
8
+ * - l2Book/candle/allMids: `#<encoding>` (e.g., `#10`)
9
+ * - spotClearinghouseState balance: `+<encoding>` (e.g., `+10`)
10
+ *
11
+ * Outcome trades draw collateral from the spot balance of the outcome's own quote token —
12
+ * `outcomeMeta.outcomes[].quoteToken` (live 2026-10-12: "USDC" on every listed outcome; a USDH-only
13
+ * balance was refused by the venue "Insufficient spot balance asset=100014881"). Min order value:
14
+ * 10 quote tokens (docs error-responses MinTradeSpotNtl "Order must have minimum value of 10 {quote_token}.").
15
+ */
16
+ import type { OutcomeAdapter, OutcomeMarketInfo, OutcomeOrderbook, OutcomePosition, OutcomeView, OutcomeViewUnderlying } from "./outcome-interface.js";
17
+ import type { HyperliquidAdapter } from "./hyperliquid.js";
18
+ export declare class HyperliquidOutcomeAdapter implements OutcomeAdapter {
19
+ readonly name = "hyperliquid";
20
+ private _hl;
21
+ private _outcomeMeta;
22
+ private _initialized;
23
+ constructor(hlAdapter: HyperliquidAdapter);
24
+ init(): Promise<void>;
25
+ static encoding(outcome: number, side: number): number;
26
+ static assetId(outcome: number, side: number): number;
27
+ static mintCoin(outcome: number, side: number): string;
28
+ static balanceCoin(outcome: number, side: number): string;
29
+ /**
30
+ * Decode a balance coin name like `+10` back to (outcome, side).
31
+ * Returns null if the name does not match the outcome scheme.
32
+ */
33
+ static decodeBalanceCoin(coin: string): {
34
+ outcome: number;
35
+ side: number;
36
+ } | null;
37
+ static parseDescription(description: string): {
38
+ class?: string;
39
+ underlying?: string;
40
+ expiryMs?: number;
41
+ targetPrice?: number;
42
+ period?: string;
43
+ };
44
+ /**
45
+ * Compute the underlying mark-price view (gap / inTheMoney) for an outcome
46
+ * from a parsed description and the live allMids map.
47
+ *
48
+ * Pure helper — extracted from getView so the settlement-status logic is
49
+ * directly unit-testable.
50
+ *
51
+ * - HL `allMids` keys perps by bare symbol (e.g. "BTC"). HIP-3 perps use
52
+ * "@dexIdx:SYMBOL" but those aren't referenced in HIP-4 outcomes yet.
53
+ * - For `class:priceBinary` the convention is Yes = "underlying >= target".
54
+ * When `class` is missing or non-binary, `inTheMoney` stays null rather
55
+ * than guessing (Rule #2 — no silent classification fallback).
56
+ * - Returns null when there is no underlying field to look up.
57
+ */
58
+ static _computeUnderlying(parsed: {
59
+ class?: string;
60
+ underlying?: string;
61
+ targetPrice?: number;
62
+ }, allMids: Record<string, string>): OutcomeViewUnderlying | null;
63
+ /**
64
+ * Sum of `impliedProb` across sides — for fair binary markets the sum
65
+ * should converge to ~1.0. Deviation hints at arbitrage or stale mids.
66
+ *
67
+ * Returns undefined when any side is missing impliedProb OR when any
68
+ * impliedProb is non-finite (NaN, Infinity). This means "we don't have a
69
+ * trustworthy view of the symmetry right now" rather than emitting NaN
70
+ * downstream (Rule #2 — no silent garbage propagation).
71
+ */
72
+ static _computeMidSum(sides: Array<{
73
+ impliedProb?: number;
74
+ }>): number | undefined;
75
+ /**
76
+ * Compute the time-status pair (`serverTime`, `msToExpiry`) for a view.
77
+ * Pure helper — takes `nowMs` as an argument so callers can inject a
78
+ * deterministic clock under test.
79
+ *
80
+ * `msToExpiry` is the raw signed delta `expiryMs - nowMs`:
81
+ * positive = unexpired
82
+ * zero = at expiry
83
+ * negative = already settled (caller decides UX)
84
+ * undefined = unknown expiry
85
+ *
86
+ * Does NOT clamp negatives or treat them as "expired" — that
87
+ * classification is the caller's job (Rule #2 — no silent classification
88
+ * fallback in a low-level helper).
89
+ */
90
+ static _computeTimeStatus(expiryMs: number | undefined, nowMs: number): {
91
+ serverTime: number;
92
+ msToExpiry?: number;
93
+ };
94
+ /**
95
+ * Pure arithmetic gate for the (outcome, side) pair.
96
+ *
97
+ * Rejects NaN / non-integer / negative values immediately so the
98
+ * encoding formula `10 * outcome + side` never produces a garbage
99
+ * asset id silently. Does NOT consult outcomeMeta — that lookup is in
100
+ * the instance-level `_validateOutcomeSide` which composes this
101
+ * helper with the live registry check.
102
+ *
103
+ * Boundary: outcome=9_999_999, side=9 → encoding=99_999_999 = MAX_ENCODING (valid).
104
+ * outcome=10_000_000, side=0 → encoding=100_000_000 > MAX_ENCODING (rejected).
105
+ */
106
+ static _assertOutcomeRange(outcome: number, side: number): void;
107
+ /**
108
+ * Trim a raw orderbook to `depth` levels and surface best bid/ask.
109
+ *
110
+ * Throws (rather than silently coercing) when:
111
+ * - `book.bids` or `book.asks` is missing/non-array (venue payload
112
+ * malformed — Rule #2: don't fabricate an empty book)
113
+ * - `depth` is not a non-negative integer (NaN, negative, Infinity,
114
+ * fractional are all caller bugs that previously silently produced
115
+ * `slice(0, NaN) === []` or `slice(0, -1)` = "all but last")
116
+ */
117
+ static _trimBook(book: {
118
+ bids: [string, string][];
119
+ asks: [string, string][];
120
+ } | {
121
+ bids: unknown;
122
+ asks: unknown;
123
+ } | null | undefined, depth: number): {
124
+ bids: [string, string][];
125
+ asks: [string, string][];
126
+ bestBid?: string;
127
+ bestAsk?: string;
128
+ };
129
+ /** Parse "20260504-0600" → ms-epoch (UTC). Returns undefined for malformed. */
130
+ private static _parseExpiry;
131
+ private _loadOutcomeMeta;
132
+ getMarkets(): Promise<OutcomeMarketInfo[]>;
133
+ getPositions(): Promise<OutcomePosition[]>;
134
+ /**
135
+ * Assemble a combined view of one outcome: all sides' books in parallel,
136
+ * the underlying mark price (HL perp mid for `description.underlying`),
137
+ * gap vs targetPrice, time-to-expiry, and per-side implied probability.
138
+ *
139
+ * Outcome markets have a symmetric (Yes / No) structure where the prices
140
+ * sum to ~$1; this view exposes both sides in a single round-trip and
141
+ * also surfaces the directional context for binary markets — what BTC
142
+ * mark price would settle the contract right now.
143
+ */
144
+ getView(outcome: number, depth?: number): Promise<OutcomeView>;
145
+ getOrderbook(outcome: number, side: number): Promise<OutcomeOrderbook>;
146
+ placeOrder(opts: {
147
+ outcome: number;
148
+ side: number;
149
+ isBuy: boolean;
150
+ price: string;
151
+ size: string;
152
+ tif?: "Gtc" | "Ioc" | "Alo";
153
+ }): Promise<unknown>;
154
+ cancelOrder(outcome: number, side: number, oid: number): Promise<unknown>;
155
+ /**
156
+ * Throw if the venue rejected the order embedded inside a top-level
157
+ * `status:"ok"` response (HL pattern). Returns silently for resting/filled.
158
+ */
159
+ static _assertOrderStatusOk(result: unknown): void;
160
+ static _assertCancelStatusOk(result: unknown): void;
161
+ getOpenOrders(): Promise<unknown[]>;
162
+ /**
163
+ * The outcome's quote token from outcomeMeta (`quoteToken`, e.g. "USDC"). Unknown outcome →
164
+ * SYMBOL_NOT_FOUND; missing / non-string quoteToken → EXCHANGE_ERROR (never an assumed token).
165
+ */
166
+ quoteTokenOf(outcome: number): string;
167
+ /**
168
+ * The outcome / side behind an outcome coin ("#14881" = outcome 1488, side 1) with its names from
169
+ * outcomeMeta; null when the coin is not an outcome coin or the outcome is not listed.
170
+ */
171
+ describeCoin(coin: string): {
172
+ outcome: number;
173
+ side: number;
174
+ name: string;
175
+ sideName: string;
176
+ } | null;
177
+ /**
178
+ * Price of held outcome balance coins (`+<encoding>`, spotClearinghouseState) in the outcome's quote
179
+ * token: the side's mid `allMids["#<encoding>"]` (docs info-endpoint "Retrieve mids for all coins";
180
+ * live 2026-10-13 mainnet allMids "#14880": "0.100405", "#14881": "0.899595"). HIP-4 docs: a side
181
+ * token settles to `settleFraction` (Yes) / `1 - settleFraction` (No) quote tokens and the Yes/No
182
+ * books are merged (buy Yes at p = sell No at 1 - p), so the mid is the token's value in its quote.
183
+ * `quoteToken` null = the outcome / side is not in outcomeMeta (outcomeMeta is re-read once when a
184
+ * coin's outcome is missing — outcomes are deployed after init) or has no quoteToken; `mid` null = no
185
+ * positive mid. Coins that are not `+<digits>` are not returned. A malformed allMids → EXCHANGE_ERROR.
186
+ */
187
+ getBalanceCoinPrices(coins: readonly string[]): Promise<Array<{
188
+ coin: string;
189
+ quoteToken: string | null;
190
+ mid: string | null;
191
+ }>>;
192
+ private _lookupSideName;
193
+ private _validateOutcomeSide;
194
+ /**
195
+ * Resolve the master EVM address for spot-clearinghouse queries.
196
+ * `HyperliquidAdapter._address` is populated only when a master/PK signer
197
+ * is configured. Agent-only setups (no master pk in OWS) leave it empty
198
+ * even though the agent meta knows the user's EVM address. Fall through
199
+ * to the agent registry rather than treating empty as zero balance —
200
+ * Rule #2: no silent fallback.
201
+ */
202
+ private _resolveUserAddress;
203
+ /**
204
+ * Available spot balance of `coin` (total − hold, spotClearinghouseState). A coin the account does
205
+ * not hold is not listed → 0 held. No balances list, or an unreadable total / hold → EXCHANGE_ERROR.
206
+ */
207
+ private _getSpotAvailable;
208
+ private _invalidateAccountCache;
209
+ private _trimZeros;
210
+ private _infoPost;
211
+ }