perp-cli 0.14.3 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/README.ja.md +243 -0
  2. package/README.ko.md +243 -0
  3. package/README.md +138 -405
  4. package/README.zh.md +243 -0
  5. package/dist/agent-wallet/store.d.ts +3 -2
  6. package/dist/agent-wallet/store.js +2 -2
  7. package/dist/api/public/hyperliquid.js +4 -0
  8. package/dist/api/public/lighter.d.ts +5 -0
  9. package/dist/api/public/lighter.js +5 -0
  10. package/dist/api/public/pacifica.js +85 -15
  11. package/dist/api/public/urls.d.ts +2 -0
  12. package/dist/api/public/urls.js +3 -0
  13. package/dist/arb/sizing.js +4 -2
  14. package/dist/arb/state.d.ts +6 -0
  15. package/dist/arb/utils.d.ts +1 -2
  16. package/dist/arb/utils.js +1 -2
  17. package/dist/balance-by-address.d.ts +39 -0
  18. package/dist/balance-by-address.js +44 -0
  19. package/dist/bot/apex/pulse.js +3 -0
  20. package/dist/bot/apex/radar.js +2 -1
  21. package/dist/bot/engine.d.ts +10 -1
  22. package/dist/bot/engine.js +14 -6
  23. package/dist/bot/indicators.d.ts +7 -0
  24. package/dist/bot/indicators.js +16 -0
  25. package/dist/bot/perp-order.d.ts +4 -4
  26. package/dist/bot/perp-order.js +5 -5
  27. package/dist/bot/quarantine.d.ts +1 -1
  28. package/dist/bot/quarantine.js +1 -1
  29. package/dist/bot/quote-rules.js +1 -1
  30. package/dist/bot/strategies/apex-strategy.js +3 -2
  31. package/dist/bot/strategies/engine-mm.js +6 -5
  32. package/dist/bot/strategies/funding-arb-strategy.js +12 -5
  33. package/dist/bot/strategies/funding-arb-utils.d.ts +15 -3
  34. package/dist/bot/strategies/funding-arb-utils.js +53 -20
  35. package/dist/bot/strategies/funding-auto.js +2 -2
  36. package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
  37. package/dist/bot/strategies/liquidation-mm.js +8 -2
  38. package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
  39. package/dist/bot/strategies/momentum-breakout.js +11 -3
  40. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +1 -1
  41. package/dist/bot/strategies/spot-perp-arb-strategy.js +6 -4
  42. package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
  43. package/dist/bot/strategies/spot-perp-executor.js +3 -3
  44. package/dist/bot/strategy-types.d.ts +2 -1
  45. package/dist/bot/tui/BotDashboard.d.ts +1 -1
  46. package/dist/bot/tui/BotDashboard.js +1 -1
  47. package/dist/cache.js +12 -6
  48. package/dist/cli-program.d.ts +15 -0
  49. package/dist/cli-program.js +126 -6
  50. package/dist/commands/account.js +168 -24
  51. package/dist/commands/agent-import.d.ts +7 -0
  52. package/dist/commands/agent-import.js +30 -1
  53. package/dist/commands/agent.d.ts +6 -3
  54. package/dist/commands/agent.js +160 -12
  55. package/dist/commands/arb/index.js +23 -81
  56. package/dist/commands/arb-auto.d.ts +24 -0
  57. package/dist/commands/arb-auto.js +175 -97
  58. package/dist/commands/arb.d.ts +20 -0
  59. package/dist/commands/arb.js +107 -163
  60. package/dist/commands/backtest.js +23 -21
  61. package/dist/commands/bot.js +1 -1
  62. package/dist/commands/builder.js +1 -1
  63. package/dist/commands/funds.js +113 -3
  64. package/dist/commands/init.d.ts +1 -1
  65. package/dist/commands/init.js +27 -7
  66. package/dist/commands/manage.js +23 -21
  67. package/dist/commands/market.d.ts +48 -0
  68. package/dist/commands/market.js +395 -100
  69. package/dist/commands/options.d.ts +14 -0
  70. package/dist/commands/options.js +151 -0
  71. package/dist/commands/pacifica-earn.d.ts +5 -0
  72. package/dist/commands/pacifica-earn.js +455 -0
  73. package/dist/commands/pacifica-orders.d.ts +14 -0
  74. package/dist/commands/pacifica-orders.js +142 -0
  75. package/dist/commands/portfolio.d.ts +16 -0
  76. package/dist/commands/portfolio.js +83 -55
  77. package/dist/commands/rebalance.d.ts +1 -0
  78. package/dist/commands/rebalance.js +15 -0
  79. package/dist/commands/risk.d.ts +11 -2
  80. package/dist/commands/risk.js +39 -44
  81. package/dist/commands/trade.d.ts +1 -0
  82. package/dist/commands/trade.js +67 -62
  83. package/dist/commands/wallet.js +1 -1
  84. package/dist/config.d.ts +2 -2
  85. package/dist/config.js +15 -4
  86. package/dist/constants.js +6 -0
  87. package/dist/cross-chain-margin.d.ts +3 -1
  88. package/dist/cross-chain-margin.js +4 -2
  89. package/dist/dashboard/server.js +3 -3
  90. package/dist/dashboard/ui.js +9 -6
  91. package/dist/errors.d.ts +29 -1
  92. package/dist/errors.js +35 -3
  93. package/dist/exchanges/address.d.ts +8 -0
  94. package/dist/exchanges/address.js +47 -0
  95. package/dist/exchanges/arcus/adapter.d.ts +16 -12
  96. package/dist/exchanges/arcus/adapter.js +45 -18
  97. package/dist/exchanges/arcus/agent.d.ts +1 -1
  98. package/dist/exchanges/arcus/agent.js +1 -1
  99. package/dist/exchanges/arcus/client.js +1 -1
  100. package/dist/exchanges/arcus/public.js +3 -2
  101. package/dist/exchanges/arcus/signing.d.ts +2 -3
  102. package/dist/exchanges/arcus/signing.js +1 -1
  103. package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
  104. package/dist/exchanges/arcus/spot-chain.js +1 -1
  105. package/dist/exchanges/arcus/spot-router.d.ts +1 -1
  106. package/dist/exchanges/arcus/spot-router.js +2 -2
  107. package/dist/exchanges/arcus/spot.d.ts +2 -3
  108. package/dist/exchanges/arcus/spot.js +2 -3
  109. package/dist/exchanges/aster-spot.d.ts +3 -3
  110. package/dist/exchanges/aster-spot.js +6 -9
  111. package/dist/exchanges/aster-typed-data.d.ts +1 -1
  112. package/dist/exchanges/aster-typed-data.js +1 -1
  113. package/dist/exchanges/aster.d.ts +30 -10
  114. package/dist/exchanges/aster.js +153 -53
  115. package/dist/exchanges/builder-fee.d.ts +1 -1
  116. package/dist/exchanges/builder-fee.js +13 -2
  117. package/dist/exchanges/canonical-symbols.d.ts +8 -2
  118. package/dist/exchanges/canonical-symbols.js +46 -2
  119. package/dist/exchanges/capabilities.d.ts +2 -0
  120. package/dist/exchanges/capabilities.js +2 -1
  121. package/dist/exchanges/derive/client.d.ts +37 -0
  122. package/dist/exchanges/derive/client.js +135 -0
  123. package/dist/exchanges/derive/options.d.ts +73 -0
  124. package/dist/exchanges/derive/options.js +379 -0
  125. package/dist/exchanges/extended/adapter.d.ts +96 -0
  126. package/dist/exchanges/extended/adapter.js +241 -0
  127. package/dist/exchanges/extended/client.d.ts +38 -0
  128. package/dist/exchanges/extended/client.js +88 -0
  129. package/dist/exchanges/extended/public.d.ts +133 -0
  130. package/dist/exchanges/extended/public.js +436 -0
  131. package/dist/exchanges/grvt/adapter.d.ts +100 -0
  132. package/dist/exchanges/grvt/adapter.js +283 -0
  133. package/dist/exchanges/grvt/client.d.ts +25 -0
  134. package/dist/exchanges/grvt/client.js +86 -0
  135. package/dist/exchanges/grvt/public.d.ts +151 -0
  136. package/dist/exchanges/grvt/public.js +438 -0
  137. package/dist/exchanges/hyperliquid-outcome.d.ts +2 -0
  138. package/dist/exchanges/hyperliquid-outcome.js +29 -1
  139. package/dist/exchanges/hyperliquid-spot.d.ts +9 -1
  140. package/dist/exchanges/hyperliquid-spot.js +24 -16
  141. package/dist/exchanges/hyperliquid.d.ts +199 -22
  142. package/dist/exchanges/hyperliquid.js +550 -202
  143. package/dist/exchanges/index.d.ts +1 -1
  144. package/dist/exchanges/index.js +1 -1
  145. package/dist/exchanges/interface.d.ts +157 -13
  146. package/dist/exchanges/interface.js +47 -0
  147. package/dist/exchanges/ioc-outcome.d.ts +1 -1
  148. package/dist/exchanges/ioc-outcome.js +1 -1
  149. package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
  150. package/dist/exchanges/legacy-trading-v2.js +7 -2
  151. package/dist/exchanges/lighter-public.d.ts +67 -12
  152. package/dist/exchanges/lighter-public.js +250 -82
  153. package/dist/exchanges/lighter-signer.d.ts +1 -1
  154. package/dist/exchanges/lighter-signer.js +1 -1
  155. package/dist/exchanges/lighter-spot.d.ts +10 -5
  156. package/dist/exchanges/lighter-spot.js +105 -97
  157. package/dist/exchanges/lighter.d.ts +80 -21
  158. package/dist/exchanges/lighter.js +312 -105
  159. package/dist/exchanges/ondo/adapter.d.ts +38 -13
  160. package/dist/exchanges/ondo/adapter.js +86 -27
  161. package/dist/exchanges/ondo/agent.d.ts +1 -1
  162. package/dist/exchanges/ondo/agent.js +1 -1
  163. package/dist/exchanges/ondo/client.d.ts +1 -1
  164. package/dist/exchanges/ondo/client.js +2 -2
  165. package/dist/exchanges/ondo/public.d.ts +35 -3
  166. package/dist/exchanges/ondo/public.js +75 -32
  167. package/dist/exchanges/ondo/spot.d.ts +2 -2
  168. package/dist/exchanges/ondo/spot.js +3 -3
  169. package/dist/exchanges/options-interface.d.ts +158 -0
  170. package/dist/exchanges/options-interface.js +17 -0
  171. package/dist/exchanges/options-venues.d.ts +12 -0
  172. package/dist/exchanges/options-venues.js +35 -0
  173. package/dist/exchanges/outcome-interface.d.ts +4 -0
  174. package/dist/exchanges/pacifica-atomic.d.ts +211 -0
  175. package/dist/exchanges/pacifica-atomic.js +440 -0
  176. package/dist/exchanges/pacifica-decimal.d.ts +10 -0
  177. package/dist/exchanges/pacifica-decimal.js +51 -0
  178. package/dist/exchanges/pacifica-presigned.d.ts +53 -0
  179. package/dist/exchanges/pacifica-presigned.js +141 -0
  180. package/dist/exchanges/pacifica-print.d.ts +200 -0
  181. package/dist/exchanges/pacifica-print.js +417 -0
  182. package/dist/exchanges/pacifica-spot.d.ts +8 -2
  183. package/dist/exchanges/pacifica-spot.js +26 -18
  184. package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
  185. package/dist/exchanges/pacifica-typed-data.js +1 -1
  186. package/dist/exchanges/pacifica-vaults.d.ts +130 -0
  187. package/dist/exchanges/pacifica-vaults.js +277 -0
  188. package/dist/exchanges/pacifica.d.ts +108 -10
  189. package/dist/exchanges/pacifica.js +428 -171
  190. package/dist/exchanges/precision.d.ts +3 -1
  191. package/dist/exchanges/precision.js +9 -2
  192. package/dist/exchanges/public-balances.d.ts +25 -0
  193. package/dist/exchanges/public-balances.js +158 -0
  194. package/dist/exchanges/public-positions.d.ts +43 -0
  195. package/dist/exchanges/public-positions.js +154 -0
  196. package/dist/exchanges/qfex/adapter.d.ts +69 -13
  197. package/dist/exchanges/qfex/adapter.js +102 -17
  198. package/dist/exchanges/qfex/agent.d.ts +1 -1
  199. package/dist/exchanges/qfex/agent.js +1 -1
  200. package/dist/exchanges/qfex/client.d.ts +1 -1
  201. package/dist/exchanges/qfex/client.js +1 -1
  202. package/dist/exchanges/qfex/errors.d.ts +1 -1
  203. package/dist/exchanges/qfex/errors.js +2 -2
  204. package/dist/exchanges/qfex/public.d.ts +65 -12
  205. package/dist/exchanges/qfex/public.js +131 -25
  206. package/dist/exchanges/qfex/signing.d.ts +2 -2
  207. package/dist/exchanges/qfex/signing.js +4 -5
  208. package/dist/exchanges/qfex/ws-transport.d.ts +3 -3
  209. package/dist/exchanges/qfex/ws-transport.js +3 -3
  210. package/dist/exchanges/rate-limiter.d.ts +1 -1
  211. package/dist/exchanges/rate-limiter.js +5 -2
  212. package/dist/exchanges/registry.d.ts +1 -1
  213. package/dist/exchanges/registry.js +1 -1
  214. package/dist/exchanges/risex/adapter.d.ts +160 -0
  215. package/dist/exchanges/risex/adapter.js +842 -0
  216. package/dist/exchanges/risex/agent.d.ts +154 -0
  217. package/dist/exchanges/risex/agent.js +384 -0
  218. package/dist/exchanges/risex/client.d.ts +47 -0
  219. package/dist/exchanges/risex/client.js +174 -0
  220. package/dist/exchanges/risex/nonce.d.ts +43 -0
  221. package/dist/exchanges/risex/nonce.js +212 -0
  222. package/dist/exchanges/risex/public.d.ts +64 -0
  223. package/dist/exchanges/risex/public.js +150 -0
  224. package/dist/exchanges/risex/session.d.ts +71 -0
  225. package/dist/exchanges/risex/session.js +171 -0
  226. package/dist/exchanges/risex/typed-data.d.ts +173 -0
  227. package/dist/exchanges/risex/typed-data.js +240 -0
  228. package/dist/exchanges/risex/units.d.ts +29 -0
  229. package/dist/exchanges/risex/units.js +104 -0
  230. package/dist/exchanges/slippage.d.ts +1 -1
  231. package/dist/exchanges/slippage.js +1 -1
  232. package/dist/exchanges/spot-factory.d.ts +3 -3
  233. package/dist/exchanges/spot-factory.js +8 -8
  234. package/dist/exchanges/spot-interface.d.ts +5 -5
  235. package/dist/exchanges/spot-interface.js +2 -2
  236. package/dist/exchanges/spot-result.d.ts +3 -3
  237. package/dist/exchanges/spot-result.js +3 -3
  238. package/dist/exchanges/trading-v2.d.ts +3 -3
  239. package/dist/exchanges/trading-v2.js +9 -6
  240. package/dist/exchanges/txflow/adapter.d.ts +61 -0
  241. package/dist/exchanges/txflow/adapter.js +150 -0
  242. package/dist/exchanges/txflow/client.d.ts +47 -0
  243. package/dist/exchanges/txflow/client.js +155 -0
  244. package/dist/exchanges/txflow/public.d.ts +87 -0
  245. package/dist/exchanges/txflow/public.js +355 -0
  246. package/dist/exchanges/unknown-symbol.d.ts +34 -0
  247. package/dist/exchanges/unknown-symbol.js +56 -0
  248. package/dist/exchanges/variational/adapter.d.ts +67 -0
  249. package/dist/exchanges/variational/adapter.js +137 -0
  250. package/dist/exchanges/variational/client.d.ts +21 -0
  251. package/dist/exchanges/variational/client.js +66 -0
  252. package/dist/exchanges/variational/public.d.ts +126 -0
  253. package/dist/exchanges/variational/public.js +430 -0
  254. package/dist/exchanges/venue-types.d.ts +52 -10
  255. package/dist/exchanges/venue-types.js +82 -11
  256. package/dist/exchanges/venue.d.ts +150 -11
  257. package/dist/exchanges/venue.js +126 -4
  258. package/dist/exchanges/venues/arcus.d.ts +1 -2
  259. package/dist/exchanges/venues/arcus.js +5 -4
  260. package/dist/exchanges/venues/aster.d.ts +2 -2
  261. package/dist/exchanges/venues/aster.js +6 -4
  262. package/dist/exchanges/venues/create-helpers.d.ts +1 -1
  263. package/dist/exchanges/venues/create-helpers.js +3 -3
  264. package/dist/exchanges/venues/extended.d.ts +21 -0
  265. package/dist/exchanges/venues/extended.js +96 -0
  266. package/dist/exchanges/venues/grvt.d.ts +30 -0
  267. package/dist/exchanges/venues/grvt.js +98 -0
  268. package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
  269. package/dist/exchanges/venues/hyperliquid.js +19 -8
  270. package/dist/exchanges/venues/index.d.ts +7 -2
  271. package/dist/exchanges/venues/index.js +8 -2
  272. package/dist/exchanges/venues/lighter-family.d.ts +7 -9
  273. package/dist/exchanges/venues/lighter-family.js +9 -11
  274. package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
  275. package/dist/exchanges/venues/lighter-rh.js +20 -8
  276. package/dist/exchanges/venues/lighter.d.ts +1 -1
  277. package/dist/exchanges/venues/lighter.js +18 -6
  278. package/dist/exchanges/venues/ondo.d.ts +1 -1
  279. package/dist/exchanges/venues/ondo.js +5 -3
  280. package/dist/exchanges/venues/pacifica.d.ts +2 -2
  281. package/dist/exchanges/venues/pacifica.js +15 -4
  282. package/dist/exchanges/venues/qfex.d.ts +1 -1
  283. package/dist/exchanges/venues/qfex.js +4 -2
  284. package/dist/exchanges/venues/risex-release.d.ts +14 -0
  285. package/dist/exchanges/venues/risex-release.js +14 -0
  286. package/dist/exchanges/venues/risex.d.ts +31 -0
  287. package/dist/exchanges/venues/risex.js +131 -0
  288. package/dist/exchanges/venues/txflow.d.ts +18 -0
  289. package/dist/exchanges/venues/txflow.js +77 -0
  290. package/dist/exchanges/venues/variational.d.ts +21 -0
  291. package/dist/exchanges/venues/variational.js +85 -0
  292. package/dist/execution-log.d.ts +1 -1
  293. package/dist/funding/legacy-public.d.ts +6 -4
  294. package/dist/funding/legacy-public.js +42 -41
  295. package/dist/funding/normalize.d.ts +1 -1
  296. package/dist/funding/normalize.js +1 -1
  297. package/dist/funding/rates.d.ts +95 -6
  298. package/dist/funding/rates.js +99 -19
  299. package/dist/index.js +7 -6
  300. package/dist/jobs.d.ts +1 -0
  301. package/dist/jobs.js +25 -1
  302. package/dist/landing.d.ts +2 -0
  303. package/dist/landing.js +1 -1
  304. package/dist/liquidity.d.ts +3 -1
  305. package/dist/liquidity.js +8 -4
  306. package/dist/mcp-pacifica-earn.d.ts +9 -0
  307. package/dist/mcp-pacifica-earn.js +64 -0
  308. package/dist/mcp-server.js +211 -68
  309. package/dist/pacifica/client.d.ts +69 -5
  310. package/dist/pacifica/client.js +181 -8
  311. package/dist/pacifica/rate-limit.d.ts +144 -0
  312. package/dist/pacifica/rate-limit.js +267 -0
  313. package/dist/pacifica/types/order.d.ts +2 -1
  314. package/dist/plan-executor.js +7 -2
  315. package/dist/positions-by-address.d.ts +34 -0
  316. package/dist/positions-by-address.js +46 -0
  317. package/dist/rebalance.js +1 -1
  318. package/dist/risk.d.ts +2 -1
  319. package/dist/risk.js +2 -4
  320. package/dist/settings.d.ts +32 -3
  321. package/dist/signer/ows-evm.d.ts +1 -1
  322. package/dist/signer/ows-evm.js +1 -1
  323. package/dist/smart-order.d.ts +1 -1
  324. package/dist/smart-order.js +1 -1
  325. package/dist/strategies/funding-arb.d.ts +1 -1
  326. package/dist/strategies/funding-arb.js +36 -63
  327. package/dist/trade-validator.js +2 -2
  328. package/dist/utils.d.ts +22 -3
  329. package/dist/utils.js +11 -3
  330. package/dist/venue-health.d.ts +40 -0
  331. package/dist/venue-health.js +75 -0
  332. package/dist/withdraw-gate.d.ts +1 -1
  333. package/dist/withdraw-gate.js +1 -1
  334. package/dist/ws/arcus-market.d.ts +9 -0
  335. package/dist/ws/arcus-market.js +9 -0
  336. package/dist/ws/aster-market.d.ts +33 -0
  337. package/dist/ws/aster-market.js +30 -0
  338. package/dist/ws/index.d.ts +980 -0
  339. package/dist/ws/index.js +4460 -0
  340. package/dist/ws/lighter-market.d.ts +14 -0
  341. package/dist/ws/lighter-market.js +13 -0
  342. package/dist/ws/node.d.ts +996 -0
  343. package/dist/ws/node.js +4554 -0
  344. package/dist/ws/pacifica-instrument.d.ts +8 -0
  345. package/dist/ws/pacifica-instrument.js +8 -0
  346. package/dist/ws/unclassified.d.ts +16 -0
  347. package/dist/ws/unclassified.js +43 -0
  348. package/dist/ws-cli/credentials.d.ts +62 -0
  349. package/dist/ws-cli/credentials.js +126 -0
  350. package/package.json +71 -10
  351. package/skills/perp-cli/SKILL.md +153 -36
  352. package/skills/perp-cli/package.json +15 -2
  353. package/skills/perp-cli/references/agent-operations.md +22 -12
  354. package/skills/perp-cli/references/commands.md +143 -17
  355. package/skills/perp-cli/references/strategies.md +38 -3
  356. package/skills/perp-cli/references/ws-library.md +523 -0
  357. package/skills/perp-cli/scripts/arb-monitor.sh +13 -10
  358. package/skills/perp-cli/scripts/funding-analysis.sh +57 -29
  359. package/skills/perp-cli/scripts/preflight.sh +27 -19
  360. package/skills/perp-cli/scripts/spot-perp-scan.sh +58 -38
  361. package/skills/perp-cli/scripts/validate-arb.sh +56 -39
  362. package/dist/cli-spec.d.ts +0 -46
  363. package/dist/cli-spec.js +0 -81
@@ -1,9 +1,14 @@
1
1
  import { listConfiguredAccountVenues } from "../config.js";
2
- import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch } from "../utils.js";
2
+ import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch, withJsonErrors } from "../utils.js";
3
3
  import chalk from "chalk";
4
4
  import { hasPacificaSdk, isDexCapable } from "../exchanges/capabilities.js";
5
5
  import { PerpError } from "../errors.js";
6
6
  import { unsupported } from "../exchanges/trading-v2.js";
7
+ /** The configured Pacifica account of an account read; keyless → NO_SIGNER_AVAILABLE (never the throwaway keypair's). */
8
+ function pacificaAccount(adapter) {
9
+ const read = adapter.accountForReads;
10
+ return typeof read === "function" ? read.call(adapter) : adapter.publicKey;
11
+ }
7
12
  function pac(adapter) {
8
13
  if (!hasPacificaSdk(adapter))
9
14
  throw new Error("Market settings are only available on Pacifica.");
@@ -28,8 +33,14 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
28
33
  // user what to run and exit non-zero so scripts can detect the rename.
29
34
  account
30
35
  .command("balance")
31
- .description("[renamed] Use 'perp portfolio' (exchange-aggregated) or 'perp portfolio -e <ex>'")
32
- .action(async () => {
36
+ .description("Any account's balances by public address, keyless (--address). Your own balance: 'perp portfolio' (renamed in v0.12)")
37
+ .option("--address <address>", "Read this public address — keyless (hyperliquid, lighter, lighter-rh, risex: 0x address; pacifica: Solana address). Without -e: every venue that supports it")
38
+ .option("--account-index <n>", "With --address on Lighter: only this account (sub-account) of the address")
39
+ .action(async (opts) => {
40
+ if (opts.address !== undefined) {
41
+ const explicitExchange = program.getOptionValueSource?.("exchange") === "cli";
42
+ return void await withJsonErrors(isJson(), () => balanceByAddress(opts.address, explicitExchange ? String(program.opts().exchange) : null, opts));
43
+ }
33
44
  const msg = "'account balance' was renamed in v0.12 — use 'portfolio' instead.";
34
45
  const remediation = "perp portfolio # all exchanges\nperp portfolio -e <exchange> # single exchange detail";
35
46
  if (isJson()) {
@@ -47,9 +58,8 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
47
58
  async function fetchHip3Data(hlAdapter, fetcher) {
48
59
  const dexes = await hlAdapter.listDeployedDexes();
49
60
  const results = await Promise.allSettled(dexes.map(async (d) => {
50
- // Clone adapter with dex set
51
- const dexAdapter = Object.create(hlAdapter);
52
- dexAdapter.setDex(d.name);
61
+ // An independent per-dex adapter (a prototype copy + setDex emptied the native adapter's maps)
62
+ const dexAdapter = hlAdapter.forDex(d.name);
53
63
  const items = await fetcher(dexAdapter);
54
64
  return { dex: d.name, items };
55
65
  }));
@@ -58,12 +68,158 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
58
68
  .map(r => r.value)
59
69
  .filter(r => r.items.length > 0);
60
70
  }
71
+ /** `account balance --address`: keyless public read (registry: VenuePublicData.fetchBalanceByAddress). */
72
+ async function balanceByAddress(address, venue, opts) {
73
+ const { readBalanceByAddress, readBalanceByAddressAll } = await import("../balance-by-address.js");
74
+ const { networkOf } = await import("../cli-flags.js");
75
+ let accountIndex;
76
+ if (opts.accountIndex !== undefined) {
77
+ if (!/^\d+$/.test(opts.accountIndex.trim()))
78
+ throw new PerpError("INVALID_PARAMS", `--account-index must be a whole number, got "${opts.accountIndex}"`);
79
+ accountIndex = Number(opts.accountIndex);
80
+ }
81
+ const net = networkOf(program);
82
+ const balanceRows = (d) => {
83
+ const row = (label, b) => [
84
+ label, `$${formatUsd(b.equity)}`, `$${formatUsd(b.available)}`, `$${formatUsd(b.marginUsed)}`, formatPnl(b.unrealizedPnl),
85
+ ];
86
+ return [
87
+ ...(d.balance !== null ? [row(d.accountMode !== undefined ? `native (${d.accountMode})` : "account", d.balance)] : []),
88
+ ...(d.accounts ?? []).map(a => row(`account ${a.accountIndex}`, a.balance)),
89
+ ...Object.entries(d.dexes ?? {}).map(([dex, b]) => row(chalk.magenta(`dex ${dex}`), b)),
90
+ ];
91
+ };
92
+ const spotRows = (d) => [
93
+ ...(d.spot ?? []).map(s => ["-", s.token, s.total, s.available, s.held]),
94
+ ...(d.accounts ?? []).flatMap(a => a.spot.map(s => [String(a.accountIndex), s.token, s.total, s.available, s.held])),
95
+ ];
96
+ const extras = (d) => {
97
+ const b = d.balance;
98
+ if (b === null)
99
+ return [];
100
+ return ["usdcBalance", "borrowedUsdc", "pendingInterest", "availableToWithdraw"].filter(k => k in b).map(k => `${k}: ${b[k] === null ? "-" : String(b[k])}`);
101
+ };
102
+ const printVenue = (ex, d) => {
103
+ console.log(chalk.cyan.bold(`\n ${ex}`));
104
+ const rows = balanceRows(d);
105
+ if (rows.length > 0)
106
+ console.log(makeTable(["Account", "Equity", "Available", "Margin Used", "uPnL"], rows));
107
+ const x = extras(d);
108
+ if (x.length > 0)
109
+ console.log(chalk.gray(` ${x.join(" ")}`));
110
+ const sr = spotRows(d);
111
+ if (sr.length > 0)
112
+ console.log(makeTable(["Acct", "Spot token", "Total", "Available", "Held"], sr));
113
+ if (rows.length === 0 && sr.length === 0)
114
+ console.log(chalk.gray(" no balance (see notes)"));
115
+ };
116
+ if (venue !== null) {
117
+ const r = await readBalanceByAddress(venue, net, address, { accountIndex });
118
+ if (isJson()) {
119
+ return printJson(jsonOk({ exchange: r.venue, address, ...r.data }, {
120
+ exchange: r.venue, address, source: "public",
121
+ ...(r.warnings.length > 0 ? { warnings: r.warnings, errors: r.errors } : {}),
122
+ ...(r.notes.length > 0 ? { notes: r.notes } : {}),
123
+ }));
124
+ }
125
+ for (const w of r.warnings)
126
+ console.log(chalk.yellow(` ${w}`));
127
+ printVenue(r.venue, r.data);
128
+ for (const n of r.notes)
129
+ console.log(chalk.gray(` ${n}`));
130
+ console.log();
131
+ return;
132
+ }
133
+ const all = await readBalanceByAddressAll(net, address, { accountIndex });
134
+ if (isJson()) {
135
+ return printJson(jsonOk({
136
+ venues: all.venues,
137
+ ...(Object.keys(all.errors).length > 0 ? { errors: all.errors } : {}),
138
+ ...(Object.keys(all.notes).length > 0 ? { notes: all.notes } : {}),
139
+ }, { address, source: "public", ...(all.warnings.length > 0 ? { warnings: all.warnings } : {}) }));
140
+ }
141
+ for (const [ex, d] of Object.entries(all.venues))
142
+ printVenue(ex, d);
143
+ console.log();
144
+ for (const [ex, e] of Object.entries(all.errors))
145
+ console.log(chalk.gray(` ${ex}: ${e.code} ${e.message}`));
146
+ for (const [ex, n] of Object.entries(all.notes))
147
+ console.log(chalk.gray(` ${ex}: ${n.join("; ")}`));
148
+ }
149
+ /** `account positions --address`: keyless public read (registry: VenuePublicData.fetchPositionsByAddress). */
150
+ async function positionsByAddress(address, venue, opts) {
151
+ const { readPositionsByAddress, readPositionsByAddressAll } = await import("../positions-by-address.js");
152
+ const { networkOf } = await import("../cli-flags.js");
153
+ let accountIndex;
154
+ if (opts.accountIndex !== undefined) {
155
+ if (!/^\d+$/.test(opts.accountIndex.trim()))
156
+ throw new PerpError("INVALID_PARAMS", `--account-index must be a whole number, got "${opts.accountIndex}"`);
157
+ accountIndex = Number(opts.accountIndex);
158
+ }
159
+ const net = networkOf(program);
160
+ const row = (p, ex) => [
161
+ chalk.white.bold(p.symbol),
162
+ ...(ex !== null ? [chalk.gray(ex)] : []),
163
+ p.dex != null ? chalk.magenta(p.dex) : p.accountIndex !== undefined ? chalk.gray(String(p.accountIndex)) : chalk.gray("-"),
164
+ p.side === "long" ? chalk.green("LONG") : chalk.red("SHORT"),
165
+ p.size,
166
+ `$${formatUsd(p.entryPrice)}`,
167
+ `$${formatUsd(p.markPrice)}`,
168
+ p.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(p.liquidationPrice)}`,
169
+ formatPnl(p.unrealizedPnl),
170
+ `${p.leverage}x`,
171
+ ];
172
+ if (venue !== null) {
173
+ const r = await readPositionsByAddress(venue, net, address, { accountIndex, symbol: opts.symbol });
174
+ if (isJson()) {
175
+ return printJson(jsonOk(r.positions, {
176
+ exchange: r.venue, address, source: "public",
177
+ ...(r.warnings.length > 0 ? { warnings: r.warnings, errors: r.errors } : {}),
178
+ ...(r.notes.length > 0 ? { notes: r.notes } : {}),
179
+ }));
180
+ }
181
+ for (const w of r.warnings)
182
+ console.log(chalk.yellow(` ${w}`));
183
+ if (r.positions.length === 0) {
184
+ console.log(chalk.gray(`\n No open positions for ${address} on ${r.venue}${r.notes.length > 0 ? ` (${r.notes.join("; ")})` : ""}.\n`));
185
+ return;
186
+ }
187
+ console.log(makeTable(["Symbol", "Dex/Acct", "Side", "Size", "Entry", "Mark", "Liq", "PnL", "Lev"], r.positions.map(p => row(p, null))));
188
+ return;
189
+ }
190
+ const all = await readPositionsByAddressAll(net, address, { accountIndex, symbol: opts.symbol });
191
+ if (isJson()) {
192
+ return printJson(jsonOk({
193
+ venues: all.venues,
194
+ ...(Object.keys(all.errors).length > 0 ? { errors: all.errors } : {}),
195
+ ...(Object.keys(all.notes).length > 0 ? { notes: all.notes } : {}),
196
+ }, { address, source: "public", ...(all.warnings.length > 0 ? { warnings: all.warnings } : {}) }));
197
+ }
198
+ const rows = Object.entries(all.venues).flatMap(([ex, ps]) => ps.map(p => row(p, ex)));
199
+ if (rows.length > 0)
200
+ console.log(makeTable(["Symbol", "Exch", "Dex/Acct", "Side", "Size", "Entry", "Mark", "Liq", "PnL", "Lev"], rows));
201
+ else
202
+ console.log(chalk.gray(`\n No open positions for ${address} on ${Object.keys(all.venues).join(", ") || "any venue"}.\n`));
203
+ for (const [ex, e] of Object.entries(all.errors))
204
+ console.log(chalk.gray(` ${ex}: ${e.code} ${e.message}`));
205
+ for (const [ex, n] of Object.entries(all.notes))
206
+ console.log(chalk.gray(` ${ex}: ${n.join("; ")}`));
207
+ }
61
208
  account
62
209
  .command("positions")
63
- .description("Show open positions")
210
+ .description("Show open positions (yours; or any account's, keyless, with --address)")
64
211
  .option("--hip3", "Include HIP-3 dex positions (Hyperliquid)")
212
+ .option("--address <address>", "Read this public address instead of your account — keyless (hyperliquid, lighter, lighter-rh, risex: 0x address; pacifica: Solana address). Without -e: every venue that supports it")
213
+ .option("--account-index <n>", "With --address on Lighter: only this account (sub-account) of the address")
214
+ .option("--symbol <symbol>", "With --address: only this market (plain asset, e.g. BTC)")
65
215
  .action(async (opts) => {
66
216
  const explicitExchange = program.getOptionValueSource?.("exchange") === "cli";
217
+ if (opts.address !== undefined) {
218
+ return void await withJsonErrors(isJson(), () => positionsByAddress(opts.address, explicitExchange ? String(program.opts().exchange) : null, opts));
219
+ }
220
+ if (opts.accountIndex !== undefined || opts.symbol !== undefined) {
221
+ throw new PerpError("INVALID_PARAMS", "--account-index / --symbol apply to --address reads", { remediation: "Add --address <address>, or drop the option" });
222
+ }
67
223
  if (!explicitExchange && getAdapterForExchange) {
68
224
  const EXCHANGES = await listConfiguredAccountVenues();
69
225
  const allRows = [];
@@ -316,7 +472,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
316
472
  // Pacifica: use dedicated SDK endpoint
317
473
  if (hasPacificaSdk(adapter)) {
318
474
  const sdk = adapter.sdk;
319
- const settings = await sdk.getAccountSettings(adapter.publicKey);
475
+ const settings = await sdk.getAccountSettings(pacificaAccount(adapter));
320
476
  if (isJson())
321
477
  return printJson(jsonOk(settings));
322
478
  // GET /account/settings returns an object; per-market entries are in `margin_settings`
@@ -404,7 +560,8 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
404
560
  .description("Margin details for a specific symbol position")
405
561
  .action(async (symbol) => {
406
562
  const sym = symbol.toUpperCase();
407
- try {
563
+ // Errors: the one envelope (code, status, remediation) and exit 1 via withJsonErrors.
564
+ return void await withJsonErrors(isJson(), async () => {
408
565
  const adapter = await getAdapter();
409
566
  const [balance, positions] = await Promise.all([
410
567
  adapter.getBalance(),
@@ -452,20 +609,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
452
609
  console.log(` Liquidation: ${pos.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(pos.liquidationPrice)}`}`);
453
610
  console.log(` Unrealized PnL: ${formatPnl(pos.unrealizedPnl)}`);
454
611
  console.log();
455
- }
456
- catch (err) {
457
- const msg = err instanceof Error ? err.message : String(err);
458
- if (isJson()) {
459
- const { classifyError } = await import("../errors.js");
460
- const classified = classifyError(err);
461
- return printJson(jsonError(classified.code, classified.message, {
462
- status: classified.status,
463
- retryable: classified.retryable,
464
- }));
465
- }
466
- console.error(chalk.red(`Error: ${msg}`));
467
- process.exitCode = 1;
468
- }
612
+ });
469
613
  });
470
614
  // ── PnL Report ──
471
615
  account
@@ -609,7 +753,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
609
753
  }
610
754
  const p = pac(adapter);
611
755
  const sdk = p.sdk;
612
- const orders = await sdk.getTWAPOrders(p.publicKey);
756
+ const orders = await sdk.getTWAPOrders(pacificaAccount(p));
613
757
  if (isJson())
614
758
  return printJson(jsonOk(orders));
615
759
  if (!orders || orders.length === 0) {
@@ -90,6 +90,13 @@ export declare function importSecretLineCount(venue: VenueId): number;
90
90
  export declare function importSecretFromLines(venue: VenueId, lines: string[]): ImportSecret;
91
91
  /** Read the secret: hidden TTY prompt, else piped stdin (ondo: 2 lines key id + secret; others: 1 line). */
92
92
  export declare function readImportSecret(venue: VenueId): Promise<ImportSecret>;
93
+ /**
94
+ * Venues whose keys cannot be imported. TxFlow: market-data-only (unofficial read-only API).
95
+ * RISEx: perp-cli trades only with a signer it registered itself and then restricted ON-CHAIN to
96
+ * the trading permission; a signer created in the RISEx app keeps every permission (including
97
+ * deposit / withdraw), so it is never stored here.
98
+ */
99
+ export declare function assertImportSupported(venue: VenueId, network: Network): void;
93
100
  /** Venues whose import cannot be checked against the venue (stored as "unverified"). */
94
101
  export declare const UNVERIFIED_IMPORT_VENUES: readonly VenueId[];
95
102
  /**
@@ -24,7 +24,8 @@
24
24
  import chalk from "chalk";
25
25
  import { PerpError, classifyError } from "../errors.js";
26
26
  import { acquireLock, releaseLock, getAgent, setAgent, deleteAgent, listAgents, agentNetworkOf, agentSourceOf, getVenueAgent, setVenueAgent, deleteVenueAgent, } from "../agent-wallet/store.js";
27
- import { getVenue, networkConfig } from "../exchanges/venue.js";
27
+ import { getVenue, networkConfig, roleUnsupported } from "../exchanges/venue.js";
28
+ import { unsupported } from "../exchanges/trading-v2.js";
28
29
  import { LIGHTER_RH_RESERVED_KEY_INDEXES } from "../exchanges/venues/lighter-family.js";
29
30
  import { loadOws } from "../signer/ows-loader.js";
30
31
  import { defaultAgentName, isLighterFamilyVenue, parseExpiresIn, promptHidden, qfexWithdrawKeyWarning } from "./agent.js";
@@ -67,6 +68,11 @@ export function importSecretLabel(venue) {
67
68
  case "arcus": return "Arcus API key private key (Ed25519)";
68
69
  case "ondo": return "Ondo API secret";
69
70
  case "qfex": return "QFEX API secret";
71
+ case "risex": return "RISEx signer private key";
72
+ case "txflow": return "TxFlow key (not supported)";
73
+ case "variational": return "Variational key (not supported)";
74
+ case "grvt": return "GRVT key (not supported)";
75
+ case "extended": return "Extended key (not supported)";
70
76
  }
71
77
  }
72
78
  /**
@@ -154,6 +160,20 @@ function redacted(err, secrets, venue) {
154
160
  details.remediation = scrub(e.remediation, forms);
155
161
  return new PerpError(e.code, scrub(e.message, forms), details);
156
162
  }
163
+ /**
164
+ * Venues whose keys cannot be imported. TxFlow: market-data-only (unofficial read-only API).
165
+ * RISEx: perp-cli trades only with a signer it registered itself and then restricted ON-CHAIN to
166
+ * the trading permission; a signer created in the RISEx app keeps every permission (including
167
+ * deposit / withdraw), so it is never stored here.
168
+ */
169
+ export function assertImportSupported(venue, network) {
170
+ const def = getVenue(venue);
171
+ if (!def.roles.includes("trading"))
172
+ throw roleUnsupported(def, "agentImport");
173
+ if (venue === "risex") {
174
+ throw unsupported("risex", "agentImport", "perp-cli only uses RISEx signers it registered and restricted on-chain to trading-only permissions; an app-created signer keeps deposit / withdraw permissions", `Register a restricted signer with your master wallet: perp${network === "testnet" ? " -n testnet" : ""} wallet agent approve risex --master <ows-wallet>`);
175
+ }
176
+ }
157
177
  /** Venues whose import cannot be checked against the venue (stored as "unverified"). */
158
178
  export const UNVERIFIED_IMPORT_VENUES = ["pacifica"];
159
179
  /**
@@ -722,6 +742,8 @@ async function importQfex(p, agentName, s, replacing) {
722
742
  * appears in a thrown error.
723
743
  */
724
744
  export async function importVenueAgent(p) {
745
+ // Refused before the secret is even inspected (nothing read, stored or sent).
746
+ assertImportSupported(p.venue, p.network);
725
747
  const secrets = secretsOf(p.secret);
726
748
  if (secrets.some(x => x.trim().length === 0))
727
749
  throw new PerpError("INVALID_PARAMS", "Empty key — nothing was imported");
@@ -751,6 +773,13 @@ export async function importVenueAgent(p) {
751
773
  case "lighter":
752
774
  case "lighter-rh":
753
775
  return await importLighter(p, p.venue, agentName, key, replacing);
776
+ case "risex":
777
+ case "txflow":
778
+ case "variational":
779
+ case "grvt":
780
+ case "extended":
781
+ // Unreachable: assertImportSupported() refused these before the lock.
782
+ throw new PerpError("CAPABILITY_UNSUPPORTED", `${p.venue} keys cannot be imported`);
754
783
  }
755
784
  }
756
785
  catch (err) {
@@ -1,5 +1,5 @@
1
1
  import { Command, Option } from "commander";
2
- import { loadSettings, type OndoAgentMeta, type ArcusAgentMeta, type QfexAgentMeta } from "../settings.js";
2
+ import { loadSettings, type OndoAgentMeta, type ArcusAgentMeta, type QfexAgentMeta, type RisexAgentMeta } from "../settings.js";
3
3
  import "../exchanges/venues/index.js";
4
4
  import type { Network, VenueId } from "../exchanges/venue-types.js";
5
5
  import { type LighterVenueId } from "../exchanges/venues/lighter-family.js";
@@ -27,7 +27,7 @@ export interface VerifyResult {
27
27
  /** Extract the agent list from a Pacifica /agent/list envelope; throws on an unrecognized shape. */
28
28
  export declare function parsePacAgentList(json: unknown): unknown[];
29
29
  /**
30
- * Confirmation of the account a QFEX key was resolved to (design §14.12 #9). In a terminal: a
30
+ * Confirmation of the account a QFEX key was resolved to. In a terminal: a
31
31
  * y/N prompt showing the UUID. Without one (piped stdin, --json): only an explicit --account-id
32
32
  * that equals the resolved account counts — the resolved UUID is printed on stderr either way.
33
33
  */
@@ -94,6 +94,9 @@ export type ApproveAgentOutcome = {
94
94
  } | {
95
95
  venue: "arcus";
96
96
  meta: ArcusAgentMeta;
97
+ } | {
98
+ venue: "risex";
99
+ meta: RisexAgentMeta;
97
100
  } | {
98
101
  venue: LighterVenueId;
99
102
  agentName: string;
@@ -131,7 +134,7 @@ export declare function qfexWithdrawKeyWarning(meta: Pick<QfexAgentMeta, "agentN
131
134
  /** Venues `wallet agent rotate` (and `approve --rotate`) can rotate. */
132
135
  type RotatableVenue = "aster" | "hyperliquid" | "pacifica" | LighterVenueId;
133
136
  type RotatedAgentOutcome = Exclude<ApproveAgentOutcome, {
134
- venue: "ondo" | "arcus";
137
+ venue: "ondo" | "arcus" | "risex";
135
138
  }>;
136
139
  export interface RotateAgentParams {
137
140
  exchange: RotatableVenue;