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,309 @@
1
+ import { PacificaAdapter } from "../exchanges/pacifica.js";
2
+ import { printJson, jsonOk } from "../utils.js";
3
+ import chalk from "chalk";
4
+ export function registerManageCommands(program, getAdapter, isJson, getPacificaAdapter) {
5
+ const manage = program.command("manage").description("Account management");
6
+ // Ensure adapter is initialized before accessing PacificaAdapter
7
+ async function pac() {
8
+ const adapter = await getAdapter();
9
+ if (!(adapter instanceof PacificaAdapter)) {
10
+ throw new Error("This command requires --exchange pacifica");
11
+ }
12
+ return adapter;
13
+ }
14
+ manage
15
+ .command("margin <symbol> <mode>")
16
+ .description("Set margin mode (cross/isolated)")
17
+ .action(async (symbol, mode) => {
18
+ const m = mode.toLowerCase();
19
+ if (m !== "cross" && m !== "isolated") {
20
+ console.error(chalk.red("Mode must be cross or isolated"));
21
+ process.exit(1);
22
+ }
23
+ const a = await pac();
24
+ const result = await a.sdk.updateMarginMode({ symbol: symbol.toUpperCase(), is_isolated: m === "isolated" }, a.publicKey, a.signer);
25
+ if (isJson())
26
+ return printJson(jsonOk(result));
27
+ console.log(chalk.green(`\n Margin mode for ${symbol.toUpperCase()} set to ${m}.\n`));
28
+ });
29
+ manage
30
+ .command("withdraw <amount> <address>")
31
+ .description("Withdraw funds to a Solana address")
32
+ .action(async (amount, address) => {
33
+ const a = await pac();
34
+ const result = await a.sdk.withdraw({ amount, dest_address: address }, a.publicKey, a.signer);
35
+ if (isJson())
36
+ return printJson(jsonOk(result));
37
+ console.log(chalk.green(`\n Withdrawal of $${amount} to ${address} submitted.\n`));
38
+ });
39
+ // Subaccounts
40
+ const sub = manage.command("sub").description("Subaccount management");
41
+ sub
42
+ .command("create <name>")
43
+ .description("Create a subaccount")
44
+ .action(async (name) => {
45
+ const a = await pac();
46
+ const result = await a.sdk.createSubaccount(name, a.publicKey, a.signer);
47
+ if (isJson())
48
+ return printJson(jsonOk(result));
49
+ console.log(chalk.green(`\n Subaccount "${name}" created.\n`));
50
+ });
51
+ sub
52
+ .command("list")
53
+ .description("List subaccounts")
54
+ .action(async () => {
55
+ const a = await pac();
56
+ const result = await a.sdk.listSubaccounts(a.publicKey, a.signer);
57
+ if (isJson())
58
+ return printJson(jsonOk(result));
59
+ printJson(jsonOk(result));
60
+ });
61
+ sub
62
+ .command("transfer <from> <to> <amount>")
63
+ .description("Transfer funds between accounts")
64
+ .action(async (from, to, amount) => {
65
+ const a = await pac();
66
+ const result = await a.sdk.transferFunds({ from_account: from, to_account: to, amount }, a.publicKey, a.signer);
67
+ if (isJson())
68
+ return printJson(jsonOk(result));
69
+ console.log(chalk.green(`\n Transferred $${amount}.\n`));
70
+ });
71
+ // Agent wallets
72
+ const agent = manage.command("agent").description("Agent wallet management");
73
+ agent
74
+ .command("bind <wallet>")
75
+ .description("Bind an agent wallet")
76
+ .action(async (wallet) => {
77
+ const a = await pac();
78
+ const result = await a.sdk.bindAgentWallet(wallet, a.publicKey, a.signer);
79
+ if (isJson())
80
+ return printJson(jsonOk(result));
81
+ console.log(chalk.green(`\n Agent wallet ${wallet} bound.\n`));
82
+ });
83
+ agent
84
+ .command("list")
85
+ .description("List agent wallets")
86
+ .action(async () => {
87
+ const a = await pac();
88
+ const result = await a.sdk.listAgentWallets(a.publicKey, a.signer);
89
+ if (isJson())
90
+ return printJson(jsonOk(result));
91
+ printJson(jsonOk(result));
92
+ });
93
+ agent
94
+ .command("revoke <wallet>")
95
+ .description("Revoke an agent wallet")
96
+ .action(async (wallet) => {
97
+ const a = await pac();
98
+ const result = await a.sdk.revokeAgentWallet(wallet, a.publicKey, a.signer);
99
+ if (isJson())
100
+ return printJson(jsonOk(result));
101
+ console.log(chalk.green(`\n Agent wallet ${wallet} revoked.\n`));
102
+ });
103
+ agent
104
+ .command("revoke-all")
105
+ .description("Revoke all agent wallets")
106
+ .action(async () => {
107
+ const a = await pac();
108
+ const result = await a.sdk.revokeAllAgentWallets(a.publicKey, a.signer);
109
+ if (isJson())
110
+ return printJson(jsonOk(result));
111
+ console.log(chalk.green("\n All agent wallets revoked.\n"));
112
+ });
113
+ // Lake (liquidity vaults)
114
+ const lake = manage.command("lake").description("Lake (liquidity vault) management");
115
+ lake
116
+ .command("create <symbol> <amount>")
117
+ .description("Create a new lake")
118
+ .action(async (symbol, amount) => {
119
+ const a = await pac();
120
+ const result = await a.sdk.createLake({ symbol: symbol.toUpperCase(), amount }, a.publicKey, a.signer);
121
+ if (isJson())
122
+ return printJson(jsonOk(result));
123
+ console.log(chalk.green(`\n Lake created for ${symbol.toUpperCase()} with $${amount}.\n`));
124
+ printJson(jsonOk(result));
125
+ });
126
+ lake
127
+ .command("deposit <lakeId> <amount>")
128
+ .description("Deposit to a lake")
129
+ .action(async (lakeId, amount) => {
130
+ const a = await pac();
131
+ const result = await a.sdk.depositToLake({ lake_id: lakeId, amount }, a.publicKey, a.signer);
132
+ if (isJson())
133
+ return printJson(jsonOk(result));
134
+ console.log(chalk.green(`\n Deposited $${amount} to lake ${lakeId}.\n`));
135
+ });
136
+ lake
137
+ .command("withdraw <lakeId> <amount>")
138
+ .description("Withdraw from a lake")
139
+ .action(async (lakeId, amount) => {
140
+ const a = await pac();
141
+ const result = await a.sdk.withdrawFromLake({ lake_id: lakeId, amount }, a.publicKey, a.signer);
142
+ if (isJson())
143
+ return printJson(jsonOk(result));
144
+ console.log(chalk.green(`\n Withdrew $${amount} from lake ${lakeId}.\n`));
145
+ });
146
+ // Builder Codes
147
+ const builder = manage.command("builder").description("Builder code management (Pacifica)");
148
+ builder
149
+ .command("approve <code> <maxFeeRate>")
150
+ .description("Approve a builder code (e.g. approve MYCODE 0.001)")
151
+ .action(async (code, maxFeeRate) => {
152
+ const a = await pac();
153
+ const result = await a.sdk.approveBuilderCode({ builder_code: code, max_fee_rate: maxFeeRate }, a.publicKey, a.signer);
154
+ if (isJson())
155
+ return printJson(jsonOk(result));
156
+ console.log(chalk.green(`\n Builder code "${code}" approved (max fee: ${maxFeeRate}).\n`));
157
+ });
158
+ builder
159
+ .command("revoke <code>")
160
+ .description("Revoke a builder code")
161
+ .action(async (code) => {
162
+ const a = await pac();
163
+ const result = await a.sdk.revokeBuilderCode({ builder_code: code }, a.publicKey, a.signer);
164
+ if (isJson())
165
+ return printJson(jsonOk(result));
166
+ console.log(chalk.green(`\n Builder code "${code}" revoked.\n`));
167
+ });
168
+ builder
169
+ .command("list")
170
+ .description("List approved builder codes")
171
+ .action(async () => {
172
+ const a = await pac();
173
+ const result = await a.sdk.getBuilderApprovals(a.publicKey);
174
+ if (isJson())
175
+ return printJson(jsonOk(result));
176
+ const approvals = result;
177
+ if (!Array.isArray(approvals) || approvals.length === 0) {
178
+ console.log(chalk.gray("\n No builder codes approved.\n"));
179
+ return;
180
+ }
181
+ console.log(chalk.cyan.bold("\n Approved Builder Codes\n"));
182
+ for (const b of approvals) {
183
+ console.log(` ${chalk.white(b.builder_code.padEnd(16))} max_fee: ${b.max_fee_rate} ${chalk.gray(b.description || "")}`);
184
+ }
185
+ console.log();
186
+ });
187
+ builder
188
+ .command("overview")
189
+ .description("Show your builder code overview (if you are a builder)")
190
+ .action(async () => {
191
+ const a = await pac();
192
+ const result = await a.sdk.getBuilderOverview(a.publicKey);
193
+ if (isJson())
194
+ return printJson(jsonOk(result));
195
+ printJson(jsonOk(result));
196
+ });
197
+ builder
198
+ .command("trades <code>")
199
+ .description("Show trade history for a builder code")
200
+ .action(async (code) => {
201
+ const a = await pac();
202
+ const result = await a.sdk.getBuilderTrades(code);
203
+ if (isJson())
204
+ return printJson(jsonOk(result));
205
+ printJson(jsonOk(result));
206
+ });
207
+ builder
208
+ .command("leaderboard <code>")
209
+ .description("Show user leaderboard for a builder code")
210
+ .action(async (code) => {
211
+ const a = await pac();
212
+ const result = await a.sdk.getBuilderLeaderboard(code);
213
+ if (isJson())
214
+ return printJson(jsonOk(result));
215
+ printJson(jsonOk(result));
216
+ });
217
+ builder
218
+ .command("update-fee <code> <feeRate>")
219
+ .description("Update fee rate for your builder code (builder owners only)")
220
+ .action(async (code, feeRate) => {
221
+ const a = await pac();
222
+ const result = await a.sdk.updateBuilderFeeRate({ builder_code: code, fee_rate: feeRate }, a.publicKey, a.signer);
223
+ if (isJson())
224
+ return printJson(jsonOk(result));
225
+ console.log(chalk.green(`\n Builder code "${code}" fee rate updated to ${feeRate}.\n`));
226
+ });
227
+ // Referral
228
+ const referral = manage.command("referral").description("Referral code management (Pacifica)");
229
+ referral
230
+ .command("claim <code>")
231
+ .description("Claim a referral code")
232
+ .action(async (code) => {
233
+ const a = await pac();
234
+ const result = await a.sdk.claimReferralCode({ code }, a.publicKey, a.signer);
235
+ if (isJson())
236
+ return printJson(jsonOk(result));
237
+ console.log(chalk.green(`\n Referral code "${code}" claimed!\n`));
238
+ });
239
+ // API Keys
240
+ const apikey = manage.command("apikey").description("API key management");
241
+ apikey
242
+ .command("create <name> <maxFeeRate>")
243
+ .description("Create an API key")
244
+ .action(async (name, maxFeeRate) => {
245
+ const a = await pac();
246
+ const result = await a.sdk.createApiKey(name, maxFeeRate, a.publicKey, a.signer);
247
+ if (isJson())
248
+ return printJson(jsonOk(result));
249
+ console.log(chalk.green(`\n API key "${name}" created.\n`));
250
+ printJson(jsonOk(result));
251
+ });
252
+ apikey
253
+ .command("list")
254
+ .description("List API keys")
255
+ .action(async () => {
256
+ const a = await pac();
257
+ const result = await a.sdk.listApiKeys(a.publicKey, a.signer);
258
+ if (isJson())
259
+ return printJson(jsonOk(result));
260
+ printJson(jsonOk(result));
261
+ });
262
+ apikey
263
+ .command("revoke <key>")
264
+ .description("Revoke an API key")
265
+ .action(async (key) => {
266
+ const a = await pac();
267
+ const result = await a.sdk.revokeApiKey(key, a.publicKey, a.signer);
268
+ if (isJson())
269
+ return printJson(jsonOk(result));
270
+ console.log(chalk.green(`\n API key revoked.\n`));
271
+ });
272
+ // === Lighter API Key Setup ===
273
+ manage
274
+ .command("setup-api-key")
275
+ .description("Generate & register a Lighter API key (required for trading)")
276
+ .option("--key-index <n>", "API key index (2-254, default: 2)", "2")
277
+ .action(async (opts) => {
278
+ const adapter = await getAdapter();
279
+ const { LighterAdapter } = await import("../exchanges/lighter.js");
280
+ if (!(adapter instanceof LighterAdapter)) {
281
+ throw new Error("This command requires --exchange lighter");
282
+ }
283
+ const keyIndex = parseInt(opts.keyIndex);
284
+ if (!isJson()) {
285
+ console.log(chalk.cyan.bold("\n Lighter API Key Setup\n"));
286
+ console.log(chalk.gray(` Account: ${adapter.address} (index: ${adapter.accountIndex})`));
287
+ console.log(chalk.gray(` API Key Index: ${keyIndex}\n`));
288
+ console.log(chalk.gray(" Generating key pair + registering on-chain...\n"));
289
+ }
290
+ const { privateKey, publicKey } = await adapter.setupApiKey(keyIndex);
291
+ if (isJson()) {
292
+ return printJson(jsonOk({
293
+ privateKey,
294
+ publicKey,
295
+ address: adapter.address,
296
+ accountIndex: adapter.accountIndex,
297
+ apiKeyIndex: keyIndex,
298
+ }));
299
+ }
300
+ console.log(chalk.green(" API Key Registered!\n"));
301
+ console.log(` ${chalk.bold("Private Key:")} ${privateKey}`);
302
+ console.log(` ${chalk.bold("Public Key:")} ${publicKey}`);
303
+ console.log();
304
+ console.log(chalk.yellow(" Add to your .env file:"));
305
+ console.log(chalk.white(` LIGHTER_API_KEY=${privateKey}`));
306
+ console.log(chalk.white(` LIGHTER_ACCOUNT_INDEX=${adapter.accountIndex}`));
307
+ console.log();
308
+ });
309
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { ExchangeAdapter } from "../exchanges/interface.js";
3
+ export declare function registerMarketCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean): void;
@@ -0,0 +1,225 @@
1
+ import { PacificaAdapter } from "../exchanges/pacifica.js";
2
+ import { makeTable, formatUsd, formatPercent, printJson, jsonOk, jsonError } from "../utils.js";
3
+ import chalk from "chalk";
4
+ export function registerMarketCommands(program, getAdapter, isJson) {
5
+ const market = program.command("market").description("Market data commands");
6
+ market
7
+ .command("list")
8
+ .description("List all available markets")
9
+ .action(async () => {
10
+ const adapter = await getAdapter();
11
+ const markets = await adapter.getMarkets();
12
+ if (isJson())
13
+ return printJson(jsonOk(markets));
14
+ const rows = markets.map((m) => [
15
+ chalk.white.bold(m.symbol),
16
+ `$${formatUsd(m.markPrice)}`,
17
+ `$${formatUsd(m.indexPrice)}`,
18
+ formatPercent(m.fundingRate),
19
+ `$${formatUsd(m.volume24h)}`,
20
+ `$${formatUsd(m.openInterest)}`,
21
+ String(m.maxLeverage) + "x",
22
+ ]);
23
+ console.log(makeTable(["Symbol", "Mark", "Index", "Funding", "24h Vol", "OI", "Max Lev"], rows));
24
+ });
25
+ market
26
+ .command("prices")
27
+ .description("Get current prices for all markets")
28
+ .action(async () => {
29
+ const adapter = await getAdapter();
30
+ if (adapter instanceof PacificaAdapter) {
31
+ const prices = await adapter.sdk.getPrices();
32
+ if (isJson())
33
+ return printJson(jsonOk(prices));
34
+ const rows = prices.map((p) => [
35
+ chalk.white.bold(p.symbol),
36
+ `$${formatUsd(p.mark)}`,
37
+ `$${formatUsd(p.mid)}`,
38
+ `$${formatUsd(p.oracle)}`,
39
+ formatPercent(p.funding),
40
+ ]);
41
+ console.log(makeTable(["Symbol", "Mark", "Mid", "Oracle", "Funding"], rows));
42
+ }
43
+ else {
44
+ // Generic: use getMarkets as price source
45
+ const markets = await adapter.getMarkets();
46
+ if (isJson())
47
+ return printJson(jsonOk(markets));
48
+ const rows = markets.map((m) => [
49
+ chalk.white.bold(m.symbol),
50
+ `$${formatUsd(m.markPrice)}`,
51
+ `$${formatUsd(m.indexPrice)}`,
52
+ formatPercent(m.fundingRate),
53
+ ]);
54
+ console.log(makeTable(["Symbol", "Mark", "Index", "Funding"], rows));
55
+ }
56
+ });
57
+ market
58
+ .command("info <symbol>")
59
+ .description("Detailed info for a single market")
60
+ .action(async (symbol) => {
61
+ const adapter = await getAdapter();
62
+ const markets = await adapter.getMarkets();
63
+ const sym = symbol.toUpperCase();
64
+ const m = markets.find((mk) => mk.symbol === sym || mk.symbol === `${sym}-PERP` || mk.symbol.replace(/-PERP$/, "") === sym);
65
+ if (!m) {
66
+ if (isJson())
67
+ return printJson(jsonError("SYMBOL_NOT_FOUND", `Market ${sym} not found`));
68
+ console.log(chalk.red(`\n Market "${sym}" not found.\n`));
69
+ return;
70
+ }
71
+ if (isJson())
72
+ return printJson(jsonOk(m));
73
+ console.log(chalk.cyan.bold(`\n ${m.symbol} on ${adapter.name}\n`));
74
+ console.log(` Mark Price: $${formatUsd(m.markPrice)}`);
75
+ console.log(` Index Price: $${formatUsd(m.indexPrice)}`);
76
+ console.log(` Funding Rate: ${formatPercent(m.fundingRate)}`);
77
+ console.log(` 24h Volume: $${formatUsd(m.volume24h)}`);
78
+ console.log(` Open Interest: $${formatUsd(m.openInterest)}`);
79
+ console.log(` Max Leverage: ${m.maxLeverage}x`);
80
+ console.log();
81
+ });
82
+ market
83
+ .command("book <symbol>")
84
+ .description("Show orderbook for a symbol")
85
+ .option("-d, --depth <n>", "Number of levels", "10")
86
+ .action(async (symbol, opts) => {
87
+ const adapter = await getAdapter();
88
+ const book = await adapter.getOrderbook(symbol.toUpperCase());
89
+ if (isJson())
90
+ return printJson(jsonOk(book));
91
+ const depth = parseInt(opts.depth);
92
+ const asks = book.asks.slice(0, depth).reverse();
93
+ const bids = book.bids.slice(0, depth);
94
+ console.log(chalk.cyan.bold(`\n Orderbook: ${symbol.toUpperCase()} (${adapter.name})\n`));
95
+ console.log(chalk.gray(" Price Size"));
96
+ console.log(chalk.gray(" ─────────────────────"));
97
+ asks.forEach(([p, a]) => {
98
+ console.log(chalk.red(` ${formatUsd(p).padStart(12)} ${a}`));
99
+ });
100
+ console.log(chalk.gray(" ─── spread ───"));
101
+ bids.forEach(([p, a]) => {
102
+ console.log(chalk.green(` ${formatUsd(p).padStart(12)} ${a}`));
103
+ });
104
+ console.log();
105
+ });
106
+ market
107
+ .command("trades <symbol>")
108
+ .description("Recent trades for a symbol")
109
+ .action(async (symbol) => {
110
+ const adapter = await getAdapter();
111
+ const trades = await adapter.getRecentTrades(symbol.toUpperCase(), 20);
112
+ if (isJson())
113
+ return printJson(jsonOk(trades));
114
+ if (trades.length === 0) {
115
+ console.log(chalk.gray("\n No recent trades.\n"));
116
+ return;
117
+ }
118
+ const rows = trades.map((t) => [
119
+ new Date(t.time).toLocaleTimeString(),
120
+ t.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
121
+ `$${formatUsd(t.price)}`,
122
+ t.size,
123
+ ]);
124
+ console.log(makeTable(["Time", "Side", "Price", "Size"], rows));
125
+ });
126
+ market
127
+ .command("funding <symbol>")
128
+ .description("Funding rate history")
129
+ .option("-l, --limit <n>", "Number of records", "10")
130
+ .action(async (symbol, opts) => {
131
+ const adapter = await getAdapter();
132
+ const history = await adapter.getFundingHistory(symbol.toUpperCase(), parseInt(opts.limit));
133
+ if (isJson())
134
+ return printJson(jsonOk(history));
135
+ if (history.length === 0) {
136
+ console.log(chalk.gray("\n No funding history.\n"));
137
+ return;
138
+ }
139
+ const rows = history.map((h) => [
140
+ new Date(h.time).toLocaleString(),
141
+ formatPercent(h.rate),
142
+ `$${formatUsd(h.price)}`,
143
+ ]);
144
+ console.log(makeTable(["Time", "Funding Rate", "Oracle"], rows));
145
+ });
146
+ market
147
+ .command("mid <symbol>")
148
+ .description("Get mid price for a single symbol (fast)")
149
+ .action(async (symbol) => {
150
+ const sym = symbol.toUpperCase();
151
+ try {
152
+ const adapter = await getAdapter();
153
+ // Try orderbook mid (best bid + best ask) / 2
154
+ const book = await adapter.getOrderbook(sym);
155
+ const bestBid = book.bids[0]?.[0];
156
+ const bestAsk = book.asks[0]?.[0];
157
+ if (!bestBid && !bestAsk) {
158
+ if (isJson())
159
+ return printJson(jsonError("SYMBOL_NOT_FOUND", `No orderbook data for ${sym}`));
160
+ console.log(chalk.red(`\n No orderbook data for ${sym}.\n`));
161
+ return;
162
+ }
163
+ const bid = Number(bestBid ?? 0);
164
+ const ask = Number(bestAsk ?? 0);
165
+ const mid = bid && ask ? (bid + ask) / 2 : bid || ask;
166
+ const spread = bid && ask ? ((ask - bid) / mid * 100) : 0;
167
+ if (isJson())
168
+ return printJson(jsonOk({
169
+ symbol: sym,
170
+ mid: mid.toString(),
171
+ bid: bestBid ?? null,
172
+ ask: bestAsk ?? null,
173
+ spread: spread.toFixed(6),
174
+ }));
175
+ console.log(chalk.cyan.bold(`\n ${sym} Mid Price\n`));
176
+ console.log(` Mid: $${formatUsd(mid)}`);
177
+ if (bestBid)
178
+ console.log(` Bid: $${formatUsd(bestBid)}`);
179
+ if (bestAsk)
180
+ console.log(` Ask: $${formatUsd(bestAsk)}`);
181
+ console.log(` Spread: ${spread.toFixed(4)}%`);
182
+ console.log();
183
+ }
184
+ catch (err) {
185
+ const msg = err instanceof Error ? err.message : String(err);
186
+ if (isJson()) {
187
+ const { classifyError } = await import("../errors.js");
188
+ const classified = classifyError(err);
189
+ return printJson(jsonError(classified.code, classified.message, {
190
+ status: classified.status,
191
+ retryable: classified.retryable,
192
+ }));
193
+ }
194
+ console.error(chalk.red(`Error: ${msg}`));
195
+ }
196
+ });
197
+ market
198
+ .command("kline <symbol> <interval>")
199
+ .description("Kline/candlestick data (intervals: 1m,5m,15m,1h,4h,1d,...)")
200
+ .option("--start <ts>", "Start time (unix ms)")
201
+ .option("--end <ts>", "End time (unix ms)")
202
+ .action(async (symbol, interval, opts) => {
203
+ const adapter = await getAdapter();
204
+ const now = Date.now();
205
+ const startTime = opts.start ? parseInt(opts.start) : now - 24 * 60 * 60 * 1000;
206
+ const endTime = opts.end ? parseInt(opts.end) : now;
207
+ const klines = await adapter.getKlines(symbol.toUpperCase(), interval, startTime, endTime);
208
+ if (isJson())
209
+ return printJson(jsonOk(klines));
210
+ if (klines.length === 0) {
211
+ console.log(chalk.gray("\n No kline data.\n"));
212
+ return;
213
+ }
214
+ const rows = klines.slice(-20).map((k) => [
215
+ new Date(k.time).toLocaleString(),
216
+ `$${formatUsd(k.open)}`,
217
+ `$${formatUsd(k.high)}`,
218
+ `$${formatUsd(k.low)}`,
219
+ `$${formatUsd(k.close)}`,
220
+ k.volume,
221
+ String(k.trades),
222
+ ]);
223
+ console.log(makeTable(["Time", "Open", "High", "Low", "Close", "Volume", "Trades"], rows));
224
+ });
225
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { ExchangeAdapter } from "../exchanges/interface.js";
3
+ export declare function registerPlanCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean): void;
@@ -0,0 +1,95 @@
1
+ import { readFileSync } from "fs";
2
+ import { printJson, jsonOk, jsonError, withJsonErrors } from "../utils.js";
3
+ import { validatePlan, executePlan } from "../plan-executor.js";
4
+ import chalk from "chalk";
5
+ export function registerPlanCommands(program, getAdapter, isJson) {
6
+ const plan = program.command("plan").description("Composite execution plans (multi-step atomic operations)");
7
+ // ── plan validate ──
8
+ plan
9
+ .command("validate <file>")
10
+ .description("Validate a JSON execution plan without executing")
11
+ .action(async (file) => {
12
+ await withJsonErrors(isJson(), async () => {
13
+ const raw = file === "-" ? readFileSync(0, "utf-8") : readFileSync(file, "utf-8");
14
+ const planData = JSON.parse(raw);
15
+ const result = validatePlan(planData);
16
+ if (isJson())
17
+ return printJson(jsonOk(result));
18
+ if (result.valid) {
19
+ console.log(chalk.green(`\n Plan is valid (${planData.steps?.length ?? 0} steps).\n`));
20
+ }
21
+ else {
22
+ console.log(chalk.red(`\n Plan validation failed:\n`));
23
+ for (const err of result.errors) {
24
+ console.log(chalk.red(` • ${err}`));
25
+ }
26
+ console.log();
27
+ }
28
+ });
29
+ });
30
+ // ── plan execute ──
31
+ plan
32
+ .command("execute <file>")
33
+ .description("Execute a JSON plan (use - for stdin)")
34
+ .option("--dry-run", "Simulate without executing trades")
35
+ .action(async (file, opts) => {
36
+ await withJsonErrors(isJson(), async () => {
37
+ const raw = file === "-" ? readFileSync(0, "utf-8") : readFileSync(file, "utf-8");
38
+ const planData = JSON.parse(raw);
39
+ // Validate first
40
+ const validation = validatePlan(planData);
41
+ if (!validation.valid) {
42
+ if (isJson())
43
+ return printJson(jsonError("INVALID_PARAMS", `Plan validation failed: ${validation.errors.join("; ")}`));
44
+ console.error(chalk.red(`\n Plan validation failed:`));
45
+ for (const err of validation.errors)
46
+ console.error(chalk.red(` • ${err}`));
47
+ return;
48
+ }
49
+ const adapter = await getAdapter();
50
+ const log = isJson() ? () => { } : (msg) => console.log(chalk.gray(` ${msg}`));
51
+ if (!isJson()) {
52
+ console.log(chalk.cyan.bold(`\n Executing plan (${planData.steps.length} steps)${opts.dryRun ? " [DRY RUN]" : ""}...\n`));
53
+ }
54
+ const result = await executePlan(adapter, planData, {
55
+ dryRun: opts.dryRun,
56
+ log,
57
+ });
58
+ if (isJson())
59
+ return printJson(jsonOk(result));
60
+ // Pretty print results
61
+ for (const step of result.steps) {
62
+ const icon = step.status === "success" ? chalk.green("✓")
63
+ : step.status === "dry_run" ? chalk.blue("○")
64
+ : step.status === "skipped" ? chalk.yellow("–")
65
+ : chalk.red("✗");
66
+ const duration = chalk.gray(`(${step.durationMs}ms)`);
67
+ const err = step.error ? chalk.red(` — ${step.error.message}`) : "";
68
+ console.log(` ${icon} ${step.stepId} (${step.action}) ${duration}${err}`);
69
+ }
70
+ const statusColor = result.status === "completed" ? chalk.green
71
+ : result.status === "dry_run" ? chalk.blue
72
+ : result.status === "partial" ? chalk.yellow
73
+ : chalk.red;
74
+ console.log(`\n Status: ${statusColor(result.status)} | ${result.totalDurationMs}ms\n`);
75
+ });
76
+ });
77
+ // ── plan example ──
78
+ plan
79
+ .command("example")
80
+ .description("Print an example execution plan")
81
+ .action(() => {
82
+ const example = {
83
+ version: "1.0",
84
+ description: "Open hedged position with stop loss",
85
+ steps: [
86
+ { id: "check", action: "check_balance", params: { minAvailable: 100 }, onFailure: "abort" },
87
+ { id: "leverage", action: "set_leverage", params: { symbol: "ETH", leverage: 5 }, onFailure: "abort" },
88
+ { id: "entry", action: "market_order", params: { symbol: "ETH", side: "buy", size: "0.5" }, onFailure: "rollback" },
89
+ { id: "verify", action: "check_position", params: { symbol: "ETH", mustExist: true }, dependsOn: "entry", onFailure: "rollback" },
90
+ { id: "stop", action: "stop_order", params: { symbol: "ETH", side: "sell", size: "0.5", triggerPrice: "1800", reduceOnly: true }, dependsOn: "verify", onFailure: "skip" },
91
+ ],
92
+ };
93
+ printJson(jsonOk(example));
94
+ });
95
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { ExchangeAdapter } from "../exchanges/interface.js";
3
+ export declare function registerPortfolioCommands(program: Command, getAdapterForExchange: (exchange: string) => Promise<ExchangeAdapter>, isJson: () => boolean): void;