perp-cli 0.12.17 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/README.md +247 -27
  2. package/dist/_stderr-filter.js +0 -1
  3. package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
  4. package/dist/agent-wallet/lighter-keystore.js +92 -10
  5. package/dist/agent-wallet/passphrase.d.ts +1 -1
  6. package/dist/agent-wallet/passphrase.js +16 -3
  7. package/dist/agent-wallet/store.d.ts +37 -4
  8. package/dist/agent-wallet/store.js +132 -0
  9. package/dist/agent-wallet/venue-keystore.d.ts +14 -0
  10. package/dist/agent-wallet/venue-keystore.js +121 -0
  11. package/dist/api/public/hyperliquid.js +4 -4
  12. package/dist/api/public/lighter.js +5 -5
  13. package/dist/api/public/pacifica.d.ts +0 -1
  14. package/dist/api/public/pacifica.js +4 -13
  15. package/dist/api/public/urls.d.ts +9 -1
  16. package/dist/api/public/urls.js +35 -13
  17. package/dist/arb/file-lock.d.ts +11 -0
  18. package/dist/arb/file-lock.js +74 -0
  19. package/dist/arb/index.d.ts +2 -2
  20. package/dist/arb/index.js +2 -2
  21. package/dist/arb/pending-entry.d.ts +32 -0
  22. package/dist/arb/pending-entry.js +77 -0
  23. package/dist/arb/sizing.d.ts +6 -13
  24. package/dist/arb/sizing.js +12 -51
  25. package/dist/arb/state.d.ts +45 -12
  26. package/dist/arb/state.js +214 -42
  27. package/dist/arb/utils.d.ts +20 -6
  28. package/dist/arb/utils.js +43 -39
  29. package/dist/bot/conditions.d.ts +4 -4
  30. package/dist/bot/conditions.js +11 -6
  31. package/dist/bot/config.d.ts +17 -1
  32. package/dist/bot/config.js +48 -12
  33. package/dist/bot/engine.d.ts +61 -2
  34. package/dist/bot/engine.js +610 -144
  35. package/dist/bot/fill-size.d.ts +7 -0
  36. package/dist/bot/fill-size.js +18 -0
  37. package/dist/bot/index.d.ts +1 -1
  38. package/dist/bot/index.js +1 -1
  39. package/dist/bot/perp-order.d.ts +99 -0
  40. package/dist/bot/perp-order.js +299 -0
  41. package/dist/bot/presets.d.ts +7 -0
  42. package/dist/bot/presets.js +17 -0
  43. package/dist/bot/quarantine.d.ts +75 -0
  44. package/dist/bot/quarantine.js +190 -0
  45. package/dist/bot/quote-rules.d.ts +23 -0
  46. package/dist/bot/quote-rules.js +69 -0
  47. package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
  48. package/dist/bot/strategies/avellaneda-mm.js +72 -70
  49. package/dist/bot/strategies/basis-arb.js +2 -0
  50. package/dist/bot/strategies/dca-strategy.d.ts +2 -0
  51. package/dist/bot/strategies/dca-strategy.js +5 -0
  52. package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
  53. package/dist/bot/strategies/funding-arb-strategy.js +571 -380
  54. package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
  55. package/dist/bot/strategies/funding-arb-utils.js +159 -195
  56. package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
  57. package/dist/bot/strategies/funding-arb-v2.js +258 -47
  58. package/dist/bot/strategies/funding-auto.js +215 -194
  59. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
  60. package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
  61. package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
  62. package/dist/bot/strategies/spot-perp-executor.js +319 -120
  63. package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
  64. package/dist/bot/strategies/spot-perp-state.js +70 -0
  65. package/dist/bot/strategy-types.d.ts +6 -0
  66. package/dist/bot/tui/BotDashboard.d.ts +7 -2
  67. package/dist/bot/tui/BotDashboard.js +6 -3
  68. package/dist/bridge-engine.d.ts +120 -19
  69. package/dist/bridge-engine.js +710 -422
  70. package/dist/bridge-signers.d.ts +54 -0
  71. package/dist/bridge-signers.js +161 -0
  72. package/dist/cache.d.ts +4 -1
  73. package/dist/cache.js +11 -0
  74. package/dist/cli-flags.d.ts +50 -0
  75. package/dist/cli-flags.js +104 -0
  76. package/dist/cli-program.d.ts +35 -0
  77. package/dist/cli-program.js +303 -0
  78. package/dist/cli-spec.js +1 -1
  79. package/dist/client-id-tracker.js +11 -2
  80. package/dist/commands/account.d.ts +7 -1
  81. package/dist/commands/account.js +70 -92
  82. package/dist/commands/agent-import.d.ts +114 -0
  83. package/dist/commands/agent-import.js +794 -0
  84. package/dist/commands/agent.d.ts +232 -2
  85. package/dist/commands/agent.js +1858 -955
  86. package/dist/commands/alerts.d.ts +1 -0
  87. package/dist/commands/alerts.js +31 -28
  88. package/dist/commands/arb/index.d.ts +60 -1
  89. package/dist/commands/arb/index.js +381 -384
  90. package/dist/commands/arb-auto.d.ts +132 -4
  91. package/dist/commands/arb-auto.js +1474 -967
  92. package/dist/commands/arb.d.ts +3 -1
  93. package/dist/commands/arb.js +62 -30
  94. package/dist/commands/bot.js +127 -47
  95. package/dist/commands/bridge.d.ts +2 -1
  96. package/dist/commands/bridge.js +339 -192
  97. package/dist/commands/builder.d.ts +55 -0
  98. package/dist/commands/builder.js +387 -0
  99. package/dist/commands/funds-onchain.d.ts +32 -0
  100. package/dist/commands/funds-onchain.js +248 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +925 -245
  103. package/dist/commands/history.js +102 -54
  104. package/dist/commands/init.d.ts +107 -15
  105. package/dist/commands/init.js +1116 -249
  106. package/dist/commands/jobs.d.ts +2 -1
  107. package/dist/commands/jobs.js +77 -15
  108. package/dist/commands/manage.js +136 -91
  109. package/dist/commands/market.d.ts +4 -1
  110. package/dist/commands/market.js +35 -32
  111. package/dist/commands/outcome.d.ts +10 -0
  112. package/dist/commands/outcome.js +396 -0
  113. package/dist/commands/plan.js +52 -12
  114. package/dist/commands/portfolio.d.ts +1 -0
  115. package/dist/commands/portfolio.js +60 -72
  116. package/dist/commands/rebalance.d.ts +2 -1
  117. package/dist/commands/rebalance.js +33 -43
  118. package/dist/commands/risk.js +46 -19
  119. package/dist/commands/settings.d.ts +1 -0
  120. package/dist/commands/settings.js +246 -51
  121. package/dist/commands/trade.d.ts +50 -0
  122. package/dist/commands/trade.js +1943 -695
  123. package/dist/commands/wallet.d.ts +30 -1
  124. package/dist/commands/wallet.js +357 -459
  125. package/dist/config.d.ts +60 -9
  126. package/dist/config.js +252 -82
  127. package/dist/constants.d.ts +29 -4
  128. package/dist/constants.js +62 -20
  129. package/dist/dashboard/server.d.ts +2 -0
  130. package/dist/dashboard/server.js +9 -6
  131. package/dist/dashboard/ui.js +6 -4
  132. package/dist/dashboard/ws-feeds.js +20 -8
  133. package/dist/dex-asset-map.js +5 -3
  134. package/dist/errors.d.ts +122 -0
  135. package/dist/errors.js +194 -0
  136. package/dist/event-stream.js +75 -19
  137. package/dist/evm-master-tx.d.ts +59 -0
  138. package/dist/evm-master-tx.js +154 -0
  139. package/dist/exchanges/adapter-network.d.ts +10 -0
  140. package/dist/exchanges/adapter-network.js +10 -0
  141. package/dist/exchanges/arcus/adapter.d.ts +196 -0
  142. package/dist/exchanges/arcus/adapter.js +1092 -0
  143. package/dist/exchanges/arcus/agent.d.ts +55 -0
  144. package/dist/exchanges/arcus/agent.js +188 -0
  145. package/dist/exchanges/arcus/client.d.ts +63 -0
  146. package/dist/exchanges/arcus/client.js +285 -0
  147. package/dist/exchanges/arcus/public.d.ts +65 -0
  148. package/dist/exchanges/arcus/public.js +138 -0
  149. package/dist/exchanges/arcus/signing.d.ts +176 -0
  150. package/dist/exchanges/arcus/signing.js +288 -0
  151. package/dist/exchanges/arcus/spot-chain.d.ts +60 -0
  152. package/dist/exchanges/arcus/spot-chain.js +241 -0
  153. package/dist/exchanges/arcus/spot-router.d.ts +177 -0
  154. package/dist/exchanges/arcus/spot-router.js +183 -0
  155. package/dist/exchanges/arcus/spot.d.ts +109 -0
  156. package/dist/exchanges/arcus/spot.js +645 -0
  157. package/dist/exchanges/aster-funds.d.ts +127 -0
  158. package/dist/exchanges/aster-funds.js +252 -0
  159. package/dist/exchanges/aster-nonce.d.ts +2 -0
  160. package/dist/exchanges/aster-nonce.js +107 -0
  161. package/dist/exchanges/aster-spot.d.ts +117 -0
  162. package/dist/exchanges/aster-spot.js +686 -0
  163. package/dist/exchanges/aster-typed-data.d.ts +133 -7
  164. package/dist/exchanges/aster-typed-data.js +121 -7
  165. package/dist/exchanges/aster.d.ts +240 -6
  166. package/dist/exchanges/aster.js +1139 -195
  167. package/dist/exchanges/builder-fee.d.ts +254 -0
  168. package/dist/exchanges/builder-fee.js +421 -0
  169. package/dist/exchanges/canonical-symbols.d.ts +32 -0
  170. package/dist/exchanges/canonical-symbols.js +96 -0
  171. package/dist/exchanges/capabilities.d.ts +7 -1
  172. package/dist/exchanges/capabilities.js +7 -0
  173. package/dist/exchanges/hl-signing.d.ts +165 -0
  174. package/dist/exchanges/hl-signing.js +158 -0
  175. package/dist/exchanges/hyperliquid-outcome.d.ts +211 -0
  176. package/dist/exchanges/hyperliquid-outcome.js +646 -0
  177. package/dist/exchanges/hyperliquid-spot.d.ts +44 -5
  178. package/dist/exchanges/hyperliquid-spot.js +308 -117
  179. package/dist/exchanges/hyperliquid.d.ts +462 -57
  180. package/dist/exchanges/hyperliquid.js +1575 -449
  181. package/dist/exchanges/index.d.ts +6 -0
  182. package/dist/exchanges/index.js +4 -0
  183. package/dist/exchanges/interface.d.ts +63 -10
  184. package/dist/exchanges/interface.js +18 -3
  185. package/dist/exchanges/ioc-outcome.d.ts +44 -0
  186. package/dist/exchanges/ioc-outcome.js +57 -0
  187. package/dist/exchanges/legacy-trading-v2.d.ts +39 -0
  188. package/dist/exchanges/legacy-trading-v2.js +940 -0
  189. package/dist/exchanges/lighter-public.d.ts +43 -0
  190. package/dist/exchanges/lighter-public.js +276 -0
  191. package/dist/exchanges/lighter-rh-deposit.d.ts +62 -0
  192. package/dist/exchanges/lighter-rh-deposit.js +185 -0
  193. package/dist/exchanges/lighter-signer.d.ts +123 -0
  194. package/dist/exchanges/lighter-signer.js +215 -0
  195. package/dist/exchanges/lighter-spot.d.ts +91 -13
  196. package/dist/exchanges/lighter-spot.js +595 -233
  197. package/dist/exchanges/lighter.d.ts +611 -39
  198. package/dist/exchanges/lighter.js +1890 -649
  199. package/dist/exchanges/ondo/adapter.d.ts +152 -0
  200. package/dist/exchanges/ondo/adapter.js +811 -0
  201. package/dist/exchanges/ondo/agent.d.ts +31 -0
  202. package/dist/exchanges/ondo/agent.js +101 -0
  203. package/dist/exchanges/ondo/client.d.ts +60 -0
  204. package/dist/exchanges/ondo/client.js +297 -0
  205. package/dist/exchanges/ondo/funds.d.ts +95 -0
  206. package/dist/exchanges/ondo/funds.js +198 -0
  207. package/dist/exchanges/ondo/public.d.ts +95 -0
  208. package/dist/exchanges/ondo/public.js +214 -0
  209. package/dist/exchanges/ondo/spot.d.ts +127 -0
  210. package/dist/exchanges/ondo/spot.js +392 -0
  211. package/dist/exchanges/outcome-interface.d.ts +140 -0
  212. package/dist/exchanges/outcome-interface.js +16 -0
  213. package/dist/exchanges/pacifica-spot.d.ts +83 -0
  214. package/dist/exchanges/pacifica-spot.js +324 -0
  215. package/dist/exchanges/pacifica-typed-data.d.ts +30 -13
  216. package/dist/exchanges/pacifica-typed-data.js +57 -9
  217. package/dist/exchanges/pacifica.d.ts +293 -4
  218. package/dist/exchanges/pacifica.js +1044 -90
  219. package/dist/exchanges/precision.d.ts +47 -0
  220. package/dist/exchanges/precision.js +209 -0
  221. package/dist/exchanges/qfex/adapter.d.ts +341 -0
  222. package/dist/exchanges/qfex/adapter.js +1386 -0
  223. package/dist/exchanges/qfex/agent.d.ts +58 -0
  224. package/dist/exchanges/qfex/agent.js +188 -0
  225. package/dist/exchanges/qfex/client.d.ts +54 -0
  226. package/dist/exchanges/qfex/client.js +138 -0
  227. package/dist/exchanges/qfex/errors.d.ts +70 -0
  228. package/dist/exchanges/qfex/errors.js +236 -0
  229. package/dist/exchanges/qfex/public.d.ts +122 -0
  230. package/dist/exchanges/qfex/public.js +268 -0
  231. package/dist/exchanges/qfex/signing.d.ts +160 -0
  232. package/dist/exchanges/qfex/signing.js +283 -0
  233. package/dist/exchanges/qfex/ws-transport.d.ts +294 -0
  234. package/dist/exchanges/qfex/ws-transport.js +798 -0
  235. package/dist/exchanges/rate-limiter.d.ts +12 -0
  236. package/dist/exchanges/rate-limiter.js +64 -0
  237. package/dist/exchanges/registry.d.ts +14 -2
  238. package/dist/exchanges/registry.js +20 -32
  239. package/dist/exchanges/slippage.d.ts +37 -0
  240. package/dist/exchanges/slippage.js +70 -0
  241. package/dist/exchanges/spot-factory.d.ts +166 -0
  242. package/dist/exchanges/spot-factory.js +431 -0
  243. package/dist/exchanges/spot-interface.d.ts +98 -4
  244. package/dist/exchanges/spot-interface.js +27 -1
  245. package/dist/exchanges/spot-result.d.ts +79 -0
  246. package/dist/exchanges/spot-result.js +273 -0
  247. package/dist/exchanges/trading-v2.d.ts +117 -0
  248. package/dist/exchanges/trading-v2.js +301 -0
  249. package/dist/exchanges/venue-types.d.ts +231 -0
  250. package/dist/exchanges/venue-types.js +87 -0
  251. package/dist/exchanges/venue.d.ts +211 -0
  252. package/dist/exchanges/venue.js +132 -0
  253. package/dist/exchanges/venues/arcus.d.ts +8 -0
  254. package/dist/exchanges/venues/arcus.js +109 -0
  255. package/dist/exchanges/venues/aster.d.ts +49 -0
  256. package/dist/exchanges/venues/aster.js +176 -0
  257. package/dist/exchanges/venues/create-helpers.d.ts +18 -0
  258. package/dist/exchanges/venues/create-helpers.js +199 -0
  259. package/dist/exchanges/venues/hyperliquid.d.ts +23 -0
  260. package/dist/exchanges/venues/hyperliquid.js +126 -0
  261. package/dist/exchanges/venues/index.d.ts +16 -0
  262. package/dist/exchanges/venues/index.js +26 -0
  263. package/dist/exchanges/venues/lighter-family.d.ts +92 -0
  264. package/dist/exchanges/venues/lighter-family.js +166 -0
  265. package/dist/exchanges/venues/lighter-rh.d.ts +7 -0
  266. package/dist/exchanges/venues/lighter-rh.js +58 -0
  267. package/dist/exchanges/venues/lighter.d.ts +6 -0
  268. package/dist/exchanges/venues/lighter.js +55 -0
  269. package/dist/exchanges/venues/ondo.d.ts +29 -0
  270. package/dist/exchanges/venues/ondo.js +136 -0
  271. package/dist/exchanges/venues/pacifica.d.ts +8 -0
  272. package/dist/exchanges/venues/pacifica.js +95 -0
  273. package/dist/exchanges/venues/qfex.d.ts +39 -0
  274. package/dist/exchanges/venues/qfex.js +140 -0
  275. package/dist/execution-log.js +10 -2
  276. package/dist/funding/legacy-public.d.ts +31 -0
  277. package/dist/funding/legacy-public.js +369 -0
  278. package/dist/funding/normalize.d.ts +28 -16
  279. package/dist/funding/normalize.js +61 -29
  280. package/dist/funding/rates.d.ts +46 -11
  281. package/dist/funding/rates.js +228 -277
  282. package/dist/guardrail/perp-guardrail.js +0 -0
  283. package/dist/index.js +156 -684
  284. package/dist/jobs.d.ts +84 -6
  285. package/dist/jobs.js +239 -41
  286. package/dist/landing.d.ts +7 -2
  287. package/dist/landing.js +19 -3
  288. package/dist/mcp-server.d.ts +14 -4
  289. package/dist/mcp-server.js +821 -403
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/onchain-balances.d.ts +40 -0
  293. package/dist/onchain-balances.js +173 -0
  294. package/dist/pacifica/client.d.ts +41 -10
  295. package/dist/pacifica/client.js +167 -63
  296. package/dist/pacifica/constants.d.ts +0 -1
  297. package/dist/pacifica/constants.js +0 -5
  298. package/dist/pacifica/deposit.d.ts +30 -3
  299. package/dist/pacifica/deposit.js +119 -2
  300. package/dist/pacifica/faucet.d.ts +29 -0
  301. package/dist/pacifica/faucet.js +100 -0
  302. package/dist/pacifica/sign-tx.d.ts +15 -0
  303. package/dist/pacifica/sign-tx.js +41 -0
  304. package/dist/pacifica/types/account.d.ts +28 -4
  305. package/dist/pacifica/types/lake.d.ts +20 -5
  306. package/dist/pacifica/types/lake.js +4 -0
  307. package/dist/pacifica/types/market.d.ts +5 -0
  308. package/dist/pacifica/types/order.d.ts +4 -1
  309. package/dist/pacifica/types/position.d.ts +9 -1
  310. package/dist/plan-executor.d.ts +10 -5
  311. package/dist/plan-executor.js +165 -54
  312. package/dist/position-history.js +13 -0
  313. package/dist/rebalance.d.ts +26 -2
  314. package/dist/rebalance.js +86 -7
  315. package/dist/relay-swap.d.ts +232 -0
  316. package/dist/relay-swap.js +630 -0
  317. package/dist/risk.js +5 -1
  318. package/dist/secret-env.d.ts +15 -0
  319. package/dist/secret-env.js +36 -0
  320. package/dist/settings.d.ts +169 -6
  321. package/dist/settings.js +219 -38
  322. package/dist/signer/ows-evm.d.ts +13 -0
  323. package/dist/signer/ows-evm.js +22 -0
  324. package/dist/smart-order.d.ts +9 -0
  325. package/dist/smart-order.js +53 -8
  326. package/dist/strategies/dca.d.ts +6 -2
  327. package/dist/strategies/dca.js +66 -26
  328. package/dist/strategies/funding-arb.d.ts +11 -1
  329. package/dist/strategies/funding-arb.js +202 -89
  330. package/dist/strategies/grid.d.ts +31 -0
  331. package/dist/strategies/grid.js +89 -11
  332. package/dist/strategies/pending-stop.d.ts +8 -0
  333. package/dist/strategies/pending-stop.js +12 -0
  334. package/dist/strategies/split-order.d.ts +45 -17
  335. package/dist/strategies/split-order.js +157 -91
  336. package/dist/strategies/trailing-stop.d.ts +2 -1
  337. package/dist/strategies/trailing-stop.js +52 -6
  338. package/dist/strategies/twap.d.ts +6 -1
  339. package/dist/strategies/twap.js +39 -11
  340. package/dist/trade-validator.d.ts +22 -0
  341. package/dist/trade-validator.js +119 -15
  342. package/dist/utils/numeric.d.ts +46 -0
  343. package/dist/utils/numeric.js +79 -0
  344. package/dist/utils.d.ts +19 -0
  345. package/dist/utils.js +96 -19
  346. package/dist/withdraw-gate.d.ts +49 -0
  347. package/dist/withdraw-gate.js +131 -0
  348. package/package.json +15 -6
  349. package/skills/perp-cli/SKILL.md +159 -55
  350. package/skills/perp-cli/references/agent-operations.md +112 -58
  351. package/skills/perp-cli/references/commands.md +269 -73
  352. package/skills/perp-cli/references/strategies.md +34 -31
  353. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  354. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  355. package/skills/perp-cli/scripts/preflight.sh +21 -14
  356. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  357. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  358. package/vendor/lighter-signer/SHA256SUMS +2 -0
  359. package/vendor/lighter-signer/VERSION +8 -0
  360. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  361. package/vendor/lighter-signer/wasm_exec.js +575 -0
  362. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  363. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -1,10 +1,11 @@
1
+ import { listConfiguredAccountVenues } from "../config.js";
1
2
  import chalk from "chalk";
2
3
  import { printJson, jsonOk, jsonError, makeTable, formatUsd, formatPnl, withJsonErrors } from "../utils.js";
3
4
  import { readExecutionLog, getExecutionStats, pruneExecutionLog } from "../execution-log.js";
4
5
  import { loadArbState } from "../arb/index.js";
6
+ import { networkOf } from "../cli-flags.js";
5
7
  import { readPositionHistory, getPositionStats } from "../position-history.js";
6
8
  import { saveEquitySnapshot, readEquityHistory, computePnlMetrics, computeDailyPnl, aggregateWeekly, } from "../equity-tracker.js";
7
- const EXCHANGES = ["pacifica", "hyperliquid", "lighter", "aster"];
8
9
  function parseSince(since) {
9
10
  if (!since)
10
11
  return undefined;
@@ -16,6 +17,18 @@ function parseSince(since) {
16
17
  }
17
18
  return since;
18
19
  }
20
+ /**
21
+ * Exchange filter of a history subcommand: the ROOT `-e, --exchange`, only when given on the command
22
+ * line. Commander hands `-e` / `--exchange` to the root wherever it appears in argv, so a subcommand
23
+ * copy of the option was never set (the filter was silently dropped). The root's default venue is
24
+ * never used as a filter.
25
+ */
26
+ function cliExchangeFilter(cmd) {
27
+ let root = cmd;
28
+ while (root.parent)
29
+ root = root.parent;
30
+ return root.getOptionValueSource("exchange") === "cli" ? String(root.opts().exchange) : undefined;
31
+ }
19
32
  /** Parse period string (7d, 30d, 90d) to milliseconds. Returns undefined for "all" or missing. */
20
33
  function parsePeriodMs(period) {
21
34
  if (!period || period === "all")
@@ -32,14 +45,14 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
32
45
  // ── history list ──
33
46
  history
34
47
  .command("list")
35
- .description("Show recent executions")
36
- .option("-n, --limit <n>", "Number of records to show", "20")
37
- .option("-e, --exchange <exchange>", "Filter by exchange")
48
+ .description("Show recent executions — filter with the root -e <exchange>")
49
+ .option("--limit <n>", "Number of records to show", "20")
38
50
  .option("-s, --symbol <symbol>", "Filter by symbol")
39
51
  .option("-t, --type <type>", "Filter by type (market_order, limit_order, arb_entry, etc.)")
40
52
  .option("--since <date>", "Show records since date (ISO format or relative like '24h', '7d')")
41
53
  .option("--dry-run-only", "Show only dry-run simulations")
42
54
  .action(async (opts) => {
55
+ const exchangeFilter = cliExchangeFilter(history);
43
56
  await withJsonErrors(isJson(), async () => {
44
57
  // Parse relative dates
45
58
  let since = opts.since;
@@ -53,7 +66,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
53
66
  }
54
67
  const records = readExecutionLog({
55
68
  limit: parseInt(opts.limit),
56
- exchange: opts.exchange,
69
+ exchange: exchangeFilter,
57
70
  symbol: opts.symbol,
58
71
  type: opts.type,
59
72
  since,
@@ -143,14 +156,14 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
143
156
  // ── history positions ──
144
157
  history
145
158
  .command("positions")
146
- .description("Show position history (from event stream logging)")
147
- .option("-n, --limit <n>", "Number of records to show", "20")
148
- .option("-e, --exchange <exchange>", "Filter by exchange")
159
+ .description("Show position history (from event stream logging) — filter with the root -e <exchange>")
160
+ .option("--limit <n>", "Number of records to show", "20")
149
161
  .option("-s, --symbol <symbol>", "Filter by symbol")
150
162
  .option("--status <status>", "Filter by status (open, closed, updated)")
151
163
  .option("--since <date>", "Show records since date (ISO format or relative like '24h', '7d')")
152
164
  .option("--stats", "Show aggregate position stats instead of list")
153
165
  .action(async (opts) => {
166
+ const exchangeFilter = cliExchangeFilter(history);
154
167
  await withJsonErrors(isJson(), async () => {
155
168
  // Parse relative dates
156
169
  let since = opts.since;
@@ -164,7 +177,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
164
177
  }
165
178
  // Stats mode
166
179
  if (opts.stats) {
167
- const stats = getPositionStats({ exchange: opts.exchange, since });
180
+ const stats = getPositionStats({ exchange: exchangeFilter, since });
168
181
  if (isJson()) {
169
182
  return printJson(jsonOk(stats));
170
183
  }
@@ -206,7 +219,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
206
219
  // List mode
207
220
  const records = readPositionHistory({
208
221
  limit: parseInt(opts.limit),
209
- exchange: opts.exchange,
222
+ exchange: exchangeFilter,
210
223
  symbol: opts.symbol,
211
224
  status: opts.status,
212
225
  since,
@@ -330,16 +343,16 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
330
343
  // ── analytics pnl ──
331
344
  parent
332
345
  .command("pnl")
333
- .description("P&L analysis — trades, fees, funding income with daily breakdown")
334
- .option("-e, --exchange <exchanges>", "Comma-separated exchanges")
346
+ .description("P&L analysis — trades, fees, funding income with daily breakdown — filter with the root -e <exchange> (comma-separated)")
335
347
  .option("--period <duration>", "Time period: 7d, 30d, 90d, all (default: all)")
336
348
  .option("--since <period>", "Alias for --period")
337
- .option("-n, --limit <n>", "History limit per exchange", "200")
349
+ .option("--limit <n>", "History limit per exchange", "200")
338
350
  .action(async (opts) => {
351
+ const exchangeFilter = cliExchangeFilter(parent);
339
352
  await withJsonErrors(isJson(), async () => {
340
- const exchanges = opts.exchange
341
- ? opts.exchange.split(",").map(e => e.trim())
342
- : [...EXCHANGES];
353
+ const exchanges = exchangeFilter
354
+ ? exchangeFilter.split(",").map(e => e.trim())
355
+ : await listConfiguredAccountVenues();
343
356
  const period = opts.period ?? opts.since;
344
357
  const periodMs = parsePeriodMs(period);
345
358
  const sinceMs = periodMs ? Date.now() - periodMs : 0;
@@ -451,17 +464,17 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
451
464
  // ── analytics funding ──
452
465
  parent
453
466
  .command("funding")
454
- .description("Funding income analysis — cumulative, daily, per-arb-position breakdown")
455
- .option("-e, --exchange <exchanges>", "Comma-separated exchanges")
467
+ .description("Funding income analysis — cumulative, daily, per-arb-position breakdown — filter with the root -e <exchange> (comma-separated)")
456
468
  .option("-s, --symbol <symbol>", "Filter by symbol")
457
469
  .option("--period <duration>", "Time period: 7d, 30d, 90d, all (default: all)")
458
470
  .option("--daily", "Show daily funding breakdown")
459
- .option("-n, --limit <n>", "Funding history limit per exchange", "200")
471
+ .option("--limit <n>", "Funding history limit per exchange", "200")
460
472
  .action(async (opts) => {
473
+ const exchangeFilter = cliExchangeFilter(parent);
461
474
  await withJsonErrors(isJson(), async () => {
462
- const exchanges = opts.exchange
463
- ? opts.exchange.split(",").map(e => e.trim())
464
- : [...EXCHANGES];
475
+ const exchanges = exchangeFilter
476
+ ? exchangeFilter.split(",").map(e => e.trim())
477
+ : await listConfiguredAccountVenues();
465
478
  const periodMs = parsePeriodMs(opts.period);
466
479
  const sinceMs = periodMs ? Date.now() - periodMs : 0;
467
480
  const allFunding = [];
@@ -510,7 +523,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
510
523
  ? (allFunding[allFunding.length - 1].time - allFunding[0].time) / 86400000
511
524
  : 1;
512
525
  // Match funding to arb positions
513
- const arbState = loadArbState();
526
+ const arbState = loadArbState(networkOf(parent));
514
527
  const arbPositions = arbState?.positions ?? [];
515
528
  const arbFunding = new Map();
516
529
  for (const pos of arbPositions) {
@@ -611,17 +624,17 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
611
624
  // ── analytics report ──
612
625
  parent
613
626
  .command("report")
614
- .description("Full performance report (summary + pnl + funding)")
615
- .option("-e, --exchange <exchanges>", "Comma-separated exchanges")
627
+ .description("Full performance report (summary + pnl + funding) — filter with the root -e <exchange> (comma-separated)")
616
628
  .option("--since <period>", "Period: 24h, 7d, 30d")
617
629
  .action(async (opts) => {
630
+ const exchangeFilter = cliExchangeFilter(parent);
618
631
  await withJsonErrors(isJson(), async () => {
619
632
  const since = parseSince(opts.since);
620
633
  const stats = getExecutionStats(since);
621
634
  const records = readExecutionLog({ since });
622
- const exchanges = opts.exchange
623
- ? opts.exchange.split(",").map(e => e.trim())
624
- : [...EXCHANGES];
635
+ const exchanges = exchangeFilter
636
+ ? exchangeFilter.split(",").map(e => e.trim())
637
+ : await listConfiguredAccountVenues();
625
638
  // Volume from log
626
639
  let logVolume = 0;
627
640
  for (const r of records) {
@@ -634,24 +647,42 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
634
647
  let totalEquity = 0;
635
648
  let totalUPnl = 0;
636
649
  const symbolSet = new Set();
650
+ // A venue whose read failed is reported here and left out of the totals — never counted as 0.
651
+ const errors = {};
652
+ const errText = (e) => (e instanceof Error ? e.message : String(e));
637
653
  await Promise.allSettled(exchanges.map(async (ex) => {
654
+ let adapter;
638
655
  try {
639
- const adapter = await getAdapterForExchange(ex);
640
- const [balance, trades, funding] = await Promise.all([
641
- adapter.getBalance(),
642
- adapter.getTradeHistory(50).catch(() => []),
643
- adapter.getFundingPayments(50).catch(() => []),
644
- ]);
656
+ adapter = await getAdapterForExchange(ex);
657
+ }
658
+ catch (e) {
659
+ errors[`${ex}.adapter`] = errText(e);
660
+ return;
661
+ }
662
+ try {
663
+ const balance = await adapter.getBalance();
645
664
  totalEquity += Number(balance.equity);
646
665
  totalUPnl += Number(balance.unrealizedPnl);
647
- for (const t of trades) {
666
+ }
667
+ catch (e) {
668
+ errors[`${ex}.balance`] = errText(e);
669
+ return;
670
+ }
671
+ const [trades, funding] = await Promise.allSettled([adapter.getTradeHistory(50), adapter.getFundingPayments(50)]);
672
+ if (trades.status === "fulfilled") {
673
+ for (const t of trades.value) {
648
674
  totalFees += Number(t.fee);
649
675
  symbolSet.add(t.symbol);
650
676
  }
651
- for (const f of funding)
677
+ }
678
+ else
679
+ errors[`${ex}.trades`] = errText(trades.reason);
680
+ if (funding.status === "fulfilled") {
681
+ for (const f of funding.value)
652
682
  totalFunding += Number(f.payment);
653
683
  }
654
- catch { /* skip */ }
684
+ else
685
+ errors[`${ex}.funding`] = errText(funding.reason);
655
686
  }));
656
687
  const report = {
657
688
  period: opts.since ?? "all time",
@@ -678,6 +709,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
678
709
  ? (stats.totalTrades / Math.max(1, (Date.now() - new Date(records[records.length - 1]?.timestamp ?? Date.now()).getTime()) / 86400000)).toFixed(1)
679
710
  : "0",
680
711
  },
712
+ errors,
681
713
  };
682
714
  if (isJson())
683
715
  return printJson(jsonOk(report));
@@ -694,6 +726,8 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
694
726
  console.log(` Trading Fees: ${chalk.red(`-$${formatUsd(totalFees)}`)}`);
695
727
  console.log(` Funding Income: ${formatPnl(totalFunding)}`);
696
728
  console.log(` Net: ${formatPnl(totalFunding - totalFees)}`);
729
+ for (const [k, msg] of Object.entries(errors))
730
+ console.log(chalk.yellow(` ⚠ ${k} unavailable (left out of the totals): ${msg}`));
697
731
  console.log();
698
732
  });
699
733
  });
@@ -702,10 +736,10 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
702
736
  .command("compare")
703
737
  .description("Compare active arb positions — ROI, realized PnL, funding income side by side")
704
738
  .option("--period <duration>", "Funding lookup period: 7d, 30d, 90d, all (default: all)")
705
- .option("-n, --limit <n>", "Funding history limit per exchange", "200")
739
+ .option("--limit <n>", "Funding history limit per exchange", "200")
706
740
  .action(async (opts) => {
707
741
  await withJsonErrors(isJson(), async () => {
708
- const arbState = loadArbState();
742
+ const arbState = loadArbState(networkOf(parent));
709
743
  const positions = arbState?.positions ?? [];
710
744
  if (positions.length === 0) {
711
745
  if (isJson())
@@ -744,8 +778,12 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
744
778
  }
745
779
  catch { /* skip */ }
746
780
  }));
781
+ // Entries without a verified entry price (a bot leg the venue reported no fill price for)
782
+ // have no price PnL: listed apart, never priced at a guess.
783
+ const priced = positions.filter((p) => p.entryLongPrice !== null && p.entryShortPrice !== null);
784
+ const unpricedPositions = positions.filter(p => p.entryLongPrice === null || p.entryShortPrice === null).map(p => p.symbol);
747
785
  // Build comparison data
748
- const rows = positions.map(pos => {
786
+ const rows = priced.map(pos => {
749
787
  const daysHeld = Math.max(1, Math.round((Date.now() - new Date(pos.entryTime).getTime()) / 86400000));
750
788
  const longFunding = fundingByExSym.get(`${pos.longExchange}:${pos.symbol}`) ?? 0;
751
789
  const shortFunding = fundingByExSym.get(`${pos.shortExchange}:${pos.symbol}`) ?? 0;
@@ -790,6 +828,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
790
828
  period: opts.period ?? "all",
791
829
  positionCount: rows.length,
792
830
  positions: rows,
831
+ unpricedPositions,
793
832
  totals: {
794
833
  ...totals,
795
834
  roi: totals.notional > 0 ? (totals.totalPnl / totals.notional) * 100 : 0,
@@ -811,6 +850,8 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
811
850
  `${r.annualizedRoi >= 0 ? "+" : ""}${r.annualizedRoi.toFixed(1)}%`,
812
851
  ]);
813
852
  console.log(makeTable(["Symbol", "Long → Short", "Mode", "Held", "Funding", "Price PnL", "Total PnL", "ROI", "Ann.ROI"], tableRows));
853
+ if (unpricedPositions.length > 0)
854
+ console.log(chalk.gray(` No entry price recorded (not compared): ${unpricedPositions.join(", ")}\n`));
814
855
  console.log(chalk.white.bold(" Totals:"));
815
856
  console.log(` Funding Income: ${formatPnl(totals.funding)}`);
816
857
  console.log(` Price PnL: ${formatPnl(totals.pricePnl)}`);
@@ -866,10 +907,10 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
866
907
  parent
867
908
  .command("snapshot")
868
909
  .description("Take equity snapshot across all exchanges")
869
- .option("--exchanges <list>", "Comma-separated exchange list", EXCHANGES.join(","))
910
+ .option("--exchanges <list>", "Comma-separated exchange list (default: all with configured credentials)")
870
911
  .action(async (opts) => {
871
912
  await withJsonErrors(isJson(), async () => {
872
- const exchanges = opts.exchanges.split(",").map(e => e.trim());
913
+ const exchanges = opts.exchanges ? opts.exchanges.split(",").map(e => e.trim()) : await listConfiguredAccountVenues();
873
914
  const snaps = await takeSnapshot(getAdapterForExchange, exchanges);
874
915
  if (isJson()) {
875
916
  printJson(jsonOk({ snapshots: snaps }));
@@ -893,10 +934,10 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
893
934
  .command("track")
894
935
  .description("Continuously track equity (foreground)")
895
936
  .option("--interval <sec>", "Snapshot interval in seconds", "300")
896
- .option("--exchanges <list>", "Comma-separated exchange list", EXCHANGES.join(","))
937
+ .option("--exchanges <list>", "Comma-separated exchange list (default: all with configured credentials)")
897
938
  .action(async (opts) => {
898
939
  const intervalMs = parseInt(opts.interval) * 1000;
899
- const exchanges = opts.exchanges.split(",").map(e => e.trim());
940
+ const exchanges = opts.exchanges ? opts.exchanges.split(",").map(e => e.trim()) : await listConfiguredAccountVenues();
900
941
  console.log(chalk.cyan(`PnL tracker started — snapshot every ${opts.interval}s for [${exchanges.join(", ")}]`));
901
942
  console.log(chalk.gray("Press Ctrl+C to stop\n"));
902
943
  const controller = new AbortController();
@@ -907,8 +948,15 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
907
948
  console.log(`${chalk.gray(new Date().toLocaleTimeString())} Total equity: $${formatUsd(prevTotal)}`);
908
949
  while (!controller.signal.aborted) {
909
950
  await new Promise((resolve) => {
910
- const timer = setTimeout(resolve, intervalMs);
911
- controller.signal.addEventListener("abort", () => { clearTimeout(timer); resolve(); }, { once: true });
951
+ let timer;
952
+ const onAbort = () => { clearTimeout(timer); resolve(); };
953
+ // Remove the listener when the timer wins so it does not pile up on
954
+ // the controller's signal every snapshot interval (MaxListeners leak).
955
+ timer = setTimeout(() => {
956
+ controller.signal.removeEventListener("abort", onAbort);
957
+ resolve();
958
+ }, intervalMs);
959
+ controller.signal.addEventListener("abort", onAbort, { once: true });
912
960
  });
913
961
  if (controller.signal.aborted)
914
962
  break;
@@ -928,20 +976,20 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
928
976
  // ── perf (unified: daily/weekly/summary) ──
929
977
  parent
930
978
  .command("perf")
931
- .description("Performance breakdown — daily, weekly, or summary stats")
979
+ .description("Performance breakdown — daily, weekly, or summary stats — filter with the root -e <exchange>")
932
980
  .option("--period <period>", "daily, weekly, or summary", "daily")
933
- .option("--exchange <name>", "Single exchange filter")
934
981
  .option("--days <n>", "Number of days (daily mode)", "14")
935
982
  .option("--weeks <n>", "Number of weeks (weekly mode)", "8")
936
983
  .option("--since <period>", "Time range (e.g. 7d, 2w, 30d)")
937
984
  .action(async (opts) => {
985
+ const exchangeFilter = cliExchangeFilter(parent);
938
986
  await withJsonErrors(isJson(), async () => {
939
987
  const mode = opts.period.toLowerCase();
940
988
  const defaultSince = mode === "weekly"
941
989
  ? new Date(Date.now() - parseInt(opts.weeks) * 7 * 86400000)
942
990
  : new Date(Date.now() - parseInt(opts.days) * 86400000);
943
991
  const since = parseSinceDate(opts.since) ?? defaultSince;
944
- const snapshots = readEquityHistory({ exchange: opts.exchange, since });
992
+ const snapshots = readEquityHistory({ exchange: exchangeFilter, since });
945
993
  if (snapshots.length === 0) {
946
994
  if (isJson()) {
947
995
  printJson(jsonError("NO_DATA", "No equity snapshots found. Run 'perp history snapshot' or 'perp history track' first."));
@@ -952,12 +1000,12 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
952
1000
  return;
953
1001
  }
954
1002
  if (mode === "summary") {
955
- const metrics = computePnlMetrics(snapshots, opts.exchange);
1003
+ const metrics = computePnlMetrics(snapshots, exchangeFilter);
956
1004
  if (isJson()) {
957
1005
  printJson(jsonOk({ ...metrics, dailyReturns: undefined, dailyCount: metrics.dailyReturns.length }));
958
1006
  }
959
1007
  else {
960
- console.log(chalk.cyan.bold(`Performance Summary${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
1008
+ console.log(chalk.cyan.bold(`Performance Summary${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
961
1009
  console.log(` Period: ${metrics.period.from} → ${metrics.period.to} (${metrics.period.days} days)`);
962
1010
  console.log(` Total Return: ${formatPnl(metrics.totalReturn)} (${metrics.totalReturnPct >= 0 ? "+" : ""}${metrics.totalReturnPct.toFixed(2)}%)`);
963
1011
  console.log(` Peak Equity: $${formatUsd(metrics.peakEquity)}`);
@@ -976,14 +1024,14 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
976
1024
  }
977
1025
  return;
978
1026
  }
979
- const daily = computeDailyPnl(snapshots, opts.exchange);
1027
+ const daily = computeDailyPnl(snapshots, exchangeFilter);
980
1028
  if (mode === "weekly") {
981
1029
  const weekly = aggregateWeekly(daily);
982
1030
  if (isJson()) {
983
1031
  printJson(jsonOk({ weekly }));
984
1032
  return;
985
1033
  }
986
- console.log(chalk.cyan.bold(`Weekly PnL${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
1034
+ console.log(chalk.cyan.bold(`Weekly PnL${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
987
1035
  const rows = weekly.map(w => [w.date, `$${formatUsd(w.startEquity)}`, `$${formatUsd(w.endEquity)}`, formatPnl(w.pnl), `${w.pnlPct >= 0 ? "+" : ""}${w.pnlPct.toFixed(2)}%`]);
988
1036
  console.log(makeTable(["Week", "Start", "End", "PnL", "PnL %"], rows));
989
1037
  }
@@ -993,7 +1041,7 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
993
1041
  printJson(jsonOk({ daily }));
994
1042
  return;
995
1043
  }
996
- console.log(chalk.cyan.bold(`Daily PnL${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
1044
+ console.log(chalk.cyan.bold(`Daily PnL${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
997
1045
  const rows = daily.map(d => [d.date, `$${formatUsd(d.startEquity)}`, `$${formatUsd(d.endEquity)}`, formatPnl(d.pnl), `${d.pnlPct >= 0 ? "+" : ""}${d.pnlPct.toFixed(2)}%`]);
998
1046
  console.log(makeTable(["Date", "Start", "End", "PnL", "PnL %"], rows));
999
1047
  }
@@ -1,4 +1,10 @@
1
1
  import { Command } from "commander";
2
+ import { type Settings } from "../settings.js";
3
+ import { type StructuredError } from "../errors.js";
4
+ import { type VenueDefinition } from "../exchanges/venue.js";
5
+ import "../exchanges/venues/index.js";
6
+ import type { Network, VenueId } from "../exchanges/venue-types.js";
7
+ import { type ImportVerification } from "./agent-import.js";
2
8
  declare const ENV_FILE: string;
3
9
  export { ENV_FILE, loadEnvFile, setEnvVar };
4
10
  declare function loadEnvFile(): Record<string, string>;
@@ -13,23 +19,109 @@ export declare function validateKey(chain: "solana" | "evm" | "apikey", key: str
13
19
  valid: boolean;
14
20
  address: string;
15
21
  }>;
16
- export declare function registerInitCommand(program: Command): void;
22
+ /** Names (never values) of legacy private-key variables present in ~/.perp/.env. */
23
+ export declare function legacyEnvKeyNames(): string[];
24
+ /** Trading venues from the registry (no hardcoded list). */
25
+ export declare function setupVenues(): VenueDefinition[];
26
+ /** Resolve one venue id/alias for setup: must be a trading venue with an environment on `network`. */
27
+ export declare function resolveSetupVenue(input: string, network: Network): VenueId;
28
+ /** Parse a comma-separated venue list (ids or aliases), de-duplicated in input order. */
29
+ export declare function parseVenueList(csv: string, network: Network): VenueId[];
30
+ /** Parse `<venue>=<bps>` per-venue slippage overrides; each bps must fit that venue's maxSlippageBps. */
31
+ export declare function parseVenueSlippage(entries: string[], network: Network): {
32
+ [K in VenueId]?: number;
33
+ };
34
+ export interface SetupSettingsChange {
35
+ /** null = leave settings.owsActiveWallet unchanged (no master wallet on this computer). */
36
+ owsActiveWallet: string | null;
37
+ /** null = leave settings.defaultExchange unchanged. */
38
+ defaultExchange: VenueId | null;
39
+ /** null = leave settings.defaultSlippageBps unchanged. */
40
+ defaultSlippageBps: number | null;
41
+ /** Per-venue overrides to set (other venues' overrides are left alone). */
42
+ slippageBps: {
43
+ [K in VenueId]?: number;
44
+ };
45
+ }
46
+ /** Write the wizard's choices to ~/.perp/settings.json (metadata only — never secrets). */
47
+ export declare function applySetupSettings(change: SetupSettingsChange): Settings;
48
+ /** Real follow-up commands for the configured venues (all exist in this CLI). */
49
+ export declare function nextStepCommands(venues: VenueId[], network: Network): string[];
50
+ /** Plain-language slippage explanation (design §13.2, §13.10 #3). */
51
+ export declare function slippageExplanation(venues: VenueId[]): string[];
52
+ export type AgentStepResult = {
53
+ venue: VenueId;
54
+ status: "approved";
55
+ agentName: string;
56
+ } | {
57
+ venue: VenueId;
58
+ status: "imported";
59
+ agentName: string;
60
+ verification: ImportVerification;
61
+ } | {
62
+ venue: VenueId;
63
+ status: "skipped";
64
+ reason: string;
65
+ } | {
66
+ venue: VenueId;
67
+ status: "failed";
68
+ error: StructuredError;
69
+ };
70
+ /** Prompt I/O for the wizard (injectable for tests). askHidden never echoes. */
71
+ export interface Prompter {
72
+ ask(question: string): Promise<string>;
73
+ askHidden(question: string): Promise<string>;
74
+ }
17
75
  /**
18
- * Drive `perp setup` end-to-end without TTY. Required:
19
- * - --passphrase or OWS_PASSPHRASE env (3-path resolver)
20
- * Optional:
21
- * - --wallet-name (default: "main")
22
- * - --default-exchange (must be one of pacifica/hyperliquid/lighter/aster)
23
- *
24
- * Side effects:
25
- * 1. Creates an OWS wallet via createWallet(name, passphrase)
26
- * 2. Sets settings.owsActiveWallet (if unset) + settings.defaultExchange (if provided)
27
- *
28
- * Errors are returned as INVALID_PARAMS / PASSPHRASE_REQUIRED — never via
29
- * readline. JSON envelope is emitted on stdout when --json is present.
76
+ * Optional builder-fee step — offered only when settings `builder.<venue>` already holds a
77
+ * value for a chosen venue (builder fees ship off). Explains the fee and approves only after
78
+ * an explicit "y" (default No). Never configures a builder itself.
30
79
  */
31
- export declare function runNonInteractiveSetup(opts: {
80
+ export declare function stepBuilder(p: Prompter, venues: VenueId[], network: Network, master: string | null, getPassphrase: () => Promise<string>): Promise<void>;
81
+ /** Interactive `perp setup`. All prompts go through `p`; nothing secret is printed or written to .env. */
82
+ export declare function runInteractiveSetup(p: Prompter, passphraseFlag: string | undefined, preselectedNetwork: Network): Promise<void>;
83
+ export interface SetupOpts {
84
+ nonInteractive?: boolean;
85
+ wallet?: string;
32
86
  walletName?: string;
33
87
  passphrase?: string;
88
+ /** Root -n/--network (validated by networkOf). */
89
+ network: Network;
90
+ venues?: string;
91
+ defaultVenue?: string;
34
92
  defaultExchange?: string;
35
- }): Promise<void>;
93
+ slippageBps?: string;
94
+ slippage: string[];
95
+ approveAgents?: boolean;
96
+ yes?: boolean;
97
+ ondoSecretStdin?: boolean;
98
+ asterCanSpot?: boolean;
99
+ lighterApiKeyIndex?: string;
100
+ lighterRhApiKeyIndex?: string;
101
+ arcusAccountIndex?: string;
102
+ /** QFEX account UUID the imported key trades (--import-agents); it is the non-interactive confirmation. */
103
+ qfexAccountId?: string;
104
+ /** Venues whose key was created on the exchange website (keys read from stdin, in this order). */
105
+ importAgents?: string;
106
+ /** `<venue>=<address>` master / owner public addresses for --import-agents (repeatable). */
107
+ masterAddress: string[];
108
+ /** --import-agents venues the user accepts storing UNVERIFIED (pacifica has no read-only check). */
109
+ allowUnverified?: string;
110
+ lighterAccountIndex?: string;
111
+ lighterRhAccountIndex?: string;
112
+ }
113
+ export declare function registerInitCommand(program: Command): void;
114
+ /**
115
+ * Drive `perp setup` end-to-end without TTY.
116
+ *
117
+ * Master wallet: exactly one of --wallet <existing> or --wallet-name <new>.
118
+ * Passphrase (--passphrase / OWS_PASSPHRASE / stdin) is required to create a
119
+ * wallet or to sign agent approvals. With --ondo-secret-stdin, stdin carries
120
+ * the Ondo key, so the passphrase must come from the flag or env.
121
+ *
122
+ * Side effects, in order: validate everything → create wallet (if asked) →
123
+ * write settings (owsActiveWallet, defaultExchange, slippage) → register
124
+ * agents (only with --approve-agents --yes; a failure on one venue does not
125
+ * stop the others). Never deposits, withdraws, or trades; never writes .env.
126
+ */
127
+ export declare function runNonInteractiveSetup(opts: SetupOpts): Promise<void>;