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
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Master-wallet signers for the USDC bridge (`funds bridge send / exchange`, `funds rebalance
3
+ * execute --auto-bridge`).
4
+ *
5
+ * The master is either an OWS vault wallet (the supported secret store, SSOT Rule #3) or a raw
6
+ * private key (--private-key / wallets.json / legacy env). Addresses are read without decrypting
7
+ * anything (OWS: the vault's public account list; raw key: derived locally). Signing goes through
8
+ * the existing signers: OwsEvmSigner / OwsSolanaSigner for vault wallets (digest derived inside the
9
+ * signer), a local SigningKey / Keypair for raw keys.
10
+ */
11
+ import { type Transaction } from "ethers";
12
+ import { type Keypair, type VersionedTransaction } from "@solana/web3.js";
13
+ import type { CliCredentialOpts } from "./config.js";
14
+ import type { VenueId } from "./exchanges/venue-types.js";
15
+ import type { SolanaSigner } from "./signer/interface.js";
16
+ type TypedDataTypes = Record<string, Array<{
17
+ name: string;
18
+ type: string;
19
+ }>>;
20
+ /** EVM signer the bridge engine uses. OwsEvmSigner satisfies it; raw keys use pkEvmSigner. */
21
+ export interface BridgeEvmSigner {
22
+ getAddress(): string;
23
+ /** Signs an unsigned, chain-bound tx (digest derived inside); returns the 65-byte 0x signature. */
24
+ signTransaction(tx: Transaction): Promise<string>;
25
+ signTypedData(domain: Record<string, unknown>, types: TypedDataTypes, value: Record<string, unknown>): Promise<string>;
26
+ }
27
+ /** Signs with a raw EVM private key (legacy raw-key masters). */
28
+ export declare function pkEvmSigner(privateKey: string): BridgeEvmSigner;
29
+ /** Signs with a raw Solana secret key (base58 or JSON byte array). */
30
+ export declare function pkSolanaSigner(secret: string): Promise<SolanaSigner>;
31
+ export declare function isBridgeEvmSigner(x: unknown): x is BridgeEvmSigner;
32
+ export declare function isSolanaSigner(x: unknown): x is SolanaSigner;
33
+ /**
34
+ * EIP-712 signature from the bridge signer, checked locally: the recovered address must be the
35
+ * signer's own address before anything is submitted.
36
+ */
37
+ export declare function signTypedDataChecked(signer: BridgeEvmSigner, domain: Record<string, unknown>, types: TypedDataTypes, value: Record<string, unknown>, what: string): Promise<string>;
38
+ /**
39
+ * Add the master's signature to a v0 Solana transaction (plus any locally generated keypairs,
40
+ * e.g. a CCTP event-data account). OWS never exposes a keypair, so the serialized transaction is
41
+ * signed inside the vault and the signature attached. The signature is verified locally before
42
+ * the caller sends anything.
43
+ */
44
+ export declare function signVersionedSolanaTx(signer: SolanaSigner, tx: VersionedTransaction, extra?: Keypair[]): Promise<void>;
45
+ /** The venue whose master key signs on a bridge chain (Solana → Pacifica's, EVM → the given EVM venue). */
46
+ export declare function bridgeVenueForChain(chain: string, evmVenue?: VenueId): VenueId;
47
+ /**
48
+ * The master wallet's own PUBLIC address on a bridge chain. Nothing is decrypted: OWS reads the
49
+ * vault's public account list, a raw key is derived locally.
50
+ */
51
+ export declare function bridgeAddress(chain: string, venue: VenueId, opts: CliCredentialOpts): Promise<string>;
52
+ /** The master wallet's signer on a bridge chain (OWS vault signer, or a raw-key signer). */
53
+ export declare function loadBridgeSigner(chain: string, venue: VenueId, opts: CliCredentialOpts): Promise<BridgeEvmSigner | SolanaSigner>;
54
+ export {};
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Master-wallet signers for the USDC bridge (`funds bridge send / exchange`, `funds rebalance
3
+ * execute --auto-bridge`).
4
+ *
5
+ * The master is either an OWS vault wallet (the supported secret store, SSOT Rule #3) or a raw
6
+ * private key (--private-key / wallets.json / legacy env). Addresses are read without decrypting
7
+ * anything (OWS: the vault's public account list; raw key: derived locally). Signing goes through
8
+ * the existing signers: OwsEvmSigner / OwsSolanaSigner for vault wallets (digest derived inside the
9
+ * signer), a local SigningKey / Keypair for raw keys.
10
+ */
11
+ import { SigningKey, computeAddress, verifyTypedData } from "ethers";
12
+ import { PublicKey } from "@solana/web3.js";
13
+ import { PerpError } from "./errors.js";
14
+ import { LocalSolanaSigner } from "./signer/solana-local.js";
15
+ import { unsignedTxDigest } from "./signer/ows-evm.js";
16
+ /** Signs with a raw EVM private key (legacy raw-key masters). */
17
+ export function pkEvmSigner(privateKey) {
18
+ const key = new SigningKey(privateKey);
19
+ const address = computeAddress(key);
20
+ return {
21
+ getAddress: () => address,
22
+ signTransaction: async (tx) => key.sign(unsignedTxDigest(tx)).serialized,
23
+ signTypedData: async (domain, types, value) => {
24
+ const { TypedDataEncoder } = await import("ethers");
25
+ return key.sign(TypedDataEncoder.hash(domain, types, value)).serialized;
26
+ },
27
+ };
28
+ }
29
+ /** Signs with a raw Solana secret key (base58 or JSON byte array). */
30
+ export async function pkSolanaSigner(secret) {
31
+ const { parseSolanaKeypair } = await import("./config.js");
32
+ return new LocalSolanaSigner(parseSolanaKeypair(secret));
33
+ }
34
+ export function isBridgeEvmSigner(x) {
35
+ const o = x;
36
+ return typeof o === "object" && o !== null && typeof o.getAddress === "function"
37
+ && typeof o.signTransaction === "function" && typeof o.signTypedData === "function";
38
+ }
39
+ export function isSolanaSigner(x) {
40
+ const o = x;
41
+ return typeof o === "object" && o !== null && typeof o.getPublicKeyBase58 === "function";
42
+ }
43
+ /**
44
+ * EIP-712 signature from the bridge signer, checked locally: the recovered address must be the
45
+ * signer's own address before anything is submitted.
46
+ */
47
+ export async function signTypedDataChecked(signer, domain, types, value, what) {
48
+ const sig = await signer.signTypedData(domain, types, value);
49
+ const recovered = verifyTypedData(domain, types, value, sig);
50
+ if (recovered.toLowerCase() !== signer.getAddress().toLowerCase()) {
51
+ throw new PerpError("SIGNATURE_FAILED", `${what}: signature recovered ${recovered}, expected ${signer.getAddress()} — nothing was sent`, {
52
+ remediation: "Check the selected master wallet (perp wallet list); nothing was submitted",
53
+ });
54
+ }
55
+ return sig;
56
+ }
57
+ /**
58
+ * Add the master's signature to a v0 Solana transaction (plus any locally generated keypairs,
59
+ * e.g. a CCTP event-data account). OWS never exposes a keypair, so the serialized transaction is
60
+ * signed inside the vault and the signature attached. The signature is verified locally before
61
+ * the caller sends anything.
62
+ */
63
+ export async function signVersionedSolanaTx(signer, tx, extra = []) {
64
+ if (extra.length > 0)
65
+ tx.sign(extra);
66
+ const pubkey = new PublicKey(signer.getPublicKeyBase58());
67
+ const message = tx.message.serialize();
68
+ let sig;
69
+ if (signer instanceof LocalSolanaSigner) {
70
+ sig = await signer.signMessage(message);
71
+ }
72
+ else if (typeof signer.signTransactionBytes === "function") {
73
+ sig = signer.signTransactionBytes(tx.serialize());
74
+ }
75
+ else {
76
+ throw new PerpError("NO_SIGNER_AVAILABLE", "This Solana signer cannot sign transactions", {
77
+ remediation: "Use an OWS vault wallet (perp wallet use <name>) or a local Solana key",
78
+ });
79
+ }
80
+ const nacl = (await import("tweetnacl")).default;
81
+ if (sig.length !== 64 || !nacl.sign.detached.verify(message, sig, pubkey.toBytes())) {
82
+ throw new PerpError("SIGNATURE_FAILED", `Solana transaction signature from ${pubkey.toBase58()} did not verify — nothing was sent`, {
83
+ remediation: "Check the selected master wallet; the transaction was not submitted",
84
+ });
85
+ }
86
+ tx.addSignature(pubkey, sig);
87
+ }
88
+ /** The venue whose master key signs on a bridge chain (Solana → Pacifica's, EVM → the given EVM venue). */
89
+ export function bridgeVenueForChain(chain, evmVenue = "hyperliquid") {
90
+ return chain === "solana" ? "pacifica" : evmVenue;
91
+ }
92
+ async function resolveBridgeMaster(venue, opts) {
93
+ const { resolveOwsMaster, loadPrivateKey, isOwsKey } = await import("./config.js");
94
+ const ows = await resolveOwsMaster(venue, opts);
95
+ if (ows !== null)
96
+ return { kind: "ows", ...ows };
97
+ // Not an OWS wallet: a raw-key master (throws NO_SIGNER_AVAILABLE when none is configured).
98
+ const key = await loadPrivateKey(venue, opts.privateKey ?? undefined, opts.wallet ?? undefined);
99
+ if (isOwsKey(key)) {
100
+ throw new PerpError("NO_SIGNER_AVAILABLE", `The ${venue} master resolved to an OWS wallet reference that the vault does not serve`, {
101
+ remediation: "Select the master wallet explicitly: --ows <name> (or perp wallet use <name>)",
102
+ });
103
+ }
104
+ return { kind: "pk", key };
105
+ }
106
+ function owsAccountMissing(wallet, vm, e) {
107
+ return new PerpError("NO_SIGNER_AVAILABLE", `OWS wallet "${wallet}" has no ${vm} account usable for bridging (${e instanceof Error ? e.message : String(e)})`, {
108
+ remediation: `Use an OWS wallet with an ${vm} account (perp wallet list), or pass --ows <name>`,
109
+ });
110
+ }
111
+ /**
112
+ * The master wallet's own PUBLIC address on a bridge chain. Nothing is decrypted: OWS reads the
113
+ * vault's public account list, a raw key is derived locally.
114
+ */
115
+ export async function bridgeAddress(chain, venue, opts) {
116
+ const master = await resolveBridgeMaster(venue, opts);
117
+ if (master.kind === "ows") {
118
+ if (chain === "solana") {
119
+ const { OwsSolanaSigner } = await import("./signer/ows-solana.js");
120
+ try {
121
+ return OwsSolanaSigner.create(master.wallet, master.passphrase).getPublicKeyBase58();
122
+ }
123
+ catch (e) {
124
+ throw owsAccountMissing(master.wallet, "Solana", e);
125
+ }
126
+ }
127
+ const { OwsEvmSigner } = await import("./signer/ows-evm.js");
128
+ try {
129
+ return OwsEvmSigner.create(master.wallet, master.passphrase).getAddress();
130
+ }
131
+ catch (e) {
132
+ throw owsAccountMissing(master.wallet, "EVM", e);
133
+ }
134
+ }
135
+ if (chain === "solana")
136
+ return (await pkSolanaSigner(master.key)).getPublicKeyBase58();
137
+ return computeAddress(new SigningKey(master.key));
138
+ }
139
+ /** The master wallet's signer on a bridge chain (OWS vault signer, or a raw-key signer). */
140
+ export async function loadBridgeSigner(chain, venue, opts) {
141
+ const master = await resolveBridgeMaster(venue, opts);
142
+ if (master.kind === "ows") {
143
+ if (chain === "solana") {
144
+ const { OwsSolanaSigner } = await import("./signer/ows-solana.js");
145
+ try {
146
+ return OwsSolanaSigner.create(master.wallet, master.passphrase);
147
+ }
148
+ catch (e) {
149
+ throw owsAccountMissing(master.wallet, "Solana", e);
150
+ }
151
+ }
152
+ const { OwsEvmSigner } = await import("./signer/ows-evm.js");
153
+ try {
154
+ return OwsEvmSigner.create(master.wallet, master.passphrase);
155
+ }
156
+ catch (e) {
157
+ throw owsAccountMissing(master.wallet, "EVM", e);
158
+ }
159
+ }
160
+ return chain === "solana" ? pkSolanaSigner(master.key) : pkEvmSigner(master.key);
161
+ }
package/dist/cache.d.ts CHANGED
@@ -19,6 +19,9 @@ export declare function withCache<T>(key: string, ttlMs: number, fetcher: () =>
19
19
  */
20
20
  export declare function fetchAndCache<T>(key: string, ttlMs: number, fetcher: () => Promise<T>): Promise<T>;
21
21
  /**
22
- * Invalidate cache entries matching a prefix (e.g., "acct" after a trade).
22
+ * Monotonic counter bumped on every account-cache invalidation. Adapters that keep
23
+ * in-process account / position / order snapshots (Aster) store the epoch with the
24
+ * snapshot and treat a mismatch as stale, so `invalidateCache("acct")` also reaches them.
23
25
  */
26
+ export declare function accountCacheEpoch(): number;
24
27
  export declare function invalidateCache(keyPrefix?: string): void;
package/dist/cache.js CHANGED
@@ -77,7 +77,18 @@ export async function fetchAndCache(key, ttlMs, fetcher) {
77
77
  /**
78
78
  * Invalidate cache entries matching a prefix (e.g., "acct" after a trade).
79
79
  */
80
+ let _accountEpoch = 0;
81
+ /**
82
+ * Monotonic counter bumped on every account-cache invalidation. Adapters that keep
83
+ * in-process account / position / order snapshots (Aster) store the epoch with the
84
+ * snapshot and treat a mismatch as stale, so `invalidateCache("acct")` also reaches them.
85
+ */
86
+ export function accountCacheEpoch() {
87
+ return _accountEpoch;
88
+ }
80
89
  export function invalidateCache(keyPrefix) {
90
+ if (keyPrefix === undefined || keyPrefix === "acct" || "acct".startsWith(keyPrefix))
91
+ _accountEpoch++;
81
92
  try {
82
93
  const prefix = keyPrefix ? safeKey(keyPrefix) : "";
83
94
  const files = readdirSync(CACHE_DIR);
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Root-level CLI flags shared by every command (single source).
3
+ *
4
+ * `--dry-run` and `-n/--network` are defined ONLY on the root program. Commander
5
+ * (v13, non-positional options) lets the root consume a root option wherever it
6
+ * appears in argv — so a subcommand that re-declares `--dry-run` never sees it
7
+ * (the root swallows it) and silently runs live. Commands therefore never declare
8
+ * these options themselves; they read them with `isDryRun(cmd)` / `networkOf(cmd)`.
9
+ *
10
+ * Dry-run is default-deny: `installDryRunGuard(root)` rejects `--dry-run` with
11
+ * INVALID_PARAMS on every command that has not been explicitly marked with
12
+ * `supportsDryRun(cmd)`. A write command added later without dry-run handling
13
+ * therefore refuses `--dry-run` instead of executing live.
14
+ */
15
+ import { Command, Option } from "commander";
16
+ import type { Network } from "./exchanges/venue-types.js";
17
+ export declare const NETWORKS: readonly ["mainnet", "testnet"];
18
+ /** `-n, --network` option for the root program (validated: a typo is a usage error, never mainnet). */
19
+ export declare function networkOption(): Option;
20
+ /**
21
+ * The root-only safety flags (`-n/--network`, `--dry-run`) — declared ONCE on the root program
22
+ * (cli-program.ts) and by tests that mount a command subtree on a bare root.
23
+ */
24
+ export declare function addRootSafetyOptions(root: Command): Command;
25
+ /** True when the root `--dry-run` flag is set (wherever it appeared in argv). */
26
+ export declare function isDryRun(cmd: Command): boolean;
27
+ /** The validated `-n` network. Throws INVALID_PARAMS for anything but mainnet/testnet (no coercion). */
28
+ export declare function networkOf(cmd: Command): Network;
29
+ export declare function parseNetwork(value: unknown): Network;
30
+ /**
31
+ * Mark a command as honoring `--dry-run`: it must return a plan — `sent: false` — before
32
+ * SIGNING or SENDING anything. Contract (review L3): reading account state (balance /
33
+ * positions / open orders, needed to size closes and run the local risk check) may resolve
34
+ * the configured credentials — that can decrypt a key or prompt for the passphrase — but a
35
+ * dry-run never signs, never sends, and never writes venue state. Commands that can plan
36
+ * from public data alone (funds deposit/withdraw plans, `funds bridge send` with --sender
37
+ * and --recipient) load no key. Returns the command for chaining.
38
+ */
39
+ export declare function supportsDryRun<T extends Command>(cmd: T): T;
40
+ export declare function honorsDryRun(cmd: Command): boolean;
41
+ export declare function commandPath(cmd: Command): string;
42
+ /** Throws INVALID_PARAMS when `--dry-run` is set on a command that does not honor it. */
43
+ export declare function assertDryRunSupported(actionCommand: Command): void;
44
+ /**
45
+ * Root preAction hook: validates `-n` and enforces default-deny dry-run before any
46
+ * command action runs (so nothing is loaded or signed for a rejected invocation).
47
+ */
48
+ export declare function installDryRunGuard(root: Command): void;
49
+ /** Every command in the tree (depth-first), excluding the root. */
50
+ export declare function allCommands(root: Command): Command[];
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Root-level CLI flags shared by every command (single source).
3
+ *
4
+ * `--dry-run` and `-n/--network` are defined ONLY on the root program. Commander
5
+ * (v13, non-positional options) lets the root consume a root option wherever it
6
+ * appears in argv — so a subcommand that re-declares `--dry-run` never sees it
7
+ * (the root swallows it) and silently runs live. Commands therefore never declare
8
+ * these options themselves; they read them with `isDryRun(cmd)` / `networkOf(cmd)`.
9
+ *
10
+ * Dry-run is default-deny: `installDryRunGuard(root)` rejects `--dry-run` with
11
+ * INVALID_PARAMS on every command that has not been explicitly marked with
12
+ * `supportsDryRun(cmd)`. A write command added later without dry-run handling
13
+ * therefore refuses `--dry-run` instead of executing live.
14
+ */
15
+ import { Option } from "commander";
16
+ import { PerpError } from "./errors.js";
17
+ export const NETWORKS = ["mainnet", "testnet"];
18
+ /** `-n, --network` option for the root program (validated: a typo is a usage error, never mainnet). */
19
+ export function networkOption() {
20
+ return new Option("-n, --network <network>", "Network: mainnet or testnet").choices(NETWORKS).default("mainnet");
21
+ }
22
+ /**
23
+ * The root-only safety flags (`-n/--network`, `--dry-run`) — declared ONCE on the root program
24
+ * (cli-program.ts) and by tests that mount a command subtree on a bare root.
25
+ */
26
+ export function addRootSafetyOptions(root) {
27
+ return root
28
+ .addOption(networkOption())
29
+ .option("--dry-run", "Simulate without sending anything (only commands that support it; others reject --dry-run)");
30
+ }
31
+ function rootOf(cmd) {
32
+ let c = cmd;
33
+ while (c.parent)
34
+ c = c.parent;
35
+ return c;
36
+ }
37
+ /** True when the root `--dry-run` flag is set (wherever it appeared in argv). */
38
+ export function isDryRun(cmd) {
39
+ return rootOf(cmd).opts().dryRun === true;
40
+ }
41
+ /** The validated `-n` network. Throws INVALID_PARAMS for anything but mainnet/testnet (no coercion). */
42
+ export function networkOf(cmd) {
43
+ return parseNetwork(rootOf(cmd).opts().network);
44
+ }
45
+ export function parseNetwork(value) {
46
+ if (value === "mainnet" || value === "testnet")
47
+ return value;
48
+ throw new PerpError("INVALID_PARAMS", `Invalid network "${String(value)}" — expected one of: ${NETWORKS.join(", ")}`, {
49
+ remediation: "Pass -n mainnet or -n testnet (lowercase)",
50
+ });
51
+ }
52
+ const DRY_RUN_AWARE = new WeakSet();
53
+ /**
54
+ * Mark a command as honoring `--dry-run`: it must return a plan — `sent: false` — before
55
+ * SIGNING or SENDING anything. Contract (review L3): reading account state (balance /
56
+ * positions / open orders, needed to size closes and run the local risk check) may resolve
57
+ * the configured credentials — that can decrypt a key or prompt for the passphrase — but a
58
+ * dry-run never signs, never sends, and never writes venue state. Commands that can plan
59
+ * from public data alone (funds deposit/withdraw plans, `funds bridge send` with --sender
60
+ * and --recipient) load no key. Returns the command for chaining.
61
+ */
62
+ export function supportsDryRun(cmd) {
63
+ DRY_RUN_AWARE.add(cmd);
64
+ return cmd;
65
+ }
66
+ export function honorsDryRun(cmd) {
67
+ return DRY_RUN_AWARE.has(cmd);
68
+ }
69
+ export function commandPath(cmd) {
70
+ const parts = [];
71
+ for (let c = cmd; c && c.parent; c = c.parent)
72
+ parts.unshift(c.name());
73
+ return parts.join(" ");
74
+ }
75
+ /** Throws INVALID_PARAMS when `--dry-run` is set on a command that does not honor it. */
76
+ export function assertDryRunSupported(actionCommand) {
77
+ if (!isDryRun(actionCommand) || honorsDryRun(actionCommand))
78
+ return;
79
+ throw new PerpError("INVALID_PARAMS", `'perp ${commandPath(actionCommand)}' does not support --dry-run (it would run live)`, {
80
+ remediation: "Remove --dry-run. Commands that can simulate say 'supports --dry-run' in --help",
81
+ });
82
+ }
83
+ /**
84
+ * Root preAction hook: validates `-n` and enforces default-deny dry-run before any
85
+ * command action runs (so nothing is loaded or signed for a rejected invocation).
86
+ */
87
+ export function installDryRunGuard(root) {
88
+ root.hook("preAction", (_thisCommand, actionCommand) => {
89
+ networkOf(actionCommand);
90
+ assertDryRunSupported(actionCommand);
91
+ });
92
+ }
93
+ /** Every command in the tree (depth-first), excluding the root. */
94
+ export function allCommands(root) {
95
+ const out = [];
96
+ const walk = (c) => {
97
+ for (const sub of c.commands) {
98
+ out.push(sub);
99
+ walk(sub);
100
+ }
101
+ };
102
+ walk(root);
103
+ return out;
104
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The perp CLI Commander tree (root options + every command group), built without
3
+ * parsing argv — `src/index.ts` parses it; tests parse full argv through the same tree.
4
+ */
5
+ import { Command } from "commander";
6
+ import type { ExchangeAdapter } from "./exchanges/interface.js";
7
+ import "./exchanges/venues/index.js";
8
+ import { PerpError } from "./errors.js";
9
+ export interface CliProgram {
10
+ program: Command;
11
+ getAdapterForExchange: (rawExchange: string) => Promise<ExchangeAdapter>;
12
+ isJson: () => boolean;
13
+ }
14
+ export declare function assertNoArgvSecrets(root: Command): void;
15
+ /**
16
+ * `-n` used to be the record count of `history` / `account` subcommands (now `--limit`); it is the
17
+ * root network flag. A numeric `-n` / `--network` value on those commands is a migration error
18
+ * (INVALID_PARAMS "use --limit <n>") instead of the bare "invalid network" usage error. null = no such use.
19
+ */
20
+ export declare function numericNetworkFlagError(argv: readonly string[]): PerpError | null;
21
+ /** `perp --json` with no subcommand: the landing / usage document (static — no wallet or venue reads). */
22
+ export declare function landingData(program: Command, version: string): {
23
+ name: string;
24
+ version: string;
25
+ usage: string;
26
+ help: string;
27
+ commands: {
28
+ name: string;
29
+ description: string;
30
+ }[];
31
+ };
32
+ export declare function buildProgram(opts: {
33
+ defaultExchange: string;
34
+ version: string;
35
+ }): CliProgram;