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,425 @@
1
+ import { PacificaAdapter } from "../exchanges/pacifica.js";
2
+ import { HyperliquidAdapter } from "../exchanges/hyperliquid.js";
3
+ import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch } from "../utils.js";
4
+ import chalk from "chalk";
5
+ function pac(adapter) {
6
+ if (!(adapter instanceof PacificaAdapter))
7
+ throw new Error("This command requires --exchange pacifica");
8
+ return adapter;
9
+ }
10
+ export function registerAccountCommands(program, getAdapter, isJson) {
11
+ const account = program.command("account").description("Account commands");
12
+ account
13
+ .command("info")
14
+ .description("Show account balance and info")
15
+ .action(async () => {
16
+ const adapter = await getAdapter();
17
+ const bal = await adapter.getBalance();
18
+ if (isJson())
19
+ return printJson(jsonOk(bal));
20
+ console.log(chalk.cyan.bold(`\n ${adapter.name.toUpperCase()} Account Info\n`));
21
+ console.log(` Equity: $${formatUsd(bal.equity)}`);
22
+ console.log(` Available: $${formatUsd(bal.available)}`);
23
+ console.log(` Margin Used: $${formatUsd(bal.marginUsed)}`);
24
+ console.log(` Unreal. PnL: ${formatPnl(bal.unrealizedPnl)}`);
25
+ console.log();
26
+ });
27
+ account
28
+ .command("balance")
29
+ .description("Alias for 'account info' — show account balance")
30
+ .action(async () => {
31
+ const adapter = await getAdapter();
32
+ const bal = await adapter.getBalance();
33
+ if (isJson())
34
+ return printJson(jsonOk(bal));
35
+ console.log(chalk.cyan.bold(`\n ${adapter.name.toUpperCase()} Account Balance\n`));
36
+ console.log(` Equity: $${formatUsd(bal.equity)}`);
37
+ console.log(` Available: $${formatUsd(bal.available)}`);
38
+ console.log(` Margin Used: $${formatUsd(bal.marginUsed)}`);
39
+ console.log(` Unreal. PnL: ${formatPnl(bal.unrealizedPnl)}`);
40
+ console.log();
41
+ });
42
+ account
43
+ .command("positions")
44
+ .description("Show open positions")
45
+ .action(async () => {
46
+ const adapter = await getAdapter();
47
+ const positions = await adapter.getPositions();
48
+ if (isJson())
49
+ return printJson(jsonOk(positions));
50
+ if (positions.length === 0) {
51
+ console.log(chalk.gray("\n No open positions.\n"));
52
+ return;
53
+ }
54
+ const rows = positions.map((p) => [
55
+ chalk.white.bold(p.symbol),
56
+ p.side === "long" ? chalk.green("LONG") : chalk.red("SHORT"),
57
+ p.size,
58
+ `$${formatUsd(p.entryPrice)}`,
59
+ `$${formatUsd(p.markPrice)}`,
60
+ p.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(p.liquidationPrice)}`,
61
+ formatPnl(p.unrealizedPnl),
62
+ `${p.leverage}x`,
63
+ ]);
64
+ console.log(makeTable(["Symbol", "Side", "Size", "Entry", "Mark", "Liq", "PnL", "Lev"], rows));
65
+ });
66
+ account
67
+ .command("orders")
68
+ .description("Show open orders")
69
+ .action(async () => {
70
+ const adapter = await getAdapter();
71
+ const orders = await adapter.getOpenOrders();
72
+ if (isJson())
73
+ return printJson(jsonOk(orders));
74
+ if (orders.length === 0) {
75
+ console.log(chalk.gray("\n No open orders.\n"));
76
+ return;
77
+ }
78
+ const rows = orders.map((o) => [
79
+ o.orderId,
80
+ chalk.white.bold(o.symbol),
81
+ o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
82
+ o.type,
83
+ `$${formatUsd(o.price)}`,
84
+ o.size,
85
+ o.filled,
86
+ o.status,
87
+ ]);
88
+ console.log(makeTable(["ID", "Symbol", "Side", "Type", "Price", "Size", "Filled", "Status"], rows));
89
+ });
90
+ account
91
+ .command("history")
92
+ .description("Order history")
93
+ .action(async () => {
94
+ const adapter = await getAdapter();
95
+ const orders = await adapter.getOrderHistory(30);
96
+ if (isJson())
97
+ return printJson(jsonOk(orders));
98
+ if (orders.length === 0) {
99
+ console.log(chalk.gray("\n No order history.\n"));
100
+ return;
101
+ }
102
+ const rows = orders.map((o) => [
103
+ o.orderId,
104
+ chalk.white.bold(o.symbol),
105
+ o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
106
+ o.type,
107
+ `$${formatUsd(o.price)}`,
108
+ o.size,
109
+ o.filled,
110
+ o.status,
111
+ ]);
112
+ console.log(makeTable(["ID", "Symbol", "Side", "Type", "Price", "Size", "Filled", "Status"], rows));
113
+ });
114
+ account
115
+ .command("settings")
116
+ .description("Show per-market account settings (leverage, margin mode)")
117
+ .action(async () => {
118
+ const adapter = await getAdapter();
119
+ const p = pac(adapter);
120
+ const settings = await p.sdk.getAccountSettings(p.publicKey);
121
+ if (isJson())
122
+ return printJson(jsonOk(settings));
123
+ if (settings.length === 0) {
124
+ console.log(chalk.gray("\n No market settings configured.\n"));
125
+ return;
126
+ }
127
+ const rows = settings.map((s) => [
128
+ chalk.white.bold(s.symbol),
129
+ s.margin_mode,
130
+ `${s.leverage}x`,
131
+ ]);
132
+ console.log(makeTable(["Symbol", "Margin Mode", "Leverage"], rows));
133
+ });
134
+ account
135
+ .command("trades")
136
+ .description("Trade history (fills)")
137
+ .action(async () => {
138
+ const adapter = await getAdapter();
139
+ const trades = await adapter.getTradeHistory(30);
140
+ if (isJson())
141
+ return printJson(jsonOk(trades));
142
+ if (trades.length === 0) {
143
+ console.log(chalk.gray("\n No trade history.\n"));
144
+ return;
145
+ }
146
+ const rows = trades.map((t) => [
147
+ new Date(t.time).toLocaleString(),
148
+ chalk.white.bold(t.symbol),
149
+ t.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
150
+ `$${formatUsd(t.price)}`,
151
+ t.size,
152
+ `$${formatUsd(t.fee)}`,
153
+ ]);
154
+ console.log(makeTable(["Time", "Symbol", "Side", "Price", "Size", "Fee"], rows));
155
+ });
156
+ account
157
+ .command("funding-history")
158
+ .description("Personal funding payment history")
159
+ .action(async () => {
160
+ const adapter = await getAdapter();
161
+ const payments = await adapter.getFundingPayments(30);
162
+ if (isJson())
163
+ return printJson(jsonOk(payments));
164
+ if (payments.length === 0) {
165
+ console.log(chalk.gray("\n No funding history.\n"));
166
+ return;
167
+ }
168
+ const rows = payments.map((h) => [
169
+ new Date(h.time).toLocaleString(),
170
+ chalk.white.bold(h.symbol),
171
+ formatPnl(h.payment),
172
+ ]);
173
+ console.log(makeTable(["Time", "Symbol", "Payment"], rows));
174
+ });
175
+ account
176
+ .command("portfolio")
177
+ .description("Portfolio overview")
178
+ .action(async () => {
179
+ const adapter = await getAdapter();
180
+ if (adapter instanceof PacificaAdapter) {
181
+ const portfolio = await adapter.sdk.getPortfolio(adapter.publicKey);
182
+ printJson(jsonOk(portfolio));
183
+ }
184
+ else if (adapter instanceof HyperliquidAdapter) {
185
+ const state = await adapter.client.info.perpetuals.getClearinghouseState(adapter.address);
186
+ printJson(jsonOk(state));
187
+ }
188
+ });
189
+ account
190
+ .command("balance-history")
191
+ .description("Balance change history")
192
+ .action(async () => {
193
+ const adapter = await getAdapter();
194
+ const p = pac(adapter);
195
+ const raw = await p.sdk.getBalanceHistory(p.publicKey);
196
+ if (isJson())
197
+ return printJson(jsonOk(raw));
198
+ const history = (raw.data ?? raw);
199
+ if (!Array.isArray(history) || history.length === 0) {
200
+ console.log(chalk.gray("\n No balance history.\n"));
201
+ return;
202
+ }
203
+ const rows = history.slice(0, 30).map((h) => [
204
+ new Date(Number(h.created_at ?? h.timestamp ?? 0)).toLocaleString(),
205
+ String(h.type ?? h.event_type ?? ""),
206
+ formatPnl(String(h.amount ?? h.change ?? "0")),
207
+ `$${formatUsd(String(h.balance ?? "0"))}`,
208
+ ]);
209
+ console.log(makeTable(["Time", "Type", "Change", "Balance"], rows));
210
+ });
211
+ account
212
+ .command("margin <symbol>")
213
+ .description("Margin details for a specific symbol position")
214
+ .action(async (symbol) => {
215
+ const sym = symbol.toUpperCase();
216
+ try {
217
+ const adapter = await getAdapter();
218
+ const [balance, positions] = await Promise.all([
219
+ adapter.getBalance(),
220
+ adapter.getPositions(),
221
+ ]);
222
+ const pos = positions.find(p => symbolMatch(p.symbol, sym));
223
+ if (!pos) {
224
+ if (isJson())
225
+ return printJson(jsonError("POSITION_NOT_FOUND", `No open position for ${sym}`));
226
+ console.log(chalk.gray(`\n No open position for ${sym}.\n`));
227
+ return;
228
+ }
229
+ const positionNotional = Math.abs(Number(pos.size) * Number(pos.markPrice));
230
+ const marginRequired = pos.leverage > 0 ? positionNotional / pos.leverage : 0;
231
+ const marginPct = Number(balance.equity) > 0
232
+ ? (marginRequired / Number(balance.equity) * 100)
233
+ : 0;
234
+ const data = {
235
+ symbol: pos.symbol,
236
+ side: pos.side,
237
+ size: pos.size,
238
+ entryPrice: pos.entryPrice,
239
+ markPrice: pos.markPrice,
240
+ leverage: pos.leverage,
241
+ notional: positionNotional.toFixed(2),
242
+ marginRequired: marginRequired.toFixed(2),
243
+ marginPctOfEquity: marginPct.toFixed(2),
244
+ liquidationPrice: pos.liquidationPrice,
245
+ unrealizedPnl: pos.unrealizedPnl,
246
+ accountEquity: balance.equity,
247
+ accountAvailable: balance.available,
248
+ };
249
+ if (isJson())
250
+ return printJson(jsonOk(data));
251
+ console.log(chalk.cyan.bold(`\n ${pos.symbol} Margin Details\n`));
252
+ console.log(` Side: ${pos.side === "long" ? chalk.green("LONG") : chalk.red("SHORT")}`);
253
+ console.log(` Size: ${pos.size}`);
254
+ console.log(` Entry: $${formatUsd(pos.entryPrice)}`);
255
+ console.log(` Mark: $${formatUsd(pos.markPrice)}`);
256
+ console.log(` Leverage: ${pos.leverage}x`);
257
+ console.log(` Notional: $${formatUsd(positionNotional)}`);
258
+ console.log(` Margin Required: $${formatUsd(marginRequired)}`);
259
+ console.log(` Margin % Equity: ${marginPct.toFixed(2)}%`);
260
+ console.log(` Liquidation: ${pos.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(pos.liquidationPrice)}`}`);
261
+ console.log(` Unrealized PnL: ${formatPnl(pos.unrealizedPnl)}`);
262
+ console.log();
263
+ }
264
+ catch (err) {
265
+ const msg = err instanceof Error ? err.message : String(err);
266
+ if (isJson()) {
267
+ const { classifyError } = await import("../errors.js");
268
+ const classified = classifyError(err);
269
+ return printJson(jsonError(classified.code, classified.message, {
270
+ status: classified.status,
271
+ retryable: classified.retryable,
272
+ }));
273
+ }
274
+ console.error(chalk.red(`Error: ${msg}`));
275
+ }
276
+ });
277
+ // ── PnL Report ──
278
+ account
279
+ .command("pnl")
280
+ .description("PnL summary: realized (from trades), unrealized (from positions), and funding")
281
+ .option("--period <period>", "Period filter: today, 7d, 30d, all", "all")
282
+ .action(async (opts) => {
283
+ const adapter = await getAdapter();
284
+ // Gather data in parallel
285
+ const [trades, positions, fundingPayments, balance] = await Promise.all([
286
+ adapter.getTradeHistory(200),
287
+ adapter.getPositions(),
288
+ adapter.getFundingPayments(200),
289
+ adapter.getBalance(),
290
+ ]);
291
+ // Period filter
292
+ const now = Date.now();
293
+ const periodMs = {
294
+ today: 24 * 60 * 60 * 1000,
295
+ "7d": 7 * 24 * 60 * 60 * 1000,
296
+ "30d": 30 * 24 * 60 * 60 * 1000,
297
+ all: Infinity,
298
+ };
299
+ const cutoff = now - (periodMs[opts.period] ?? Infinity);
300
+ const filteredTrades = trades.filter(t => t.time >= cutoff);
301
+ const filteredFunding = fundingPayments.filter(f => f.time >= cutoff);
302
+ // Realized PnL: group trades by symbol, compute net P&L
303
+ const symbolPnl = new Map();
304
+ for (const t of filteredTrades) {
305
+ if (!symbolPnl.has(t.symbol)) {
306
+ symbolPnl.set(t.symbol, { buyCost: 0, buyQty: 0, sellRevenue: 0, sellQty: 0, fees: 0 });
307
+ }
308
+ const entry = symbolPnl.get(t.symbol);
309
+ const price = parseFloat(t.price);
310
+ const size = parseFloat(t.size);
311
+ const fee = Math.abs(parseFloat(t.fee));
312
+ entry.fees += fee;
313
+ if (t.side === "buy") {
314
+ entry.buyCost += price * size;
315
+ entry.buyQty += size;
316
+ }
317
+ else {
318
+ entry.sellRevenue += price * size;
319
+ entry.sellQty += size;
320
+ }
321
+ }
322
+ // Calculate realized PnL per symbol (closed quantity only)
323
+ let totalRealizedPnl = 0;
324
+ let totalFees = 0;
325
+ const symbolRows = [];
326
+ for (const [symbol, data] of symbolPnl) {
327
+ const closedQty = Math.min(data.buyQty, data.sellQty);
328
+ let realizedPnl = 0;
329
+ if (closedQty > 0) {
330
+ const avgBuy = data.buyCost / data.buyQty;
331
+ const avgSell = data.sellRevenue / data.sellQty;
332
+ realizedPnl = (avgSell - avgBuy) * closedQty;
333
+ }
334
+ totalRealizedPnl += realizedPnl;
335
+ totalFees += data.fees;
336
+ symbolRows.push([
337
+ chalk.white.bold(symbol),
338
+ String(filteredTrades.filter(t => t.symbol === symbol).length),
339
+ formatPnl(String(realizedPnl.toFixed(2))),
340
+ `$${formatUsd(String(data.fees.toFixed(2)))}`,
341
+ ]);
342
+ }
343
+ // Unrealized PnL from positions
344
+ let totalUnrealizedPnl = 0;
345
+ const posRows = [];
346
+ for (const p of positions) {
347
+ const upnl = parseFloat(p.unrealizedPnl);
348
+ totalUnrealizedPnl += upnl;
349
+ posRows.push([
350
+ chalk.white.bold(p.symbol),
351
+ p.side === "long" ? chalk.green("LONG") : chalk.red("SHORT"),
352
+ p.size,
353
+ `$${formatUsd(p.entryPrice)}`,
354
+ formatPnl(p.unrealizedPnl),
355
+ ]);
356
+ }
357
+ // Funding income
358
+ let totalFunding = 0;
359
+ for (const f of filteredFunding) {
360
+ totalFunding += parseFloat(f.payment);
361
+ }
362
+ const netPnl = totalRealizedPnl + totalUnrealizedPnl + totalFunding - totalFees;
363
+ if (isJson()) {
364
+ return printJson(jsonOk({
365
+ period: opts.period,
366
+ realizedPnl: totalRealizedPnl,
367
+ unrealizedPnl: totalUnrealizedPnl,
368
+ funding: totalFunding,
369
+ fees: totalFees,
370
+ netPnl,
371
+ equity: parseFloat(balance.equity),
372
+ trades: filteredTrades.length,
373
+ positions: positions.length,
374
+ fundingPayments: filteredFunding.length,
375
+ }));
376
+ }
377
+ const periodLabel = opts.period === "all" ? "All Time" : opts.period === "today" ? "Today" : `Last ${opts.period}`;
378
+ console.log(chalk.cyan.bold(`\n ${adapter.name.toUpperCase()} PnL Report — ${periodLabel}\n`));
379
+ // Trade PnL by symbol
380
+ if (symbolRows.length > 0) {
381
+ console.log(chalk.white.bold(" Realized PnL by Symbol"));
382
+ console.log(makeTable(["Symbol", "Trades", "Realized PnL", "Fees"], symbolRows));
383
+ }
384
+ // Open positions
385
+ if (posRows.length > 0) {
386
+ console.log(chalk.white.bold(" Open Positions"));
387
+ console.log(makeTable(["Symbol", "Side", "Size", "Entry", "uPnL"], posRows));
388
+ }
389
+ // Summary
390
+ console.log(chalk.cyan.bold(" Summary"));
391
+ console.log(` Realized PnL: ${formatPnl(String(totalRealizedPnl.toFixed(2)))}`);
392
+ console.log(` Unrealized PnL: ${formatPnl(String(totalUnrealizedPnl.toFixed(2)))}`);
393
+ console.log(` Funding Income: ${formatPnl(String(totalFunding.toFixed(2)))}`);
394
+ console.log(` Total Fees: ${chalk.red(`-$${formatUsd(String(totalFees.toFixed(2)))}`)}`);
395
+ console.log(` ─────────────────────`);
396
+ const netColor = netPnl >= 0 ? chalk.green : chalk.red;
397
+ console.log(` Net PnL: ${netColor(`${netPnl >= 0 ? "+" : ""}$${Math.abs(netPnl).toFixed(2)}`)}`);
398
+ console.log(` Equity: $${formatUsd(balance.equity)}`);
399
+ console.log(` Trades: ${filteredTrades.length} | Positions: ${positions.length} | Funding: ${filteredFunding.length}`);
400
+ console.log();
401
+ });
402
+ account
403
+ .command("twap-orders")
404
+ .description("Active TWAP orders")
405
+ .action(async () => {
406
+ const adapter = await getAdapter();
407
+ const p = pac(adapter);
408
+ const orders = await p.sdk.getTWAPOrders(p.publicKey);
409
+ if (isJson())
410
+ return printJson(jsonOk(orders));
411
+ if (!orders || orders.length === 0) {
412
+ console.log(chalk.gray("\n No active TWAP orders.\n"));
413
+ return;
414
+ }
415
+ const rows = orders.map((o) => [
416
+ String(o.twap_order_id ?? o.id ?? ""),
417
+ chalk.white.bold(String(o.symbol ?? "")),
418
+ String(o.side) === "bid" ? chalk.green("BUY") : chalk.red("SELL"),
419
+ String(o.amount ?? ""),
420
+ String(o.filled_amount ?? "0"),
421
+ `${o.duration_in_seconds ?? ""}s`,
422
+ ]);
423
+ console.log(makeTable(["ID", "Symbol", "Side", "Size", "Filled", "Duration"], rows));
424
+ });
425
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { ExchangeAdapter } from "../exchanges/interface.js";
3
+ export declare function registerAgentCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean): void;