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
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Arb state (per network, src/arb/state.ts) of spot-perp pairs opened by a bot (spot-perp-arb,
3
+ * funding-arb). The bot records its entries like `arb exec` does, so `arb status` confirms the
4
+ * pair and `arb close <SYM>` finds it. The network is the spot adapter's own (the bot's -n).
5
+ * An entry is matched on symbol + spot venue + perp venue.
6
+ */
7
+ import { type ArbPositionState } from "../../arb/state.js";
8
+ import { type SpotAdapter } from "../../exchanges/spot-interface.js";
9
+ /** A bot spot-perp pair: spot base symbol, spot venue, perp venue (bot adapter names). */
10
+ export interface SpotPerpPair {
11
+ symbol: string;
12
+ spotExchange: string;
13
+ perpExchange: string;
14
+ }
15
+ /** Arb-state symbol of a spot base: the perp name (UBTC → BTC), as `arb status` matches it. */
16
+ export declare function stateSymbol(base: string): string;
17
+ /** This pair's spot-perp entry in the arb state (same symbol, spot venue and perp venue), or undefined. */
18
+ export declare function stateEntryOf(spot: SpotAdapter, pos: SpotPerpPair): ArbPositionState | undefined;
19
+ /** A failed state write never undoes the trade: logged (with `tag`, e.g. "[SPA]") with the manual close command. */
20
+ export declare function stateWriteFailed(tag: string, what: string, pos: SpotPerpPair, err: unknown, log: (msg: string) => void): void;
21
+ /** The opened pair's actual legs: sizes filled, the venue-reported fill prices (null = not reported). */
22
+ export interface SpotPerpEntry extends SpotPerpPair {
23
+ id: string;
24
+ entryTime: number;
25
+ /** Annualized funding spread / rate at entry (%). */
26
+ entrySpread: number;
27
+ spotSize: number;
28
+ perpSize: number;
29
+ spotAvgPrice: number | null;
30
+ perpEntryPrice: number | null;
31
+ }
32
+ /**
33
+ * Record an opened pair as a spot-perp arb-state entry (a failed write is logged, never thrown —
34
+ * including the RISK_VIOLATION of an existing entry of the symbol on other venues / another
35
+ * mode, which is never overwritten).
36
+ */
37
+ export declare function recordSpotPerpEntry(spot: SpotAdapter, e: SpotPerpEntry, tag: string, log: (msg: string) => void): void;
38
+ /**
39
+ * Close recorded in the arb state: entry removed (remaining null) or its legs set to the
40
+ * still-hedged remainder. A pair the state does not hold for these venues (e.g. recovered from
41
+ * the venues) is left alone. A failed write is logged, never thrown.
42
+ */
43
+ export declare function recordSpotPerpClose(spot: SpotAdapter, pos: SpotPerpPair, remaining: string | null, tag: string, log: (msg: string) => void): void;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Arb state (per network, src/arb/state.ts) of spot-perp pairs opened by a bot (spot-perp-arb,
3
+ * funding-arb). The bot records its entries like `arb exec` does, so `arb status` confirms the
4
+ * pair and `arb close <SYM>` finds it. The network is the spot adapter's own (the bot's -n).
5
+ * An entry is matched on symbol + spot venue + perp venue.
6
+ */
7
+ import { addPosition, getPositions, removePositionEntry, updatePositionEntry } from "../../arb/state.js";
8
+ import { spotNetworkOf, spotPairSymbol } from "../../exchanges/spot-factory.js";
9
+ import { SPOT_PERP_TOKEN_MAP } from "../../exchanges/spot-interface.js";
10
+ import { getVenue } from "../../exchanges/venue.js";
11
+ /** Arb-state symbol of a spot base: the perp name (UBTC → BTC), as `arb status` matches it. */
12
+ export function stateSymbol(base) {
13
+ const upper = base.toUpperCase();
14
+ return SPOT_PERP_TOKEN_MAP[upper] ?? upper;
15
+ }
16
+ /** This pair's spot-perp entry in the arb state (same symbol, spot venue and perp venue), or undefined. */
17
+ export function stateEntryOf(spot, pos) {
18
+ const sym = stateSymbol(pos.symbol);
19
+ const spotId = getVenue(pos.spotExchange).id;
20
+ const perpId = getVenue(pos.perpExchange).id;
21
+ return getPositions(spotNetworkOf(spot)).find(p => p.mode === "spot-perp" && p.symbol.toUpperCase() === sym
22
+ && (p.spotExchange ?? p.longExchange) === spotId && p.shortExchange === perpId);
23
+ }
24
+ /** A failed state write never undoes the trade: logged (with `tag`, e.g. "[SPA]") with the manual close command. */
25
+ export function stateWriteFailed(tag, what, pos, err, log) {
26
+ log(` ${tag} WARNING: arb state ${what} failed for ${pos.symbol} (${err instanceof Error ? err.message : String(err)}) — \`perp arb status\` may not confirm it; close with: perp arb close ${stateSymbol(pos.symbol)} --spot-exch ${pos.spotExchange} --perp-exch ${pos.perpExchange}`);
27
+ }
28
+ /**
29
+ * Record an opened pair as a spot-perp arb-state entry (a failed write is logged, never thrown —
30
+ * including the RISK_VIOLATION of an existing entry of the symbol on other venues / another
31
+ * mode, which is never overwritten).
32
+ */
33
+ export function recordSpotPerpEntry(spot, e, tag, log) {
34
+ try {
35
+ const net = spotNetworkOf(spot);
36
+ const now = new Date(e.entryTime).toISOString();
37
+ addPosition(net, {
38
+ id: e.id, symbol: stateSymbol(e.symbol),
39
+ longExchange: getVenue(e.spotExchange).id, shortExchange: getVenue(e.perpExchange).id,
40
+ longSize: e.spotSize, shortSize: e.perpSize,
41
+ entryTime: now, entrySpread: e.entrySpread,
42
+ entryLongPrice: e.spotAvgPrice, entryShortPrice: e.perpEntryPrice,
43
+ accumulatedFunding: 0, lastCheckTime: now,
44
+ mode: "spot-perp", spotExchange: getVenue(e.spotExchange).id, spotSymbol: spotPairSymbol(getVenue(e.spotExchange), net, e.symbol),
45
+ });
46
+ }
47
+ catch (err) {
48
+ stateWriteFailed(tag, "entry", e, err, log);
49
+ }
50
+ }
51
+ /**
52
+ * Close recorded in the arb state: entry removed (remaining null) or its legs set to the
53
+ * still-hedged remainder. A pair the state does not hold for these venues (e.g. recovered from
54
+ * the venues) is left alone. A failed write is logged, never thrown.
55
+ */
56
+ export function recordSpotPerpClose(spot, pos, remaining, tag, log) {
57
+ try {
58
+ const entry = stateEntryOf(spot, pos);
59
+ if (entry === undefined)
60
+ return;
61
+ // Keyed by symbol + venues + mode: never another pair of the same symbol.
62
+ if (remaining === null)
63
+ removePositionEntry(spotNetworkOf(spot), entry);
64
+ else
65
+ updatePositionEntry(spotNetworkOf(spot), entry, { longSize: Number(remaining), shortSize: Number(remaining) });
66
+ }
67
+ catch (err) {
68
+ stateWriteFailed(tag, remaining === null ? "removal" : "update", pos, err, log);
69
+ }
70
+ }
@@ -61,4 +61,10 @@ export interface Strategy {
61
61
  init(ctx: StrategyContext, snapshot: EnrichedSnapshot): Promise<void>;
62
62
  onTick(ctx: StrategyContext, snapshot: EnrichedSnapshot): Promise<StrategyAction[]>;
63
63
  onStop(ctx: StrategyContext): Promise<StrategyAction[]>;
64
+ /**
65
+ * true once the strategy has nothing left to do (e.g. DCA placed its --orders total): the
66
+ * engine runs onStop and ENDS the bot (never returns to monitoring). Absent = runs until an
67
+ * exit condition / risk limit / signal.
68
+ */
69
+ isDone?(ctx: StrategyContext): boolean;
64
70
  }
@@ -5,10 +5,15 @@ export interface ExchangeBalance {
5
5
  }
6
6
  export interface BotTuiState {
7
7
  phase: string;
8
- equity: number;
9
- peakEquity: number;
8
+ /** null = unknown (see the bot log for the reason) — never shown as $0. */
9
+ equity: number | null;
10
+ /** null = no baseline yet. */
11
+ peakEquity: number | null;
10
12
  dailyPnl: number;
13
+ /** Orders the venue reported as (partly) filled. */
11
14
  fills: number;
15
+ /** Orders sent, filled or resting. */
16
+ ordersPlaced: number;
12
17
  totalPnl: number;
13
18
  runtime: number;
14
19
  strategy: string;
@@ -64,13 +64,16 @@ export function BotDashboard({ initialState, onQuit, onPause, subscribe }) {
64
64
  onPause();
65
65
  }
66
66
  });
67
- const drawdown = state.peakEquity - state.equity;
68
- const drawdownPct = state.peakEquity > 0 ? (drawdown / state.peakEquity) * 100 : 0;
67
+ // Unknown equity / baseline → drawdown unknown (shown as "unknown", never $0).
68
+ const drawdown = state.equity !== null && state.peakEquity !== null ? state.peakEquity - state.equity : null;
69
+ const drawdownPct = drawdown !== null && state.peakEquity !== null && state.peakEquity > 0 ? (drawdown / state.peakEquity) * 100 : 0;
70
+ const usd = (v) => v === null ? "unknown" : `$${v.toFixed(2)}`;
71
+ const totalEquity = state.exchangeBalances !== undefined ? state.exchangeBalances.reduce((s, e) => s + parseFloat(e.equity), 0) : state.equity;
69
72
  const bidOrders = state.openOrders.filter((o) => o.side.toLowerCase() === "buy");
70
73
  const askOrders = state.openOrders.filter((o) => o.side.toLowerCase() === "sell");
71
74
  const hasMultiExchange = (state.exchangeBalances?.length ?? 0) > 1;
72
75
  const isMultiSymbol = state.symbol.toUpperCase() === "ALL";
73
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, color: "cyan", children: [state.strategy, " | ", state.symbol, " | ", state.exchange] }), _jsxs(Text, { color: "gray", children: ["Runtime: ", formatDuration(state.runtime), " | Tick: ", state.tick] })] }), _jsx(Box, { children: _jsx(Text, { bold: true, color: phaseColor(state.phase), children: phaseIndicator(state.phase) }) })] }), isMultiSymbol ? (_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Text, { children: ["Exchanges: ", _jsx(Text, { bold: true, color: "white", children: state.exchangeBalances?.length ?? 1 })] }), _jsxs(Text, { color: "gray", children: ["Positions: ", _jsx(Text, { bold: true, color: state.positions.length > 0 ? "yellow" : "white", children: state.positions.length })] }), _jsxs(Text, { color: "gray", children: ["Total Equity: ", _jsxs(Text, { bold: true, color: "white", children: ["$", (state.exchangeBalances?.reduce((s, e) => s + parseFloat(e.equity), 0) ?? state.equity).toFixed(2)] })] }), _jsxs(Text, { color: "gray", children: ["PnL: ", _jsxs(Text, { bold: true, color: state.totalPnl >= 0 ? "green" : "red", children: ["$", state.totalPnl.toFixed(2)] })] })] })) : (_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Text, { children: ["Price: ", _jsxs(Text, { bold: true, color: "white", children: ["$", state.price.toFixed(2)] })] }), _jsxs(Text, { color: "gray", children: ["Vol24h: ", _jsxs(Text, { color: "white", children: [state.volatility24h.toFixed(1), "%"] })] }), _jsxs(Text, { color: "gray", children: ["FR: ", _jsxs(Text, { color: state.fundingRate >= 0 ? "green" : "red", children: [(state.fundingRate * 100).toFixed(4), "%"] })] }), _jsxs(Text, { color: "gray", children: ["OI: ", _jsx(Text, { color: "white", children: state.openInterest })] })] })), _jsxs(Box, { marginTop: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Account" }), _jsxs(Text, { children: ["Equity: ", _jsxs(Text, { bold: true, color: "white", children: ["$", state.equity.toFixed(2)] }), _jsxs(Text, { color: "gray", children: [" (peak: $", state.peakEquity.toFixed(2), ")"] })] }), _jsxs(Text, { children: ["Daily P&L: ", _jsxs(Text, { bold: true, color: pnlColor(state.dailyPnl), children: ["$", state.dailyPnl.toFixed(2)] })] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: " " }), _jsxs(Text, { children: ["Drawdown: ", _jsxs(Text, { bold: true, color: drawdown > 0 ? "red" : "green", children: ["$", drawdown.toFixed(2), " (", drawdownPct.toFixed(1), "%)"] })] }), _jsxs(Text, { children: ["Fills: ", _jsx(Text, { bold: true, color: "white", children: state.fills }), _jsx(Text, { color: "gray", children: " | Total P&L: " }), _jsxs(Text, { bold: true, color: pnlColor(state.totalPnl), children: ["$", state.totalPnl.toFixed(2)] })] })] })] }), state.exchangeBalances && state.exchangeBalances.length > 1 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Exchange Balances" }), _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "gray", children: pad("Exchange", 16) }), _jsx(Text, { color: "gray", children: pad("Equity", 14) }), _jsx(Text, { color: "gray", children: "Available" })] }), state.exchangeBalances.map((eb, i) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "white", children: pad(eb.exchange, 16) }), _jsx(Text, { color: "white", children: pad(`$${parseFloat(eb.equity).toFixed(2)}`, 14) }), _jsxs(Text, { color: "gray", children: ["$", parseFloat(eb.available).toFixed(2)] })] }, i)))] })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Positions" }), state.positions.length === 0 ? (_jsx(Text, { color: "gray", children: " No open positions" })) : (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "row", children: [hasMultiExchange && _jsx(Text, { color: "gray", children: pad("Exchange", 14) }), _jsx(Text, { color: "gray", children: pad("Symbol", 10) }), _jsx(Text, { color: "gray", children: pad("Side", 6) }), _jsx(Text, { color: "gray", children: pad("Size", 12) }), _jsx(Text, { color: "gray", children: pad("Entry", 12) }), _jsx(Text, { color: "gray", children: pad("Mark", 12) }), _jsx(Text, { color: "gray", children: "uPnL" })] }), state.positions.map((p, i) => {
76
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, color: "cyan", children: [state.strategy, " | ", state.symbol, " | ", state.exchange] }), _jsxs(Text, { color: "gray", children: ["Runtime: ", formatDuration(state.runtime), " | Tick: ", state.tick] })] }), _jsx(Box, { children: _jsx(Text, { bold: true, color: phaseColor(state.phase), children: phaseIndicator(state.phase) }) })] }), isMultiSymbol ? (_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Text, { children: ["Exchanges: ", _jsx(Text, { bold: true, color: "white", children: state.exchangeBalances?.length ?? 1 })] }), _jsxs(Text, { color: "gray", children: ["Positions: ", _jsx(Text, { bold: true, color: state.positions.length > 0 ? "yellow" : "white", children: state.positions.length })] }), _jsxs(Text, { color: "gray", children: ["Total Equity: ", _jsx(Text, { bold: true, color: "white", children: usd(totalEquity) })] }), _jsxs(Text, { color: "gray", children: ["PnL: ", _jsxs(Text, { bold: true, color: state.totalPnl >= 0 ? "green" : "red", children: ["$", state.totalPnl.toFixed(2)] })] })] })) : (_jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Text, { children: ["Price: ", _jsxs(Text, { bold: true, color: "white", children: ["$", state.price.toFixed(2)] })] }), _jsxs(Text, { color: "gray", children: ["Vol24h: ", _jsxs(Text, { color: "white", children: [state.volatility24h.toFixed(1), "%"] })] }), _jsxs(Text, { color: "gray", children: ["FR: ", _jsxs(Text, { color: state.fundingRate >= 0 ? "green" : "red", children: [(state.fundingRate * 100).toFixed(4), "%"] })] }), _jsxs(Text, { color: "gray", children: ["OI: ", _jsx(Text, { color: "white", children: state.openInterest })] })] })), _jsxs(Box, { marginTop: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Account" }), _jsxs(Text, { children: ["Equity: ", _jsx(Text, { bold: true, color: "white", children: usd(state.equity) }), _jsxs(Text, { color: "gray", children: [" (peak: ", usd(state.peakEquity), ")"] })] }), _jsxs(Text, { children: ["Daily P&L: ", _jsxs(Text, { bold: true, color: pnlColor(state.dailyPnl), children: ["$", state.dailyPnl.toFixed(2)] })] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: " " }), _jsxs(Text, { children: ["Drawdown: ", _jsx(Text, { bold: true, color: drawdown === null ? "gray" : drawdown > 0 ? "red" : "green", children: drawdown === null ? "unknown" : `${usd(drawdown)} (${drawdownPct.toFixed(1)}%)` })] }), _jsxs(Text, { children: ["Orders: ", _jsx(Text, { bold: true, color: "white", children: state.ordersPlaced }), _jsx(Text, { color: "gray", children: " | Fills: " }), _jsx(Text, { bold: true, color: "white", children: state.fills }), _jsx(Text, { color: "gray", children: " | Total P&L: " }), _jsxs(Text, { bold: true, color: pnlColor(state.totalPnl), children: ["$", state.totalPnl.toFixed(2)] })] })] })] }), state.exchangeBalances && state.exchangeBalances.length > 1 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Exchange Balances" }), _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "gray", children: pad("Exchange", 16) }), _jsx(Text, { color: "gray", children: pad("Equity", 14) }), _jsx(Text, { color: "gray", children: "Available" })] }), state.exchangeBalances.map((eb, i) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "white", children: pad(eb.exchange, 16) }), _jsx(Text, { color: "white", children: pad(`$${parseFloat(eb.equity).toFixed(2)}`, 14) }), _jsxs(Text, { color: "gray", children: ["$", parseFloat(eb.available).toFixed(2)] })] }, i)))] })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Positions" }), state.positions.length === 0 ? (_jsx(Text, { color: "gray", children: " No open positions" })) : (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "row", children: [hasMultiExchange && _jsx(Text, { color: "gray", children: pad("Exchange", 14) }), _jsx(Text, { color: "gray", children: pad("Symbol", 10) }), _jsx(Text, { color: "gray", children: pad("Side", 6) }), _jsx(Text, { color: "gray", children: pad("Size", 12) }), _jsx(Text, { color: "gray", children: pad("Entry", 12) }), _jsx(Text, { color: "gray", children: pad("Mark", 12) }), _jsx(Text, { color: "gray", children: "uPnL" })] }), state.positions.map((p, i) => {
74
77
  const upnl = parseFloat(p.unrealizedPnl);
75
78
  return (_jsxs(Box, { flexDirection: "row", children: [hasMultiExchange && _jsx(Text, { color: "cyan", children: pad(p.exchange ?? "—", 14) }), _jsx(Text, { color: "white", children: pad(p.symbol, 10) }), _jsx(Text, { color: p.side.toLowerCase() === "long" ? "green" : "red", children: pad(p.side, 6) }), _jsx(Text, { color: "white", children: pad(p.size, 12) }), _jsx(Text, { color: "white", children: pad(p.entryPrice, 12) }), _jsx(Text, { color: "white", children: pad(p.markPrice, 12) }), _jsx(Text, { color: isNaN(upnl) ? "gray" : pnlColor(upnl), children: isNaN(upnl) ? "$—" : `$${upnl.toFixed(2)}` })] }, i));
76
79
  })] }))] }), _jsxs(Box, { marginTop: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", width: "50%", children: [_jsxs(Text, { color: "green", bold: true, children: ["Bids (", bidOrders.length, ")"] }), bidOrders.length === 0 ? (_jsx(Text, { color: "gray", children: " --" })) : (bidOrders.slice(0, 8).map((o, i) => (_jsxs(Text, { color: "green", children: [pad(o.price, 12), " ", pad(o.size, 10), " ", o.type] }, i))))] }), _jsxs(Box, { flexDirection: "column", width: "50%", children: [_jsxs(Text, { color: "red", bold: true, children: ["Asks (", askOrders.length, ")"] }), askOrders.length === 0 ? (_jsx(Text, { color: "gray", children: " --" })) : (askOrders.slice(0, 8).map((o, i) => (_jsxs(Text, { color: "red", children: [pad(o.price, 12), " ", pad(o.size, 10), " ", o.type] }, i))))] })] }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: state.strategyState.fundingTotal !== undefined ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: "cyan", bold: true, children: "Funding & Arb" }), _jsxs(Box, { flexDirection: "row", marginLeft: 2, children: [_jsx(Text, { color: "gray", children: "Funding Income: " }), _jsx(Text, { color: "white", children: String(state.strategyState.fundingTotal) }), _jsx(Text, { color: "gray", children: " Positions: " }), _jsx(Text, { color: "white", children: String(state.strategyState.arbPositions ?? 0) })] }), Array.isArray(state.strategyState.arbPositionDetails) &&
@@ -9,6 +9,45 @@
9
9
  * Handles USDC bridging between Solana ↔ Arbitrum ↔ Base ↔ HyperCore
10
10
  * for cross-exchange rebalancing in funding arb.
11
11
  */
12
+ import "./exchanges/venues/index.js";
13
+ import type { Network } from "./exchanges/venue-types.js";
14
+ import type { SolanaSigner } from "./signer/interface.js";
15
+ import { type BridgeEvmSigner } from "./bridge-signers.js";
16
+ /**
17
+ * What signs a bridge leg: a master-wallet signer (OWS vault signer or raw-key signer from
18
+ * bridge-signers.ts), or — for legacy callers — a raw private key string (EVM 0x hex, Solana
19
+ * base58 / JSON). An "ows:<name>" reference is not a key and is refused.
20
+ */
21
+ export type BridgeSignerInput = string | BridgeEvmSigner | SolanaSigner;
22
+ /**
23
+ * A USDC amount: preferably the user's decimal string (exact), or a number (legacy callers).
24
+ * Signed amounts are always derived from the exact decimal via usdcUnits() — never from float
25
+ * math. A number is read as its shortest round-trip decimal (String(n)); one with an exponent or
26
+ * more than 6 decimals is refused.
27
+ */
28
+ export type UsdcAmount = string | number;
29
+ /**
30
+ * Canonical USDC decimal string ("5", "5.25") of `amount`. INVALID_PARAMS for anything that is
31
+ * not a positive plain decimal with at most 6 decimals (USDC has 6).
32
+ */
33
+ export declare function parseUsdcAmount(amount: UsdcAmount, what?: string): string;
34
+ /** Exact USDC base units of `amount` (validated by parseUsdcAmount). */
35
+ export declare function usdcUnits(amount: UsdcAmount, what?: string): bigint;
36
+ /** Calldata of the exact USDC approval ensureUsdcAllowance sends (exported for tests). */
37
+ export declare function usdcApproveData(spender: string, amount: bigint): string;
38
+ /**
39
+ * Every route in this module is mainnet-only: the RPCs, USDC / CCTP contract
40
+ * addresses, Circle Iris, Relay and deBridge endpoints below are mainnet
41
+ * deployments with no testnet equivalent wired in. A testnet run must never
42
+ * sign or send through them (it would move real mainnet funds), so it throws
43
+ * NO_BRIDGE_ROUTE before any key is used.
44
+ */
45
+ export declare function assertBridgeNetwork(network: Network): void;
46
+ /**
47
+ * A bridge moves funds between two different chains. Same source and destination is a caller
48
+ * error, refused before any quote API is called or any key is used.
49
+ */
50
+ export declare function assertDistinctBridgeChains(srcChain: string, dstChain: string): void;
12
51
  export declare const CHAIN_IDS: {
13
52
  readonly solana: 7565164;
14
53
  readonly arbitrum: 42161;
@@ -56,6 +95,15 @@ export interface BridgeQuote {
56
95
  estimatedTime: number;
57
96
  gasIncluded: boolean;
58
97
  gasNote?: string;
98
+ /**
99
+ * A fee paid in the source chain's NATIVE token on top of the USDC amount (deBridge `fixFee`,
100
+ * sent as the tx value). `usd` is null when no price was read. null = the provider charges none.
101
+ */
102
+ nativeFee?: {
103
+ amount: string;
104
+ symbol: string;
105
+ usd: number | null;
106
+ } | null;
59
107
  raw: unknown;
60
108
  }
61
109
  export interface BridgeResult {
@@ -67,16 +115,62 @@ export interface BridgeResult {
67
115
  amountOut: number;
68
116
  receiveTxHash?: string;
69
117
  }
118
+ /**
119
+ * Solana-origin deBridge is refused: the create-tx answer is a full VersionedTransaction (lookup
120
+ * tables, several instructions) that this CLI cannot decode and check against the order it asked
121
+ * for, and SSOT forbids signing a payload blindly.
122
+ */
123
+ export declare function assertDebridgeSourceSupported(srcChain: string): void;
124
+ export interface DebridgeTxExpectation {
125
+ srcChain: string;
126
+ dstChain: string;
127
+ sender: string;
128
+ recipient: string;
129
+ /** USDC units that must leave the wallet (OrderCreation.giveAmount). */
130
+ giveAmount: bigint;
131
+ /** USDC units asked for on the destination (create-tx dstChainTokenOutAmount). */
132
+ takeAmount: bigint;
133
+ /** Quoted fixFee (native wei): tx.value may not exceed it. */
134
+ fixFee: bigint;
135
+ /** settings bridge.debridgeAffiliate fee, or null (then no affiliate fee may be attached). */
136
+ affiliate: {
137
+ feePercent: number;
138
+ feeRecipient: string;
139
+ } | null;
140
+ }
141
+ /**
142
+ * Verify a deBridge create-tx EVM transaction before anything is signed: pinned DlnSource target,
143
+ * createOrder / createSaltedOrder decoded, the give token / amount, take token / chain / amount,
144
+ * the receiver and destination order authority (the user's own address), source patch authority,
145
+ * no external call / permit / taker restriction, the affiliate fee, and value ≤ the quoted fixFee.
146
+ * Returns the verified { to, data, value }.
147
+ */
148
+ export declare function verifyDebridgeEvmTx(tx: Record<string, unknown>, x: DebridgeTxExpectation): Promise<{
149
+ to: string;
150
+ data: string;
151
+ value: bigint;
152
+ }>;
70
153
  /**
71
154
  * Get a bridge quote via deBridge DLN.
72
155
  */
73
- export declare function getDebridgeQuote(srcChain: string, dstChain: string, amountUsdc: number, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
156
+ export declare function getDebridgeQuote(srcChain: string, dstChain: string, amountUsdc: UsdcAmount, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
74
157
  /**
75
- * Execute a deBridge bridge transaction.
76
- * Returns the TX hash after signing and submitting.
158
+ * Execute a deBridge bridge transaction (EVM origin only). The create-tx answer is verified
159
+ * against the request (verifyDebridgeEvmTx) before the exact USDC approval and the order are
160
+ * signed. Returns the TX hash after signing and submitting.
77
161
  */
78
- export declare function executeDebridgeBridge(bridgeQuote: BridgeQuote, signerKey: string): Promise<BridgeResult>;
162
+ export declare function executeDebridgeBridge(network: Network, bridgeQuote: BridgeQuote, signerKey: BridgeSignerInput): Promise<BridgeResult>;
79
163
  export declare const CCTP_DOMAINS: Record<string, number>;
164
+ /**
165
+ * HyperCore → Solana is refused. The sendToEvmWithData action built below is EVM-only: it sends
166
+ * the recipient with addressEncoding "hex" and signs with signatureChainId = the destination's
167
+ * chain id. Hyperliquid documents addressEncoding "hex" | "base58" and signatureChainId as "the id
168
+ * of the chain used when signing" (hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/
169
+ * exchange-endpoint, read 2026-10-13) — a base58 Solana recipient sent as "hex", signed for the
170
+ * deBridge pseudo chain id 7565164, would not be what HyperCore expects. The Solana encoding is
171
+ * not implemented against documentation, so the route is refused before anything is signed.
172
+ */
173
+ export declare function assertCctpRouteSupported(srcChain: string, dstChain: string): void;
80
174
  /**
81
175
  * Get a CCTP V2 bridge quote. Supports EVM ↔ EVM, Solana ↔ EVM, and → HyperCore.
82
176
  *
@@ -87,15 +181,26 @@ export declare const CCTP_DOMAINS: Record<string, number>;
87
181
  * @param fast - If true, use fast finality (1000): ~1-2 min, $1-1.3 + $0.20 forwarding.
88
182
  * If false (default), use standard finality (2000): ~2-5 min, ~$0.20 forwarding.
89
183
  */
90
- export declare function getCctpQuote(srcChain: string, dstChain: string, amountUsdc: number, fast?: boolean): Promise<BridgeQuote>;
184
+ export declare function getCctpQuote(srcChain: string, dstChain: string, amount: UsdcAmount, fast?: boolean): Promise<BridgeQuote>;
91
185
  /**
92
186
  * Execute a CCTP V2 bridge. Routes to the appropriate implementation.
93
187
  *
94
188
  * @param fast - If true, use fast finality (1000): Circle auto-relays, no manual receiveMessage.
95
189
  * If false (default), use standard finality (2000): cheaper but requires manual relay.
96
190
  */
97
- export declare function executeCctpBridge(srcChain: string, dstChain: string, amountUsdc: number, signerKey: string, recipientAddress: string, dstSignerKey?: string, // EVM key for receiveMessage (Solana→EVM) or Solana key for receiveMessage (EVM→Solana)
191
+ export declare function executeCctpBridge(network: Network, srcChain: string, dstChain: string, amount: UsdcAmount, signerKey: BridgeSignerInput, recipientAddress: string, dstSignerKey?: BridgeSignerInput, // destination-chain signer for receiveMessage (EVM→Solana standard finality)
98
192
  fast?: boolean): Promise<BridgeResult>;
193
+ /**
194
+ * After an EVM → Solana standard-finality burn: wait for Circle's attestation, then mint on
195
+ * Solana with receiveMessage. Returns the mint signature. Timeout or a failed / unconfirmed
196
+ * receiveMessage throws ORDER_PENDING carrying the burn tx hash and the Iris URL.
197
+ * `opts` exists for tests (poll count / interval, receiveMessage implementation).
198
+ */
199
+ export declare function completeEvmToSolanaMint(srcDomain: number, burnTxHash: string, recipientAddress: string, payer: BridgeSignerInput, opts?: {
200
+ attempts: number;
201
+ intervalMs: number;
202
+ receive: typeof executeSolanaReceiveMessage;
203
+ }): Promise<string>;
99
204
  /**
100
205
  * Call receiveMessage on Solana MessageTransmitter V2 to complete an EVM→Solana bridge.
101
206
  * This mints USDC on Solana after the attestation is ready.
@@ -103,28 +208,24 @@ fast?: boolean): Promise<BridgeResult>;
103
208
  export declare function executeSolanaReceiveMessage(messageHex: string, // "0x..." CCTP message from Iris API
104
209
  attestationHex: string, // "0x..." attestation from Iris API
105
210
  recipientAddress: string, // Solana wallet pubkey (base58)
106
- payerKey: string): Promise<string>;
107
- export declare function getRelayQuote(srcChain: string, dstChain: string, amountUsdc: number, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
108
- export declare function executeRelayBridge(bridgeQuote: BridgeQuote, signerKey: string): Promise<BridgeResult>;
109
- /**
110
- * Get the best bridge quote. Strategy:
111
- * - CCTP primary ($0 fee) for all routes: Solana↔EVM, EVM↔EVM, →HyperCore
112
- * - Relay + deBridge DLN in parallel, pick cheapest
113
- */
211
+ payerKey: BridgeSignerInput): Promise<string>;
212
+ export declare function getRelayQuote(srcChain: string, dstChain: string, amount: UsdcAmount, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
114
213
  /**
115
- * Get quotes from ALL available providers in parallel.
116
- * Returns sorted by amountOut (best first).
214
+ * Execute a verified Relay USDC quote with the master's EVM signer (OWS vault signer or a raw
215
+ * key). Only the verified approve (exact amount, pinned depository) + deposit are signed — never
216
+ * an unlimited approval, never an unchecked target.
117
217
  */
118
- export declare function getAllQuotes(srcChain: string, dstChain: string, amountUsdc: number, senderAddress: string, recipientAddress: string): Promise<BridgeQuote[]>;
218
+ export declare function executeRelayBridge(network: Network, bridgeQuote: BridgeQuote, signerKey: BridgeSignerInput): Promise<BridgeResult>;
219
+ export declare function getAllQuotes(srcChain: string, dstChain: string, amount: UsdcAmount, senderAddress: string, recipientAddress: string): Promise<BridgeQuote[]>;
119
220
  /**
120
221
  * Get the best quote across all providers.
121
222
  */
122
- export declare function getBestQuote(srcChain: string, dstChain: string, amountUsdc: number, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
223
+ export declare function getBestQuote(srcChain: string, dstChain: string, amount: UsdcAmount, senderAddress: string, recipientAddress: string): Promise<BridgeQuote>;
123
224
  /**
124
225
  * Execute a bridge using the specified or best available provider.
125
226
  * @param provider - Optional: force a specific provider ("cctp" | "relay" | "debridge")
126
227
  */
127
- export declare function executeBestBridge(srcChain: string, dstChain: string, amountUsdc: number, signerKey: string, senderAddress: string, recipientAddress: string, dstSignerKey?: string, // Optional EVM key for manual receiveMessage (standard finality)
228
+ export declare function executeBestBridge(network: Network, srcChain: string, dstChain: string, amount: UsdcAmount, signerKey: BridgeSignerInput, senderAddress: string, recipientAddress: string, dstSignerKey?: BridgeSignerInput, // Optional destination-chain signer for manual receiveMessage (standard finality)
128
229
  provider?: "cctp" | "relay" | "debridge", fast?: boolean): Promise<BridgeResult>;
129
230
  /**
130
231
  * Check bridge order status via deBridge.