perp-cli 0.12.17 → 0.14.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 (361) 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 +286 -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 +286 -0
  101. package/dist/commands/funds.d.ts +25 -0
  102. package/dist/commands/funds.js +939 -245
  103. package/dist/commands/history.js +72 -45
  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 +316 -337
  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 +219 -6
  166. package/dist/exchanges/aster.js +1023 -153
  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 +166 -0
  200. package/dist/exchanges/ondo/adapter.js +835 -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 +122 -0
  206. package/dist/exchanges/ondo/funds.js +290 -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 +288 -4
  218. package/dist/exchanges/pacifica.js +1013 -76
  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 +1383 -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 +34 -0
  270. package/dist/exchanges/venues/ondo.js +140 -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 +28 -0
  274. package/dist/exchanges/venues/qfex.js +132 -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 +820 -402
  290. package/dist/mcp-trade-guard.d.ts +16 -0
  291. package/dist/mcp-trade-guard.js +59 -0
  292. package/dist/pacifica/client.d.ts +41 -10
  293. package/dist/pacifica/client.js +167 -63
  294. package/dist/pacifica/constants.d.ts +0 -1
  295. package/dist/pacifica/constants.js +0 -5
  296. package/dist/pacifica/deposit.d.ts +30 -3
  297. package/dist/pacifica/deposit.js +119 -2
  298. package/dist/pacifica/faucet.d.ts +29 -0
  299. package/dist/pacifica/faucet.js +100 -0
  300. package/dist/pacifica/sign-tx.d.ts +15 -0
  301. package/dist/pacifica/sign-tx.js +41 -0
  302. package/dist/pacifica/types/account.d.ts +28 -4
  303. package/dist/pacifica/types/lake.d.ts +20 -5
  304. package/dist/pacifica/types/lake.js +4 -0
  305. package/dist/pacifica/types/market.d.ts +5 -0
  306. package/dist/pacifica/types/order.d.ts +4 -1
  307. package/dist/pacifica/types/position.d.ts +9 -1
  308. package/dist/plan-executor.d.ts +10 -5
  309. package/dist/plan-executor.js +165 -54
  310. package/dist/position-history.js +13 -0
  311. package/dist/rebalance.d.ts +26 -2
  312. package/dist/rebalance.js +86 -7
  313. package/dist/relay-swap.d.ts +232 -0
  314. package/dist/relay-swap.js +630 -0
  315. package/dist/risk.js +5 -1
  316. package/dist/secret-env.d.ts +15 -0
  317. package/dist/secret-env.js +36 -0
  318. package/dist/settings.d.ts +169 -6
  319. package/dist/settings.js +219 -38
  320. package/dist/signer/ows-evm.d.ts +13 -0
  321. package/dist/signer/ows-evm.js +22 -0
  322. package/dist/smart-order.d.ts +9 -0
  323. package/dist/smart-order.js +53 -8
  324. package/dist/strategies/dca.d.ts +6 -2
  325. package/dist/strategies/dca.js +66 -26
  326. package/dist/strategies/funding-arb.d.ts +11 -1
  327. package/dist/strategies/funding-arb.js +202 -89
  328. package/dist/strategies/grid.d.ts +31 -0
  329. package/dist/strategies/grid.js +89 -11
  330. package/dist/strategies/pending-stop.d.ts +8 -0
  331. package/dist/strategies/pending-stop.js +12 -0
  332. package/dist/strategies/split-order.d.ts +45 -17
  333. package/dist/strategies/split-order.js +157 -91
  334. package/dist/strategies/trailing-stop.d.ts +2 -1
  335. package/dist/strategies/trailing-stop.js +52 -6
  336. package/dist/strategies/twap.d.ts +6 -1
  337. package/dist/strategies/twap.js +39 -11
  338. package/dist/trade-validator.d.ts +22 -0
  339. package/dist/trade-validator.js +119 -15
  340. package/dist/utils/numeric.d.ts +46 -0
  341. package/dist/utils/numeric.js +79 -0
  342. package/dist/utils.d.ts +19 -0
  343. package/dist/utils.js +96 -19
  344. package/dist/withdraw-gate.d.ts +49 -0
  345. package/dist/withdraw-gate.js +131 -0
  346. package/package.json +15 -6
  347. package/skills/perp-cli/SKILL.md +142 -55
  348. package/skills/perp-cli/references/agent-operations.md +110 -56
  349. package/skills/perp-cli/references/commands.md +266 -71
  350. package/skills/perp-cli/references/strategies.md +34 -31
  351. package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
  352. package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
  353. package/skills/perp-cli/scripts/preflight.sh +21 -14
  354. package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
  355. package/skills/perp-cli/scripts/validate-arb.sh +31 -15
  356. package/vendor/lighter-signer/SHA256SUMS +2 -0
  357. package/vendor/lighter-signer/VERSION +8 -0
  358. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  359. package/vendor/lighter-signer/wasm_exec.js +575 -0
  360. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  361. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -1,12 +1,25 @@
1
+ import { listConfiguredAccountVenues } from "../config.js";
1
2
  import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch } from "../utils.js";
2
3
  import chalk from "chalk";
3
4
  import { hasPacificaSdk, isDexCapable } from "../exchanges/capabilities.js";
4
- const EXCHANGES = ["pacifica", "hyperliquid", "lighter", "aster"];
5
+ import { PerpError } from "../errors.js";
6
+ import { unsupported } from "../exchanges/trading-v2.js";
5
7
  function pac(adapter) {
6
8
  if (!hasPacificaSdk(adapter))
7
9
  throw new Error("Market settings are only available on Pacifica.");
8
10
  return adapter;
9
11
  }
12
+ /**
13
+ * Type / Trigger / Price / Size cells of an order row. A trigger order (stop / TP / SL) shows its
14
+ * trigger price; a market-type trigger has no limit price ("market"), and a position-level TP/SL
15
+ * (Pacifica: size 0 — it closes the whole position) shows "position" instead of 0.
16
+ */
17
+ export function orderCells(o) {
18
+ const trigger = o.triggerPrice !== null ? `$${formatUsd(o.triggerPrice)}` : "-";
19
+ const price = Number(o.price) > 0 ? `$${formatUsd(o.price)}` : o.triggerPrice !== null ? "market" : `$${formatUsd(o.price)}`;
20
+ const size = !(Number(o.size) > 0) && o.triggerPrice !== null ? "position" : o.size;
21
+ return [o.type, trigger, price, size];
22
+ }
10
23
  export function registerAccountCommands(program, getAdapter, isJson, getAdapterForExchange) {
11
24
  const account = program.command("account").description("Account commands");
12
25
  // ── balance alias → redirect to portfolio (renamed in v0.12) ──
@@ -52,21 +65,25 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
52
65
  .action(async (opts) => {
53
66
  const explicitExchange = program.getOptionValueSource?.("exchange") === "cli";
54
67
  if (!explicitExchange && getAdapterForExchange) {
68
+ const EXCHANGES = await listConfiguredAccountVenues();
55
69
  const allRows = [];
56
70
  const errors = {};
71
+ // One read per venue for both outputs: a venue that fails is an `errors` entry, never dropped.
72
+ const grouped = {};
57
73
  await Promise.all(EXCHANGES.map(async (ex) => {
58
74
  try {
59
75
  const adapter = await getAdapterForExchange(ex);
60
76
  const positions = await adapter.getPositions();
77
+ grouped[ex] = positions;
61
78
  for (const p of positions) {
62
79
  allRows.push([
63
80
  chalk.white.bold(p.symbol),
64
- chalk.gray(ex.slice(0, 3).toUpperCase()),
81
+ chalk.gray(ex),
65
82
  p.side === "long" ? chalk.green("LONG") : chalk.red("SHORT"),
66
83
  p.size,
67
84
  `$${formatUsd(p.entryPrice)}`,
68
85
  `$${formatUsd(p.markPrice)}`,
69
- p.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(p.liquidationPrice)}`,
86
+ p.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(p.liquidationPrice)}`,
70
87
  formatPnl(p.unrealizedPnl),
71
88
  `${p.leverage}x`,
72
89
  ]);
@@ -75,6 +92,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
75
92
  if (opts.hip3 && ex === "hyperliquid" && isDexCapable(adapter)) {
76
93
  const hip3 = await fetchHip3Data(adapter, a => a.getPositions());
77
94
  for (const { dex, items } of hip3) {
95
+ grouped[`hip3:${dex}`] = items;
78
96
  for (const p of items) {
79
97
  allRows.push([
80
98
  chalk.white.bold(p.symbol),
@@ -83,7 +101,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
83
101
  p.size,
84
102
  `$${formatUsd(p.entryPrice)}`,
85
103
  `$${formatUsd(p.markPrice)}`,
86
- p.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(p.liquidationPrice)}`,
104
+ p.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(p.liquidationPrice)}`,
87
105
  formatPnl(p.unrealizedPnl),
88
106
  `${p.leverage}x`,
89
107
  ]);
@@ -96,19 +114,6 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
96
114
  }
97
115
  }));
98
116
  if (isJson()) {
99
- const grouped = {};
100
- await Promise.all(EXCHANGES.map(async (ex) => {
101
- try {
102
- const adapter = await getAdapterForExchange(ex);
103
- grouped[ex] = await adapter.getPositions();
104
- if (opts.hip3 && ex === "hyperliquid" && isDexCapable(adapter)) {
105
- const hip3 = await fetchHip3Data(adapter, a => a.getPositions());
106
- for (const { dex, items } of hip3)
107
- grouped[`hip3:${dex}`] = items;
108
- }
109
- }
110
- catch { /* skip */ }
111
- }));
112
117
  return printJson(jsonOk({ exchanges: grouped, errors: Object.keys(errors).length > 0 ? errors : undefined }));
113
118
  }
114
119
  if (allRows.length === 0) {
@@ -149,7 +154,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
149
154
  p.size,
150
155
  `$${formatUsd(p.entryPrice)}`,
151
156
  `$${formatUsd(p.markPrice)}`,
152
- p.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(p.liquidationPrice)}`,
157
+ p.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(p.liquidationPrice)}`,
153
158
  formatPnl(p.unrealizedPnl),
154
159
  `${p.leverage}x`,
155
160
  ]);
@@ -164,7 +169,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
164
169
  p.size,
165
170
  `$${formatUsd(p.entryPrice)}`,
166
171
  `$${formatUsd(p.markPrice)}`,
167
- p.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(p.liquidationPrice)}`,
172
+ p.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(p.liquidationPrice)}`,
168
173
  formatPnl(p.unrealizedPnl),
169
174
  `${p.leverage}x`,
170
175
  ]);
@@ -178,21 +183,23 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
178
183
  .action(async (opts) => {
179
184
  const explicitExchange = program.getOptionValueSource?.("exchange") === "cli";
180
185
  if (!explicitExchange && getAdapterForExchange) {
186
+ const EXCHANGES = await listConfiguredAccountVenues();
181
187
  const allRows = [];
182
188
  const errors = {};
189
+ // One read per venue for both outputs: a venue that fails is an `errors` entry, never dropped.
190
+ const grouped = {};
183
191
  await Promise.all(EXCHANGES.map(async (ex) => {
184
192
  try {
185
193
  const adapter = await getAdapterForExchange(ex);
186
194
  const orders = await adapter.getOpenOrders();
195
+ grouped[ex] = orders;
187
196
  for (const o of orders) {
188
197
  allRows.push([
189
198
  o.orderId,
190
199
  chalk.white.bold(o.symbol),
191
- chalk.gray(ex.slice(0, 3).toUpperCase()),
200
+ chalk.gray(ex),
192
201
  o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
193
- o.type,
194
- `$${formatUsd(o.price)}`,
195
- o.size,
202
+ ...orderCells(o),
196
203
  o.filled,
197
204
  o.status,
198
205
  ]);
@@ -201,15 +208,14 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
201
208
  if (opts.hip3 && ex === "hyperliquid" && isDexCapable(adapter)) {
202
209
  const hip3 = await fetchHip3Data(adapter, a => a.getOpenOrders());
203
210
  for (const { dex, items } of hip3) {
211
+ grouped[`hip3:${dex}`] = items;
204
212
  for (const o of items) {
205
213
  allRows.push([
206
214
  o.orderId,
207
215
  chalk.white.bold(o.symbol),
208
216
  chalk.magenta(dex),
209
217
  o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
210
- o.type,
211
- `$${formatUsd(o.price)}`,
212
- o.size,
218
+ ...orderCells(o),
213
219
  o.filled,
214
220
  o.status,
215
221
  ]);
@@ -222,19 +228,6 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
222
228
  }
223
229
  }));
224
230
  if (isJson()) {
225
- const grouped = {};
226
- await Promise.all(EXCHANGES.map(async (ex) => {
227
- try {
228
- const adapter = await getAdapterForExchange(ex);
229
- grouped[ex] = await adapter.getOpenOrders();
230
- if (opts.hip3 && ex === "hyperliquid" && isDexCapable(adapter)) {
231
- const hip3 = await fetchHip3Data(adapter, a => a.getOpenOrders());
232
- for (const { dex, items } of hip3)
233
- grouped[`hip3:${dex}`] = items;
234
- }
235
- }
236
- catch { /* skip */ }
237
- }));
238
231
  return printJson(jsonOk({ exchanges: grouped, errors: Object.keys(errors).length > 0 ? errors : undefined }));
239
232
  }
240
233
  if (allRows.length === 0) {
@@ -243,7 +236,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
243
236
  console.log(chalk.gray(` ${ex}: ${msg}`));
244
237
  return;
245
238
  }
246
- console.log(makeTable(["ID", "Symbol", "Exch", "Side", "Type", "Price", "Size", "Filled", "Status"], allRows));
239
+ console.log(makeTable(["ID", "Symbol", "Exch", "Side", "Type", "Trigger", "Price", "Size", "Filled", "Status"], allRows));
247
240
  for (const [ex, msg] of Object.entries(errors))
248
241
  console.log(chalk.gray(` ${ex}: ${msg}`));
249
242
  return;
@@ -274,13 +267,11 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
274
267
  o.orderId,
275
268
  chalk.white.bold(o.symbol),
276
269
  o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
277
- o.type,
278
- `$${formatUsd(o.price)}`,
279
- o.size,
270
+ ...orderCells(o),
280
271
  o.filled,
281
272
  o.status,
282
273
  ]);
283
- console.log(makeTable(["ID", "Symbol", "Side", "Type", "Price", "Size", "Filled", "Status"], rows));
274
+ console.log(makeTable(["ID", "Symbol", "Side", "Type", "Trigger", "Price", "Size", "Filled", "Status"], rows));
284
275
  }
285
276
  for (const { dex, items } of hip3Orders) {
286
277
  console.log(chalk.magenta.bold(`\n HIP-3: ${dex}`));
@@ -288,13 +279,11 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
288
279
  o.orderId,
289
280
  chalk.white.bold(o.symbol),
290
281
  o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
291
- o.type,
292
- `$${formatUsd(o.price)}`,
293
- o.size,
282
+ ...orderCells(o),
294
283
  o.filled,
295
284
  o.status,
296
285
  ]);
297
- console.log(makeTable(["ID", "Symbol", "Side", "Type", "Price", "Size", "Filled", "Status"], dexRows));
286
+ console.log(makeTable(["ID", "Symbol", "Side", "Type", "Trigger", "Price", "Size", "Filled", "Status"], dexRows));
298
287
  }
299
288
  });
300
289
  account
@@ -313,13 +302,11 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
313
302
  o.orderId,
314
303
  chalk.white.bold(o.symbol),
315
304
  o.side === "buy" ? chalk.green("BUY") : chalk.red("SELL"),
316
- o.type,
317
- `$${formatUsd(o.price)}`,
318
- o.size,
305
+ ...orderCells(o),
319
306
  o.filled,
320
307
  o.status,
321
308
  ]);
322
- console.log(makeTable(["ID", "Symbol", "Side", "Type", "Price", "Size", "Filled", "Status"], rows));
309
+ console.log(makeTable(["ID", "Symbol", "Side", "Type", "Trigger", "Price", "Size", "Filled", "Status"], rows));
323
310
  });
324
311
  account
325
312
  .command("settings")
@@ -332,39 +319,39 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
332
319
  const settings = await sdk.getAccountSettings(adapter.publicKey);
333
320
  if (isJson())
334
321
  return printJson(jsonOk(settings));
335
- if (!Array.isArray(settings) || settings.length === 0) {
336
- console.log(chalk.gray("\n No market settings configured.\n"));
322
+ // GET /account/settings returns an object; per-market entries are in `margin_settings`
323
+ // (only markets changed from the default cross / max leverage are listed).
324
+ const marginSettings = settings?.margin_settings;
325
+ if (!Array.isArray(marginSettings)) {
326
+ throw new PerpError("EXCHANGE_ERROR", `Pacifica /account/settings returned no margin_settings list (got ${JSON.stringify(settings).slice(0, 160)})`, { exchange: "pacifica" });
327
+ }
328
+ if (marginSettings.length === 0) {
329
+ console.log(chalk.gray("\n No market settings configured (every market is at the default: cross margin, max leverage).\n"));
337
330
  return;
338
331
  }
339
- const rows = settings.map((s) => [
332
+ const rows = marginSettings.map((s) => [
340
333
  chalk.white.bold(s.symbol),
341
- s.margin_mode,
334
+ s.isolated ? "isolated" : "cross",
342
335
  `${s.leverage}x`,
343
336
  ]);
344
337
  console.log(makeTable(["Symbol", "Margin Mode", "Leverage"], rows));
345
338
  return;
346
339
  }
347
- // HL / Lighter: derive settings from open positions
348
- const positions = await adapter.getPositions();
349
- if (positions.length === 0) {
350
- if (isJson())
351
- return printJson(jsonOk([]));
352
- console.log(chalk.gray("\n No open positions — settings shown per active position.\n"));
353
- return;
340
+ // Every other venue: the per-market leverage / margin mode the venue itself exposes
341
+ // (adapter.getMarketSettings). No read path → the uniform CAPABILITY_UNSUPPORTED; an
342
+ // empty answer is never printed as "no settings".
343
+ const read = adapter.getMarketSettings;
344
+ if (typeof read !== "function") {
345
+ throw unsupported(adapter.name, "accountSettings", "the adapter has no per-market leverage / margin-mode read", `Set them explicitly per market: perp trade leverage <symbol> <n> [--isolated] -e ${adapter.name}`);
354
346
  }
355
- const settings = positions.map(p => ({
356
- symbol: p.symbol,
357
- leverage: p.leverage,
358
- margin_mode: "cross", // HL/Lighter default to cross
359
- }));
347
+ const rows = await read.call(adapter);
348
+ if (rows.length === 0) {
349
+ throw unsupported(adapter.name, "accountSettings", "the venue lists no per-market leverage / margin mode for this account (no market traded or configured yet)", `Set one: perp trade leverage <symbol> <n> [--isolated] -e ${adapter.name}`);
350
+ }
351
+ const settings = rows.map(r => ({ symbol: r.symbol, leverage: r.leverage, margin_mode: r.marginMode }));
360
352
  if (isJson())
361
353
  return printJson(jsonOk(settings));
362
- const rows = settings.map((s) => [
363
- chalk.white.bold(s.symbol),
364
- s.margin_mode,
365
- `${s.leverage}x`,
366
- ]);
367
- console.log(makeTable(["Symbol", "Margin Mode", "Leverage"], rows));
354
+ console.log(makeTable(["Symbol", "Margin Mode", "Leverage"], settings.map(s => [chalk.white.bold(s.symbol), s.margin_mode, `${s.leverage}x`])));
368
355
  });
369
356
  account
370
357
  .command("trades")
@@ -392,7 +379,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
392
379
  .command("funding-history")
393
380
  .alias("funding")
394
381
  .description("Personal funding payment history")
395
- .option("-n, --limit <n>", "Number of records", "200")
382
+ .option("--limit <n>", "Number of records", "200")
396
383
  .action(async (opts) => {
397
384
  const adapter = await getAdapter();
398
385
  const payments = await adapter.getFundingPayments(parseInt(opts.limit));
@@ -428,6 +415,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
428
415
  if (isJson())
429
416
  return printJson(jsonError("POSITION_NOT_FOUND", `No open position for ${sym}`));
430
417
  console.log(chalk.gray(`\n No open position for ${sym}.\n`));
418
+ process.exitCode = 1;
431
419
  return;
432
420
  }
433
421
  const positionNotional = Math.abs(Number(pos.size) * Number(pos.markPrice));
@@ -461,7 +449,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
461
449
  console.log(` Notional: $${formatUsd(positionNotional)}`);
462
450
  console.log(` Margin Required: $${formatUsd(marginRequired)}`);
463
451
  console.log(` Margin % Equity: ${marginPct.toFixed(2)}%`);
464
- console.log(` Liquidation: ${pos.liquidationPrice === "N/A" ? chalk.gray("N/A") : `$${formatUsd(pos.liquidationPrice)}`}`);
452
+ console.log(` Liquidation: ${pos.liquidationPrice === null ? chalk.gray("-") : `$${formatUsd(pos.liquidationPrice)}`}`);
465
453
  console.log(` Unrealized PnL: ${formatPnl(pos.unrealizedPnl)}`);
466
454
  console.log();
467
455
  }
@@ -476,6 +464,7 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
476
464
  }));
477
465
  }
478
466
  console.error(chalk.red(`Error: ${msg}`));
467
+ process.exitCode = 1;
479
468
  }
480
469
  });
481
470
  // ── PnL Report ──
@@ -607,29 +596,18 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
607
596
  .command("twap-orders")
608
597
  .description("Active TWAP orders")
609
598
  .action(async () => {
610
- let p;
611
- try {
612
- const adapter = await getAdapter();
613
- p = pac(adapter);
614
- }
615
- catch (err) {
616
- // pac() throws a generic "Market settings are only available on
617
- // Pacifica" — replace with a TWAP-specific message so HL/LT/Aster
618
- // users see what's actually unsupported. Codex QA matrix #1 fix.
619
- const orig = err instanceof Error ? err.message : String(err);
620
- const msg = orig.includes("only available on Pacifica")
621
- ? "TWAP orders are a Pacifica-only feature."
622
- : orig;
599
+ const adapter = await getAdapter();
600
+ if (!hasPacificaSdk(adapter)) {
601
+ const msg = "TWAP orders are a Pacifica-only feature.";
623
602
  if (isJson())
624
603
  return printJson(jsonError("NOT_SUPPORTED", msg, {
625
604
  details: { remediation: "Use 'perp -e pacifica account twap-orders'" },
626
605
  }));
627
606
  console.error(chalk.red(`\n ${msg}\n`));
628
- if (orig.includes("only available on Pacifica")) {
629
- console.error(chalk.gray(` Run: perp -e pacifica account twap-orders\n`));
630
- }
607
+ console.error(chalk.gray(` Run: perp -e pacifica account twap-orders\n`));
631
608
  return;
632
609
  }
610
+ const p = pac(adapter);
633
611
  const sdk = p.sdk;
634
612
  const orders = await sdk.getTWAPOrders(p.publicKey);
635
613
  if (isJson())
@@ -0,0 +1,114 @@
1
+ import type { AgentMeta, ArcusAgentMeta, OndoAgentMeta, QfexAgentMeta } from "../settings.js";
2
+ import type { Network, VenueId } from "../exchanges/venue-types.js";
3
+ /** Shown wherever an import is offered: what the imported key can and cannot do. */
4
+ export declare const IMPORT_SCOPE_NOTE = "Trading works with the imported key. Deposits, withdrawals, transfers, referral and agent approvals need the master wallet \u2014 do them on the exchange website, or add the master with `perp wallet import`.";
5
+ /**
6
+ * Printed on every import: an imported key is held in a local file protected only by file
7
+ * permissions (empty passphrase), and what it may do (withdraw, transfer) is decided on the
8
+ * exchange website when the key is created.
9
+ */
10
+ export declare const IMPORT_KEY_WARNING = "The imported key is stored with an empty passphrase \u2014 it is protected by file permissions only. Its permissions (trade / withdraw) are set on the exchange website: create API keys WITHOUT withdraw permission.";
11
+ export type ImportSecret = {
12
+ kind: "key";
13
+ key: string;
14
+ } | {
15
+ kind: "ondo";
16
+ keyId: string;
17
+ secret: string;
18
+ } | {
19
+ kind: "qfex";
20
+ publicKey: string;
21
+ secret: string;
22
+ };
23
+ /** The account a QFEX key was resolved to at import, shown for confirmation before anything is stored. */
24
+ export interface ImportAccountBinding {
25
+ accountId: string;
26
+ isPrimaryAccount: boolean;
27
+ method: string;
28
+ }
29
+ export interface ImportAgentParams {
30
+ venue: VenueId;
31
+ network: Network;
32
+ /** null → defaultImportAgentName(venue, network). */
33
+ agentName: string | null;
34
+ /** Master / owner public address. Required for aster, pacifica, arcus; optional (cross-checked) for hyperliquid. */
35
+ masterAddress: string | null;
36
+ /** Lighter-family account index (required) / Arcus subaccount (optional, cross-checked). */
37
+ accountIndex: number | null;
38
+ /** Lighter-family API key slot (required). */
39
+ apiKeyIndex: number | null;
40
+ /** Expiry shown on the website, recorded when the venue does not report it (30d / 1y / ISO). null = unknown. */
41
+ expiresIn: string | null;
42
+ /** Replace an existing IMPORTED record of the same name (its local key is deleted first). */
43
+ replace: boolean;
44
+ secret: ImportSecret;
45
+ /** QFEX: the account UUID the key should trade (--account-id); null = the user's primary account. Other venues: null. */
46
+ accountId: string | null;
47
+ /**
48
+ * QFEX: confirms the RESOLVED account before anything is stored (interactive y/N, or — without
49
+ * a terminal — only an explicit --account-id that equals it). Other venues never call it.
50
+ */
51
+ confirmAccount: ((binding: ImportAccountBinding) => Promise<boolean>) | null;
52
+ }
53
+ export interface ImportVerification {
54
+ status: "verified" | "unverified";
55
+ /** How the key was checked (or why it could not be). */
56
+ method: string;
57
+ }
58
+ export interface ImportAgentOutcome {
59
+ venue: VenueId;
60
+ network: Network;
61
+ agentName: string;
62
+ source: "imported";
63
+ masterAddress: string;
64
+ agentAddress: string | null;
65
+ publicKey: string | null;
66
+ accountIndex: number | null;
67
+ apiKeyIndex: number | null;
68
+ /** QFEX: the account UUID the key is bound to; null for every other venue. */
69
+ accountId: string | null;
70
+ /** ISO expiry, or null when neither the venue nor --expires-in gave one. */
71
+ expiresAt: string | null;
72
+ /** Where the secret now lives (OWS wallet name / keystore path) — never the secret. */
73
+ storage: string;
74
+ verification: ImportVerification;
75
+ /** Shown with every import (IMPORT_KEY_WARNING). */
76
+ warnings: string[];
77
+ }
78
+ /** Default record name for an imported key (distinct from the approve default `perp-cli-*`). */
79
+ export declare function defaultImportAgentName(venue: VenueId, network: Network): string;
80
+ /** OWS wallet holding an imported EVM / Solana / Ed25519 agent key. */
81
+ export declare function importedAgentWalletName(venue: "hyperliquid" | "aster" | "pacifica" | "arcus", agentName: string): string;
82
+ /** Prompt label for the venue's secret. */
83
+ export declare function importSecretLabel(venue: VenueId): string;
84
+ /**
85
+ * Number of stdin lines the venue's secret takes (ondo: key id + secret; qfex: public key + secret; others: the key).
86
+ * Used by `perp setup --non-interactive --import-agents` to split stdin.
87
+ */
88
+ export declare function importSecretLineCount(venue: VenueId): number;
89
+ /** Turn the venue's stdin lines into an ImportSecret. */
90
+ export declare function importSecretFromLines(venue: VenueId, lines: string[]): ImportSecret;
91
+ /** Read the secret: hidden TTY prompt, else piped stdin (ondo: 2 lines key id + secret; others: 1 line). */
92
+ export declare function readImportSecret(venue: VenueId): Promise<ImportSecret>;
93
+ /** Venues whose import cannot be checked against the venue (stored as "unverified"). */
94
+ export declare const UNVERIFIED_IMPORT_VENUES: readonly VenueId[];
95
+ /**
96
+ * M3: a batch import (perp setup --import-agents) must not carry the same key for two venues
97
+ * (a mis-ordered paste). Compares every textual form (0x / case / Ed25519 seed). The error
98
+ * names venues only — never the key.
99
+ */
100
+ export declare function assertDistinctImportSecrets(entries: ReadonlyArray<readonly [VenueId, ImportSecret]>): void;
101
+ /** Delete the local key + record of an imported agent (the key stays authorized on the venue). */
102
+ export declare function deleteImportedAgentLocal(venue: VenueId, network: Network, meta: AgentMeta | OndoAgentMeta | ArcusAgentMeta | QfexAgentMeta): Promise<{
103
+ keyRemoved: boolean;
104
+ }>;
105
+ /** A probed QFEX read permission: null = it could not be told (a never-funded account has no balance record to read). */
106
+ export declare function qfexPermissionText(p: boolean | null): string;
107
+ /**
108
+ * Import one website-created agent / API key. Verifies (where the venue allows) before storing;
109
+ * a refused verification stores nothing. Holds the venue's agent lock. Key material never
110
+ * appears in a thrown error.
111
+ */
112
+ export declare function importVenueAgent(p: ImportAgentParams): Promise<ImportAgentOutcome>;
113
+ /** Human summary of an import (public data only). */
114
+ export declare function printImportOutcome(o: ImportAgentOutcome): void;