perp-cli 0.3.3

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 (325) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -0
  3. package/dist/__tests__/alert-logic.test.d.ts +1 -0
  4. package/dist/__tests__/alert-logic.test.js +107 -0
  5. package/dist/__tests__/arb-auto-3dex.test.d.ts +1 -0
  6. package/dist/__tests__/arb-auto-3dex.test.js +397 -0
  7. package/dist/__tests__/arb-history-stats.test.d.ts +1 -0
  8. package/dist/__tests__/arb-history-stats.test.js +176 -0
  9. package/dist/__tests__/arb-logic.test.d.ts +1 -0
  10. package/dist/__tests__/arb-logic.test.js +84 -0
  11. package/dist/__tests__/arb-manage.test.d.ts +1 -0
  12. package/dist/__tests__/arb-manage.test.js +253 -0
  13. package/dist/__tests__/arb-new-features.test.d.ts +1 -0
  14. package/dist/__tests__/arb-new-features.test.js +457 -0
  15. package/dist/__tests__/arb-sizing.test.d.ts +1 -0
  16. package/dist/__tests__/arb-sizing.test.js +48 -0
  17. package/dist/__tests__/arb-state.test.d.ts +1 -0
  18. package/dist/__tests__/arb-state.test.js +284 -0
  19. package/dist/__tests__/arb-userflow.test.d.ts +1 -0
  20. package/dist/__tests__/arb-userflow.test.js +945 -0
  21. package/dist/__tests__/arb-utils.test.d.ts +1 -0
  22. package/dist/__tests__/arb-utils.test.js +264 -0
  23. package/dist/__tests__/bot-conditions.test.d.ts +1 -0
  24. package/dist/__tests__/bot-conditions.test.js +341 -0
  25. package/dist/__tests__/client-id-tracker.test.d.ts +1 -0
  26. package/dist/__tests__/client-id-tracker.test.js +137 -0
  27. package/dist/__tests__/commands/new-atomic-commands.test.d.ts +1 -0
  28. package/dist/__tests__/commands/new-atomic-commands.test.js +502 -0
  29. package/dist/__tests__/commands/order-intent.test.d.ts +1 -0
  30. package/dist/__tests__/commands/order-intent.test.js +600 -0
  31. package/dist/__tests__/commands/trade-commands.test.d.ts +1 -0
  32. package/dist/__tests__/commands/trade-commands.test.js +821 -0
  33. package/dist/__tests__/config.test.d.ts +1 -0
  34. package/dist/__tests__/config.test.js +86 -0
  35. package/dist/__tests__/cross-chain-margin.test.d.ts +1 -0
  36. package/dist/__tests__/cross-chain-margin.test.js +287 -0
  37. package/dist/__tests__/dex-asset-map.test.d.ts +1 -0
  38. package/dist/__tests__/dex-asset-map.test.js +191 -0
  39. package/dist/__tests__/errors.test.d.ts +1 -0
  40. package/dist/__tests__/errors.test.js +110 -0
  41. package/dist/__tests__/event-stream.test.d.ts +1 -0
  42. package/dist/__tests__/event-stream.test.js +276 -0
  43. package/dist/__tests__/exchanges/interface.test.d.ts +1 -0
  44. package/dist/__tests__/exchanges/interface.test.js +132 -0
  45. package/dist/__tests__/exchanges/mock-adapter.d.ts +69 -0
  46. package/dist/__tests__/exchanges/mock-adapter.js +137 -0
  47. package/dist/__tests__/execution-log.test.d.ts +1 -0
  48. package/dist/__tests__/execution-log.test.js +106 -0
  49. package/dist/__tests__/funding-calc.test.d.ts +1 -0
  50. package/dist/__tests__/funding-calc.test.js +71 -0
  51. package/dist/__tests__/funding-history.test.d.ts +1 -0
  52. package/dist/__tests__/funding-history.test.js +343 -0
  53. package/dist/__tests__/funding-rates.test.d.ts +1 -0
  54. package/dist/__tests__/funding-rates.test.js +342 -0
  55. package/dist/__tests__/funding.test.d.ts +1 -0
  56. package/dist/__tests__/funding.test.js +173 -0
  57. package/dist/__tests__/gap-logic.test.d.ts +1 -0
  58. package/dist/__tests__/gap-logic.test.js +43 -0
  59. package/dist/__tests__/hip3-dex.test.d.ts +1 -0
  60. package/dist/__tests__/hip3-dex.test.js +234 -0
  61. package/dist/__tests__/integration/agent-features.integration.test.d.ts +1 -0
  62. package/dist/__tests__/integration/agent-features.integration.test.js +553 -0
  63. package/dist/__tests__/integration/atomic-commands.integration.test.d.ts +13 -0
  64. package/dist/__tests__/integration/atomic-commands.integration.test.js +246 -0
  65. package/dist/__tests__/integration/bridge-simulation.integration.test.d.ts +1 -0
  66. package/dist/__tests__/integration/bridge-simulation.integration.test.js +453 -0
  67. package/dist/__tests__/integration/bridge-strict.integration.test.d.ts +1 -0
  68. package/dist/__tests__/integration/bridge-strict.integration.test.js +812 -0
  69. package/dist/__tests__/integration/bridge.integration.test.d.ts +1 -0
  70. package/dist/__tests__/integration/bridge.integration.test.js +309 -0
  71. package/dist/__tests__/integration/cli-e2e.integration.test.d.ts +1 -0
  72. package/dist/__tests__/integration/cli-e2e.integration.test.js +202 -0
  73. package/dist/__tests__/integration/dex-arb.integration.test.d.ts +1 -0
  74. package/dist/__tests__/integration/dex-arb.integration.test.js +116 -0
  75. package/dist/__tests__/integration/envelope-consistency.integration.test.d.ts +13 -0
  76. package/dist/__tests__/integration/envelope-consistency.integration.test.js +205 -0
  77. package/dist/__tests__/integration/hip3-dex.integration.test.d.ts +1 -0
  78. package/dist/__tests__/integration/hip3-dex.integration.test.js +147 -0
  79. package/dist/__tests__/integration/hyperliquid.integration.test.d.ts +1 -0
  80. package/dist/__tests__/integration/hyperliquid.integration.test.js +79 -0
  81. package/dist/__tests__/integration/lighter.integration.test.d.ts +1 -0
  82. package/dist/__tests__/integration/lighter.integration.test.js +53 -0
  83. package/dist/__tests__/integration/new-commands-e2e.integration.test.d.ts +9 -0
  84. package/dist/__tests__/integration/new-commands-e2e.integration.test.js +236 -0
  85. package/dist/__tests__/integration/order-verification.integration.test.d.ts +1 -0
  86. package/dist/__tests__/integration/order-verification.integration.test.js +321 -0
  87. package/dist/__tests__/integration/pacifica.integration.test.d.ts +1 -0
  88. package/dist/__tests__/integration/pacifica.integration.test.js +75 -0
  89. package/dist/__tests__/integration/response-shapes.integration.test.d.ts +1 -0
  90. package/dist/__tests__/integration/response-shapes.integration.test.js +278 -0
  91. package/dist/__tests__/liquidity.test.d.ts +1 -0
  92. package/dist/__tests__/liquidity.test.js +225 -0
  93. package/dist/__tests__/plan-executor.test.d.ts +1 -0
  94. package/dist/__tests__/plan-executor.test.js +314 -0
  95. package/dist/__tests__/position-history.test.d.ts +1 -0
  96. package/dist/__tests__/position-history.test.js +367 -0
  97. package/dist/__tests__/retry.test.d.ts +1 -0
  98. package/dist/__tests__/retry.test.js +310 -0
  99. package/dist/__tests__/risk-assessment.test.d.ts +1 -0
  100. package/dist/__tests__/risk-assessment.test.js +145 -0
  101. package/dist/__tests__/security-adversarial.test.d.ts +1 -0
  102. package/dist/__tests__/security-adversarial.test.js +574 -0
  103. package/dist/__tests__/strategies.test.d.ts +1 -0
  104. package/dist/__tests__/strategies.test.js +539 -0
  105. package/dist/__tests__/trade-execution.test.d.ts +1 -0
  106. package/dist/__tests__/trade-execution.test.js +129 -0
  107. package/dist/__tests__/trade-validator.test.d.ts +1 -0
  108. package/dist/__tests__/trade-validator.test.js +655 -0
  109. package/dist/__tests__/utils.test.d.ts +1 -0
  110. package/dist/__tests__/utils.test.js +76 -0
  111. package/dist/api/public/hyperliquid.d.ts +18 -0
  112. package/dist/api/public/hyperliquid.js +82 -0
  113. package/dist/api/public/index.d.ts +8 -0
  114. package/dist/api/public/index.js +8 -0
  115. package/dist/api/public/lighter.d.ts +24 -0
  116. package/dist/api/public/lighter.js +100 -0
  117. package/dist/api/public/pacifica.d.ts +17 -0
  118. package/dist/api/public/pacifica.js +54 -0
  119. package/dist/api/public/urls.d.ts +12 -0
  120. package/dist/api/public/urls.js +33 -0
  121. package/dist/arb/history-stats.d.ts +44 -0
  122. package/dist/arb/history-stats.js +135 -0
  123. package/dist/arb/index.d.ts +4 -0
  124. package/dist/arb/index.js +4 -0
  125. package/dist/arb/sizing.d.ts +23 -0
  126. package/dist/arb/sizing.js +96 -0
  127. package/dist/arb/state.d.ts +51 -0
  128. package/dist/arb/state.js +112 -0
  129. package/dist/arb/utils.d.ts +81 -0
  130. package/dist/arb/utils.js +267 -0
  131. package/dist/arb-history-stats.d.ts +5 -0
  132. package/dist/arb-history-stats.js +5 -0
  133. package/dist/arb-sizing.d.ts +5 -0
  134. package/dist/arb-sizing.js +5 -0
  135. package/dist/arb-state.d.ts +5 -0
  136. package/dist/arb-state.js +5 -0
  137. package/dist/arb-utils.d.ts +5 -0
  138. package/dist/arb-utils.js +5 -0
  139. package/dist/bot/conditions.d.ts +32 -0
  140. package/dist/bot/conditions.js +141 -0
  141. package/dist/bot/config.d.ts +76 -0
  142. package/dist/bot/config.js +160 -0
  143. package/dist/bot/engine.d.ts +8 -0
  144. package/dist/bot/engine.js +519 -0
  145. package/dist/bot/presets.d.ts +11 -0
  146. package/dist/bot/presets.js +296 -0
  147. package/dist/bridge-engine.d.ts +133 -0
  148. package/dist/bridge-engine.js +1487 -0
  149. package/dist/cache.d.ts +25 -0
  150. package/dist/cache.js +99 -0
  151. package/dist/cli-spec.d.ts +50 -0
  152. package/dist/cli-spec.js +75 -0
  153. package/dist/client-id-tracker.d.ts +25 -0
  154. package/dist/client-id-tracker.js +76 -0
  155. package/dist/commands/account.d.ts +3 -0
  156. package/dist/commands/account.js +425 -0
  157. package/dist/commands/agent.d.ts +3 -0
  158. package/dist/commands/agent.js +386 -0
  159. package/dist/commands/alert.d.ts +2 -0
  160. package/dist/commands/alert.js +421 -0
  161. package/dist/commands/analytics.d.ts +3 -0
  162. package/dist/commands/analytics.js +311 -0
  163. package/dist/commands/arb/index.d.ts +3 -0
  164. package/dist/commands/arb/index.js +921 -0
  165. package/dist/commands/arb-auto.d.ts +54 -0
  166. package/dist/commands/arb-auto.js +1328 -0
  167. package/dist/commands/arb-manage.d.ts +5 -0
  168. package/dist/commands/arb-manage.js +5 -0
  169. package/dist/commands/arb.d.ts +2 -0
  170. package/dist/commands/arb.js +347 -0
  171. package/dist/commands/backtest.d.ts +2 -0
  172. package/dist/commands/backtest.js +327 -0
  173. package/dist/commands/bot.d.ts +3 -0
  174. package/dist/commands/bot.js +412 -0
  175. package/dist/commands/bridge.d.ts +2 -0
  176. package/dist/commands/bridge.js +396 -0
  177. package/dist/commands/dashboard.d.ts +3 -0
  178. package/dist/commands/dashboard.js +176 -0
  179. package/dist/commands/deposit.d.ts +4 -0
  180. package/dist/commands/deposit.js +573 -0
  181. package/dist/commands/dex.d.ts +3 -0
  182. package/dist/commands/dex.js +114 -0
  183. package/dist/commands/env.d.ts +2 -0
  184. package/dist/commands/env.js +136 -0
  185. package/dist/commands/funding.d.ts +2 -0
  186. package/dist/commands/funding.js +347 -0
  187. package/dist/commands/gap.d.ts +2 -0
  188. package/dist/commands/gap.js +305 -0
  189. package/dist/commands/health.d.ts +2 -0
  190. package/dist/commands/health.js +67 -0
  191. package/dist/commands/history.d.ts +2 -0
  192. package/dist/commands/history.js +235 -0
  193. package/dist/commands/init.d.ts +15 -0
  194. package/dist/commands/init.js +266 -0
  195. package/dist/commands/jobs.d.ts +2 -0
  196. package/dist/commands/jobs.js +133 -0
  197. package/dist/commands/manage.d.ts +4 -0
  198. package/dist/commands/manage.js +309 -0
  199. package/dist/commands/market.d.ts +3 -0
  200. package/dist/commands/market.js +225 -0
  201. package/dist/commands/plan.d.ts +3 -0
  202. package/dist/commands/plan.js +95 -0
  203. package/dist/commands/portfolio.d.ts +3 -0
  204. package/dist/commands/portfolio.js +169 -0
  205. package/dist/commands/rebalance.d.ts +3 -0
  206. package/dist/commands/rebalance.js +293 -0
  207. package/dist/commands/risk.d.ts +3 -0
  208. package/dist/commands/risk.js +169 -0
  209. package/dist/commands/run.d.ts +3 -0
  210. package/dist/commands/run.js +202 -0
  211. package/dist/commands/settings.d.ts +2 -0
  212. package/dist/commands/settings.js +102 -0
  213. package/dist/commands/stream.d.ts +5 -0
  214. package/dist/commands/stream.js +123 -0
  215. package/dist/commands/trade.d.ts +3 -0
  216. package/dist/commands/trade.js +1273 -0
  217. package/dist/commands/wallet.d.ts +14 -0
  218. package/dist/commands/wallet.js +602 -0
  219. package/dist/commands/withdraw.d.ts +3 -0
  220. package/dist/commands/withdraw.js +187 -0
  221. package/dist/config.d.ts +5 -0
  222. package/dist/config.js +68 -0
  223. package/dist/cross-chain-margin.d.ts +46 -0
  224. package/dist/cross-chain-margin.js +107 -0
  225. package/dist/dashboard/server.d.ts +80 -0
  226. package/dist/dashboard/server.js +340 -0
  227. package/dist/dashboard/ui.d.ts +4 -0
  228. package/dist/dashboard/ui.js +538 -0
  229. package/dist/dashboard/ws-feeds.d.ts +29 -0
  230. package/dist/dashboard/ws-feeds.js +660 -0
  231. package/dist/dex-asset-map.d.ts +80 -0
  232. package/dist/dex-asset-map.js +201 -0
  233. package/dist/errors.d.ts +109 -0
  234. package/dist/errors.js +84 -0
  235. package/dist/event-stream.d.ts +25 -0
  236. package/dist/event-stream.js +168 -0
  237. package/dist/exchanges/hyperliquid.d.ts +212 -0
  238. package/dist/exchanges/hyperliquid.js +931 -0
  239. package/dist/exchanges/interface.d.ts +95 -0
  240. package/dist/exchanges/interface.js +5 -0
  241. package/dist/exchanges/lighter.d.ts +159 -0
  242. package/dist/exchanges/lighter.js +793 -0
  243. package/dist/exchanges/pacifica.d.ts +51 -0
  244. package/dist/exchanges/pacifica.js +248 -0
  245. package/dist/execution-log.d.ts +36 -0
  246. package/dist/execution-log.js +102 -0
  247. package/dist/funding/history.d.ts +63 -0
  248. package/dist/funding/history.js +266 -0
  249. package/dist/funding/index.d.ts +3 -0
  250. package/dist/funding/index.js +3 -0
  251. package/dist/funding/normalize.d.ts +39 -0
  252. package/dist/funding/normalize.js +66 -0
  253. package/dist/funding/rates.d.ts +45 -0
  254. package/dist/funding/rates.js +172 -0
  255. package/dist/funding-history.d.ts +5 -0
  256. package/dist/funding-history.js +5 -0
  257. package/dist/funding-rates.d.ts +5 -0
  258. package/dist/funding-rates.js +5 -0
  259. package/dist/funding.d.ts +5 -0
  260. package/dist/funding.js +5 -0
  261. package/dist/index.d.ts +2 -0
  262. package/dist/index.js +458 -0
  263. package/dist/jobs.d.ts +37 -0
  264. package/dist/jobs.js +152 -0
  265. package/dist/liquidity.d.ts +34 -0
  266. package/dist/liquidity.js +100 -0
  267. package/dist/mcp-server.d.ts +9 -0
  268. package/dist/mcp-server.js +1206 -0
  269. package/dist/pacifica/client.d.ts +111 -0
  270. package/dist/pacifica/client.js +310 -0
  271. package/dist/pacifica/constants.d.ts +27 -0
  272. package/dist/pacifica/constants.js +47 -0
  273. package/dist/pacifica/deposit.d.ts +14 -0
  274. package/dist/pacifica/deposit.js +78 -0
  275. package/dist/pacifica/index.d.ts +6 -0
  276. package/dist/pacifica/index.js +11 -0
  277. package/dist/pacifica/signing.d.ts +49 -0
  278. package/dist/pacifica/signing.js +97 -0
  279. package/dist/pacifica/types/account.d.ts +42 -0
  280. package/dist/pacifica/types/account.js +1 -0
  281. package/dist/pacifica/types/index.d.ts +6 -0
  282. package/dist/pacifica/types/index.js +6 -0
  283. package/dist/pacifica/types/lake.d.ts +18 -0
  284. package/dist/pacifica/types/lake.js +1 -0
  285. package/dist/pacifica/types/market.d.ts +64 -0
  286. package/dist/pacifica/types/market.js +1 -0
  287. package/dist/pacifica/types/order.d.ts +92 -0
  288. package/dist/pacifica/types/order.js +1 -0
  289. package/dist/pacifica/types/position.d.ts +25 -0
  290. package/dist/pacifica/types/position.js +1 -0
  291. package/dist/pacifica/types/ws.d.ts +34 -0
  292. package/dist/pacifica/types/ws.js +41 -0
  293. package/dist/pacifica/ws-client.d.ts +42 -0
  294. package/dist/pacifica/ws-client.js +180 -0
  295. package/dist/plan-executor.d.ts +48 -0
  296. package/dist/plan-executor.js +280 -0
  297. package/dist/position-history.d.ts +68 -0
  298. package/dist/position-history.js +222 -0
  299. package/dist/rebalance.d.ts +64 -0
  300. package/dist/rebalance.js +142 -0
  301. package/dist/retry.d.ts +74 -0
  302. package/dist/retry.js +129 -0
  303. package/dist/risk.d.ts +48 -0
  304. package/dist/risk.js +156 -0
  305. package/dist/settings.d.ts +19 -0
  306. package/dist/settings.js +45 -0
  307. package/dist/shared-api.d.ts +5 -0
  308. package/dist/shared-api.js +5 -0
  309. package/dist/strategies/dca.d.ts +25 -0
  310. package/dist/strategies/dca.js +114 -0
  311. package/dist/strategies/funding-arb.d.ts +15 -0
  312. package/dist/strategies/funding-arb.js +281 -0
  313. package/dist/strategies/grid.d.ts +34 -0
  314. package/dist/strategies/grid.js +185 -0
  315. package/dist/strategies/trailing-stop.d.ts +17 -0
  316. package/dist/strategies/trailing-stop.js +121 -0
  317. package/dist/strategies/twap.d.ts +20 -0
  318. package/dist/strategies/twap.js +78 -0
  319. package/dist/trade-validator.d.ts +39 -0
  320. package/dist/trade-validator.js +154 -0
  321. package/dist/utils.d.ts +38 -0
  322. package/dist/utils.js +110 -0
  323. package/package.json +63 -0
  324. package/skills/perp-cli/SKILL.md +149 -0
  325. package/skills/perp-cli/references/commands.md +143 -0
@@ -0,0 +1,386 @@
1
+ import { printJson, jsonOk } from "../utils.js";
2
+ import { ERROR_CODES } from "../errors.js";
3
+ import chalk from "chalk";
4
+ /** Infer parameter type from commander flags/description */
5
+ function inferType(flags, desc) {
6
+ if (flags.includes("[boolean]") || !flags.includes("<") && !flags.includes("["))
7
+ return "boolean";
8
+ const lower = (flags + " " + desc).toLowerCase();
9
+ if (lower.includes("pct") || lower.includes("percent") || lower.includes("leverage") ||
10
+ lower.includes("amount") || lower.includes("size") || lower.includes("price") ||
11
+ lower.includes("<n>") || lower.includes("<sec>") || lower.includes("<ms>"))
12
+ return "number";
13
+ return "string";
14
+ }
15
+ /** Infer enum values from description */
16
+ function inferEnum(desc) {
17
+ // Match patterns like "buy|sell", "market, limit, stop", "on | off"
18
+ const pipeMatch = desc.match(/:\s*(\w+(?:\s*[|,]\s*\w+)+)/);
19
+ if (pipeMatch) {
20
+ const values = pipeMatch[1].split(/\s*[|,]\s*/).map(v => v.trim()).filter(Boolean);
21
+ if (values.length >= 2 && values.every(v => v.length < 20))
22
+ return values;
23
+ }
24
+ return undefined;
25
+ }
26
+ function extractSchema(cmd, parentPath = "perp") {
27
+ const fullCommand = `${parentPath} ${cmd.name()}`.trim();
28
+ const args = (cmd.registeredArguments ?? []).map((a) => {
29
+ const desc = a.description || "";
30
+ return {
31
+ name: a.name(),
32
+ type: inferType(a.name(), desc),
33
+ required: a.required,
34
+ description: desc,
35
+ enum: inferEnum(desc),
36
+ };
37
+ });
38
+ const options = cmd.options
39
+ .filter((o) => !["--help", "-h"].includes(o.short ?? o.long ?? ""))
40
+ .map((o) => ({
41
+ name: o.long?.replace(/^--/, "") ?? o.short?.replace(/^-/, "") ?? "",
42
+ type: inferType(o.flags, o.description),
43
+ required: o.required ?? false,
44
+ description: o.description,
45
+ ...(o.defaultValue !== undefined ? { default: String(o.defaultValue) } : {}),
46
+ enum: inferEnum(o.description),
47
+ }));
48
+ const subcommands = cmd.commands
49
+ .filter((c) => c.name() !== "help")
50
+ .map((c) => extractSchema(c, fullCommand));
51
+ return {
52
+ name: cmd.name(),
53
+ fullCommand,
54
+ description: cmd.description(),
55
+ args,
56
+ options,
57
+ ...(subcommands.length > 0 ? { subcommands } : {}),
58
+ };
59
+ }
60
+ export function registerAgentCommands(program, getAdapter, isJson) {
61
+ const agent = program
62
+ .command("agent")
63
+ .description("Agent-friendly commands (structured I/O for AI agents)");
64
+ // ── agent schema ── dump full command tree as JSON
65
+ agent
66
+ .command("schema")
67
+ .description("Output full CLI command schema as JSON (for agent discovery)")
68
+ .action(() => {
69
+ const errorCodeDocs = {};
70
+ for (const [key, val] of Object.entries(ERROR_CODES)) {
71
+ errorCodeDocs[key] = { status: val.status, retryable: val.retryable, description: key.toLowerCase().replace(/_/g, " ") };
72
+ }
73
+ const envelope = {
74
+ schemaVersion: "2.0",
75
+ cliVersion: "0.1.0",
76
+ generatedAt: new Date().toISOString(),
77
+ exchanges: ["pacifica", "hyperliquid", "lighter"],
78
+ errorCodes: errorCodeDocs,
79
+ commands: program.commands
80
+ .filter(c => c.name() !== "help")
81
+ .map(c => extractSchema(c)),
82
+ };
83
+ printJson(jsonOk(envelope));
84
+ });
85
+ // ── Top-level schema alias ──
86
+ program
87
+ .command("schema")
88
+ .description("Output CLI schema as JSON (alias for agent schema)")
89
+ .action(() => {
90
+ const errorCodeDocs = {};
91
+ for (const [key, val] of Object.entries(ERROR_CODES)) {
92
+ errorCodeDocs[key] = { status: val.status, retryable: val.retryable, description: key.toLowerCase().replace(/_/g, " ") };
93
+ }
94
+ const envelope = {
95
+ schemaVersion: "2.0",
96
+ cliVersion: "0.1.0",
97
+ generatedAt: new Date().toISOString(),
98
+ exchanges: ["pacifica", "hyperliquid", "lighter"],
99
+ errorCodes: errorCodeDocs,
100
+ commands: program.commands
101
+ .filter(c => c.name() !== "help" && c.name() !== "schema")
102
+ .map(c => extractSchema(c)),
103
+ };
104
+ printJson(jsonOk(envelope));
105
+ });
106
+ // ── agent capabilities ── what this CLI can do
107
+ agent
108
+ .command("capabilities")
109
+ .description("List high-level capabilities for agent planning")
110
+ .action(() => {
111
+ printJson(jsonOk({
112
+ name: "perp-cli",
113
+ version: "0.1.0",
114
+ description: "Multi-DEX Perpetual Futures CLI (Pacifica, Hyperliquid, Lighter) with HIP-3 deployed dex support",
115
+ exchanges: ["pacifica", "hyperliquid", "lighter"],
116
+ capabilities: [
117
+ {
118
+ category: "market_data",
119
+ commands: [
120
+ "perp market list --json",
121
+ "perp market prices --json",
122
+ "perp market book <symbol> --json",
123
+ "perp market trades <symbol> --json",
124
+ "perp market funding <symbol> --json",
125
+ "perp market kline <symbol> <interval> --json",
126
+ ],
127
+ description: "Read market data: prices, orderbooks, trades, funding rates, candles",
128
+ },
129
+ {
130
+ category: "account",
131
+ commands: [
132
+ "perp account info --json",
133
+ "perp account positions --json",
134
+ "perp account orders --json",
135
+ "perp account history --json",
136
+ "perp account trades --json",
137
+ "perp status --json",
138
+ ],
139
+ description: "Read account state: balances, positions, open orders, trade history",
140
+ },
141
+ {
142
+ category: "trading",
143
+ commands: [
144
+ "perp trade check <symbol> <side> <size> --json",
145
+ "perp trade market <symbol> <buy|sell> <size> --json --client-id <id>",
146
+ "perp trade limit <symbol> <buy|sell> <price> <size> --json --client-id <id>",
147
+ "perp trade cancel <symbol> <orderId> --json",
148
+ "perp trade cancel-all --json",
149
+ "perp trade close <symbol> --json",
150
+ "perp trade close-all --json",
151
+ "perp trade flatten --json",
152
+ "perp trade reduce <symbol> <percent> --json",
153
+ "perp trade stop <symbol> <side> <stopPrice> <size> --json",
154
+ "perp trade tpsl <symbol> <side> --tp <price> --sl <price> --json",
155
+ "perp trade twap <symbol> <side> <size> <duration> --json",
156
+ ],
157
+ description: "Execute trades with pre-flight validation, client IDs for idempotency, and position management",
158
+ },
159
+ {
160
+ category: "plan_execution",
161
+ commands: [
162
+ "perp plan validate <file> --json",
163
+ "perp plan execute <file> --json",
164
+ "perp plan execute <file> --dry-run --json",
165
+ "perp plan example",
166
+ ],
167
+ description: "Composite multi-step execution plans with abort/skip/rollback semantics",
168
+ },
169
+ {
170
+ category: "arbitrage",
171
+ commands: [
172
+ "perp arb funding --json",
173
+ "perp arb rates --json",
174
+ "perp arb scan --json",
175
+ "perp arb dex --json",
176
+ "perp arb dex-monitor --min 10",
177
+ "perp gap show --json",
178
+ ],
179
+ description: "Cross-exchange + cross-dex funding arb, price gaps, HIP-3 deployed dex arb",
180
+ },
181
+ {
182
+ category: "risk_management",
183
+ commands: [
184
+ "perp risk status --json",
185
+ "perp risk limits --json",
186
+ "perp risk check --notional <usd> --leverage <n> --json",
187
+ ],
188
+ description: "Portfolio risk assessment, exposure limits, pre-trade risk checks",
189
+ },
190
+ {
191
+ category: "streaming",
192
+ commands: [
193
+ "perp stream events --interval 5000",
194
+ "perp stream prices",
195
+ "perp stream book <symbol>",
196
+ "perp stream trades <symbol>",
197
+ ],
198
+ description: "Real-time NDJSON event stream: position changes, order fills, liquidation warnings, balance updates",
199
+ },
200
+ {
201
+ category: "analytics",
202
+ commands: [
203
+ "perp analytics summary --json",
204
+ "perp analytics pnl --json",
205
+ "perp analytics funding --json",
206
+ "perp portfolio --json",
207
+ "perp health --json",
208
+ "perp history list --json",
209
+ ],
210
+ description: "Cross-exchange portfolio, PnL analytics, execution history, health checks",
211
+ },
212
+ {
213
+ category: "discovery",
214
+ commands: [
215
+ "perp schema",
216
+ "perp agent schema",
217
+ "perp agent capabilities",
218
+ "perp agent ping",
219
+ "perp dex list --json",
220
+ "perp dex markets <name> --json",
221
+ ],
222
+ description: "CLI schema discovery, connectivity checks, HIP-3 dex discovery",
223
+ },
224
+ ],
225
+ agentFeatures: [
226
+ "Structured JSON output (--json) on all commands",
227
+ "Structured error codes with retryable flag (INSUFFICIENT_BALANCE, RATE_LIMITED, etc.)",
228
+ "Client order IDs for idempotent retries (--client-id / --auto-id)",
229
+ "Pre-trade validation (perp trade check) before execution",
230
+ "Multi-step execution plans with rollback (perp plan execute)",
231
+ "NDJSON event streaming for real-time monitoring",
232
+ "HIP-3 cross-dex arbitrage scanning",
233
+ ],
234
+ notes: [
235
+ "Always use --json flag for machine-readable output",
236
+ "Use -e <exchange> to switch between pacifica, hyperliquid, lighter",
237
+ "Use --dex <name> for HIP-3 deployed perp dexes on Hyperliquid",
238
+ "Use -n testnet for testnet mode",
239
+ "Use --client-id or --auto-id on trade commands for retry safety",
240
+ "Use perp trade check before execution for pre-flight validation",
241
+ "Errors include { code, retryable, status } for automated handling",
242
+ "Exit code 0 = success, 1 = error",
243
+ ],
244
+ }));
245
+ });
246
+ // ── agent exec ── execute a sequence of commands
247
+ agent
248
+ .command("exec")
249
+ .description("Execute a command and return structured JSON result")
250
+ .argument("<command...>", "Command to execute (e.g., 'market list')")
251
+ .action(async (args) => {
252
+ // Re-parse the command through the program
253
+ // This is a convenience wrapper that forces --json
254
+ const fullArgs = ["node", "perp", "--json", ...args];
255
+ try {
256
+ await program.parseAsync(fullArgs);
257
+ }
258
+ catch (err) {
259
+ const msg = err instanceof Error ? err.message : String(err);
260
+ console.error(JSON.stringify({ error: msg }));
261
+ process.exit(1);
262
+ }
263
+ });
264
+ // ── agent ping ── health check
265
+ agent
266
+ .command("ping")
267
+ .description("Health check — returns exchange connectivity status")
268
+ .action(async () => {
269
+ const results = {
270
+ timestamp: new Date().toISOString(),
271
+ cli_version: "0.1.0",
272
+ };
273
+ // Check exchange APIs
274
+ const { pingPacifica, pingHyperliquid } = await import("../shared-api.js");
275
+ const [pacPing, hlPing] = await Promise.all([pingPacifica(), pingHyperliquid()]);
276
+ results.pacifica = {
277
+ status: pacPing.ok ? "ok" : "error",
278
+ latency_ms: pacPing.latencyMs,
279
+ http_status: pacPing.status,
280
+ };
281
+ results.hyperliquid = {
282
+ status: hlPing.ok ? "ok" : "error",
283
+ latency_ms: hlPing.latencyMs,
284
+ http_status: hlPing.status,
285
+ };
286
+ // Check relayer
287
+ try {
288
+ const start = Date.now();
289
+ const res = await fetch("http://localhost:3100/health", {
290
+ signal: AbortSignal.timeout(2000),
291
+ });
292
+ results.relayer = {
293
+ status: res.ok ? "ok" : "error",
294
+ latency_ms: Date.now() - start,
295
+ };
296
+ }
297
+ catch {
298
+ results.relayer = { status: "offline" };
299
+ }
300
+ if (isJson())
301
+ return printJson(jsonOk(results));
302
+ console.log(chalk.cyan.bold("\n Connectivity Check\n"));
303
+ for (const [name, data] of Object.entries(results)) {
304
+ if (typeof data !== "object" || !data) {
305
+ console.log(` ${name}: ${data}`);
306
+ continue;
307
+ }
308
+ const d = data;
309
+ const icon = d.status === "ok" ? chalk.green("OK") : chalk.red(String(d.status).toUpperCase());
310
+ const latency = d.latency_ms ? chalk.gray(` (${d.latency_ms}ms)`) : "";
311
+ console.log(` ${name.padEnd(14)} ${icon}${latency}`);
312
+ }
313
+ console.log();
314
+ });
315
+ // ── agent plan ── given a goal, suggest a command sequence
316
+ agent
317
+ .command("plan")
318
+ .description("Suggest a command sequence for a given trading goal")
319
+ .argument("<goal>", "Natural language goal (e.g., 'buy 0.1 BTC on pacifica')")
320
+ .action(async (goal) => {
321
+ const g = goal.toLowerCase();
322
+ const steps = [];
323
+ if (g.includes("buy") || g.includes("long")) {
324
+ const symbol = extractSymbol(g) || "BTC";
325
+ const size = extractNumber(g) || "0.01";
326
+ steps.push({ step: 1, command: `perp market book ${symbol} --json`, description: `Check ${symbol} orderbook` }, { step: 2, command: `perp account info --json`, description: "Check available balance" }, { step: 3, command: `perp trade market ${symbol} buy ${size} --json`, description: `Buy ${size} ${symbol}` }, { step: 4, command: `perp account positions --json`, description: "Verify position opened" });
327
+ }
328
+ else if (g.includes("sell") || g.includes("short")) {
329
+ const symbol = extractSymbol(g) || "BTC";
330
+ const size = extractNumber(g) || "0.01";
331
+ steps.push({ step: 1, command: `perp market book ${symbol} --json`, description: `Check ${symbol} orderbook` }, { step: 2, command: `perp account info --json`, description: "Check available balance" }, { step: 3, command: `perp trade market ${symbol} sell ${size} --json`, description: `Sell ${size} ${symbol}` }, { step: 4, command: `perp account positions --json`, description: "Verify position opened" });
332
+ }
333
+ else if (g.includes("close") || g.includes("exit")) {
334
+ const symbol = extractSymbol(g) || "ALL";
335
+ steps.push({ step: 1, command: "perp account positions --json", description: "Get current positions" }, { step: 2, command: `perp trade cancel-all --json`, description: "Cancel any open orders" });
336
+ if (symbol !== "ALL") {
337
+ steps.push({ step: 3, command: `perp trade market ${symbol} sell <position_size> --json`, description: `Close ${symbol} position (adjust side/size from step 1)` });
338
+ }
339
+ }
340
+ else if (g.includes("arb") || g.includes("arbitrage") || g.includes("funding")) {
341
+ steps.push({ step: 1, command: "perp arb rates --json", description: "Compare funding rates across exchanges" }, { step: 2, command: "perp arb scan --json", description: "Find high-spread opportunities" }, { step: 3, command: "perp gap show --json", description: "Check price gaps" }, { step: 4, command: "perp arb auto --dry-run --min-spread 30", description: "Dry-run auto arb bot" });
342
+ }
343
+ else if (g.includes("status") || g.includes("check") || g.includes("overview")) {
344
+ steps.push({ step: 1, command: "perp status --json", description: "Full account overview" }, { step: 2, command: "perp account positions --json", description: "Detailed positions" }, { step: 3, command: "perp account orders --json", description: "Open orders" });
345
+ }
346
+ else if (g.includes("deposit")) {
347
+ const amount = extractNumber(g) || "100";
348
+ steps.push({ step: 1, command: "perp wallet balance --json", description: "Check wallet balance" }, { step: 2, command: `perp deposit pacifica ${amount} --json`, description: `Deposit $${amount} to Pacifica` }, { step: 3, command: "perp account info --json", description: "Verify deposit arrived" });
349
+ }
350
+ else if (g.includes("price") || g.includes("market")) {
351
+ const symbol = extractSymbol(g);
352
+ if (symbol) {
353
+ steps.push({ step: 1, command: `perp market book ${symbol} --json`, description: `${symbol} orderbook` }, { step: 2, command: `perp market funding ${symbol} --json`, description: `${symbol} funding history` }, { step: 3, command: `perp market kline ${symbol} 1h --json`, description: `${symbol} hourly candles` });
354
+ }
355
+ else {
356
+ steps.push({ step: 1, command: "perp market prices --json", description: "All market prices" }, { step: 2, command: "perp gap show --json", description: "Cross-exchange price gaps" });
357
+ }
358
+ }
359
+ else {
360
+ steps.push({ step: 1, command: "perp agent capabilities", description: "List all available capabilities" }, { step: 2, command: "perp status --json", description: "Check account status" });
361
+ }
362
+ printJson(jsonOk({
363
+ goal,
364
+ exchange: "pacifica",
365
+ steps,
366
+ notes: [
367
+ "All commands should include --json for structured output",
368
+ "Adjust exchange with -e hyperliquid if needed",
369
+ "Check return values before proceeding to next step",
370
+ ],
371
+ }));
372
+ });
373
+ }
374
+ function extractSymbol(text) {
375
+ const symbols = ["BTC", "ETH", "SOL", "ARB", "DOGE", "WIF", "JTO", "PYTH", "JUP", "ONDO", "SUI", "APT", "AVAX", "LINK", "OP", "MATIC", "NEAR", "AAVE", "UNI", "TIA"];
376
+ const upper = text.toUpperCase();
377
+ for (const s of symbols) {
378
+ if (upper.includes(s))
379
+ return s;
380
+ }
381
+ return null;
382
+ }
383
+ function extractNumber(text) {
384
+ const match = text.match(/(\d+\.?\d*)/);
385
+ return match ? match[1] : null;
386
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerAlertCommands(program: Command, isJson: () => boolean, getAdapterFor?: (exchange: string) => Promise<import("../exchanges/interface.js").ExchangeAdapter>): void;