perp-cli 0.12.15 → 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 +278 -31
  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 +74 -84
  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 +157 -682
  284. package/dist/jobs.d.ts +84 -6
  285. package/dist/jobs.js +239 -41
  286. package/dist/landing.d.ts +14 -0
  287. package/dist/landing.js +36 -0
  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 +338 -134
  348. package/skills/perp-cli/references/agent-operations.md +181 -92
  349. package/skills/perp-cli/references/commands.md +475 -132
  350. package/skills/perp-cli/references/strategies.md +44 -38
  351. package/skills/perp-cli/scripts/arb-monitor.sh +22 -17
  352. package/skills/perp-cli/scripts/funding-analysis.sh +20 -10
  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 +33 -16
  356. package/vendor/lighter-signer/SHA256SUMS +2 -0
  357. package/vendor/lighter-signer/VERSION +8 -0
  358. package/vendor/lighter-signer/lighter-signer.wasm +0 -0
  359. package/vendor/lighter-signer/wasm_exec.js +575 -0
  360. package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
  361. package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import type { ExchangeAdapter } from "../exchanges/index.js";
3
+ import "../exchanges/venues/index.js";
3
4
  export declare function registerArbCommands(program: Command, isJson: () => boolean, getAdapterForExchange?: (exchange: string) => Promise<ExchangeAdapter>): void;
4
5
  export interface PriceSnapshot {
5
6
  symbol: string;
@@ -26,6 +27,7 @@ export declare function handleRates(isJson: () => boolean, opts: {
26
27
  all?: boolean;
27
28
  minSpread: string;
28
29
  top?: string;
30
+ includeUnverified?: boolean;
29
31
  }): Promise<void>;
30
32
  export declare function handleBasisScan(isJson: () => boolean, opts: {
31
33
  minBasis: string;
@@ -37,7 +39,7 @@ export declare function handleDexScan(isJson: () => boolean, opts: {
37
39
  includeNative: boolean;
38
40
  top: string;
39
41
  }): Promise<void>;
40
- export declare function handleCompare(isJson: () => boolean, symbol: string): Promise<void>;
42
+ export declare function handleCompare(isJson: () => boolean, symbol: string, includeUnverified?: boolean): Promise<void>;
41
43
  export declare function handleFundingHistory(isJson: () => boolean, opts: {
42
44
  symbol: string;
43
45
  hours: string;
@@ -1,8 +1,10 @@
1
1
  import { makeTable, formatUsd, formatPercent, formatPnl, printJson, jsonOk, withJsonErrors, logSettledRejections } from "../utils.js";
2
2
  import chalk from "chalk";
3
- import { annualizeRate, toHourlyRate, estimateHourlyFunding, annualizeHourlyRate } from "../funding.js";
3
+ import { toHourlyRate, annualizeHourlyRate, estimateHourlyFundingFromHourly } from "../funding.js";
4
4
  import { fetchAllFundingRates, fetchSymbolFundingRates, TOP_SYMBOLS, } from "../funding-rates.js";
5
5
  import { saveFundingSnapshot, getHistoricalRates, getCompoundedAnnualReturn, getExchangeCompoundingHours, } from "../funding-history.js";
6
+ import { getVenue, listVenuesWithRole, tryResolveVenueId } from "../exchanges/venue.js";
7
+ import "../exchanges/venues/index.js";
6
8
  import { fetchPacificaPrices, fetchHyperliquidMeta, fetchLighterOrderBookDetails, fetchLighterFundingRates, fetchPacificaPricesRaw, parsePacificaRaw, fetchHyperliquidAllMidsRaw, fetchLighterOrderBookDetailsRaw, } from "../shared-api.js";
7
9
  import { scanDexArb } from "../dex-asset-map.js";
8
10
  async function fetchPacificaRates() {
@@ -12,7 +14,6 @@ async function fetchPacificaRates() {
12
14
  symbol: p.symbol,
13
15
  fundingRate: p.funding,
14
16
  markPrice: p.mark,
15
- nextFunding: p.nextFunding ?? 0,
16
17
  }));
17
18
  }
18
19
  async function fetchHyperliquidRates() {
@@ -40,7 +41,6 @@ async function fetchAsterRates() {
40
41
  continue;
41
42
  const fundingRate = Number(p.lastFundingRate);
42
43
  const markPrice = Number(p.markPrice);
43
- const nextFunding = Number(p.nextFundingTime);
44
44
  if (!Number.isFinite(fundingRate) || !Number.isFinite(markPrice) || markPrice <= 0) {
45
45
  continue;
46
46
  }
@@ -49,7 +49,6 @@ async function fetchAsterRates() {
49
49
  symbol: rawSym.replace(/USDT$/, ""),
50
50
  fundingRate,
51
51
  markPrice,
52
- nextFunding: Number.isFinite(nextFunding) ? nextFunding : 0,
53
52
  });
54
53
  }
55
54
  return out;
@@ -237,8 +236,17 @@ function formatAvgRate(rate) {
237
236
  const color = annualPct > 0 ? chalk.red : annualPct < 0 ? chalk.green : chalk.white;
238
237
  return color(`${annualPct.toFixed(1)}%`);
239
238
  }
239
+ /** Short venue label: first alias (or id), upper-cased — e.g. PAC, HL, LT, AST, LRH, ONDO-PERPS. */
240
+ function venueAbbr(e) {
241
+ const id = tryResolveVenueId(e);
242
+ if (id === null)
243
+ return e.toUpperCase();
244
+ const def = getVenue(id);
245
+ return (def.aliases[0] ?? def.id).toUpperCase();
246
+ }
240
247
  function printSnapshotTable(snapshot) {
241
- const exAbbr = (e) => e === "pacifica" ? "PAC" : e === "hyperliquid" ? "HL" : "LT";
248
+ const exAbbr = venueAbbr;
249
+ const columns = listVenuesWithRole("marketData");
242
250
  if (snapshot.symbols.length === 0) {
243
251
  console.log(chalk.gray(" No funding rate data available.\n"));
244
252
  return;
@@ -272,23 +280,23 @@ function printSnapshotTable(snapshot) {
272
280
  }
273
281
  }
274
282
  const rows = snapshot.symbols.map(s => {
275
- const pacRate = s.rates.find(r => r.exchange === "pacifica");
276
- const hlRate = s.rates.find(r => r.exchange === "hyperliquid");
277
- const ltRate = s.rates.find(r => r.exchange === "lighter");
278
- const astRate = s.rates.find(r => r.exchange === "aster");
283
+ const rateOf = (id) => s.rates.find(r => r.exchange === id);
279
284
  const spreadColor = s.maxSpreadAnnual >= 30 ? chalk.green : s.maxSpreadAnnual >= 10 ? chalk.yellow : chalk.white;
280
- const bestRate = hlRate ?? pacRate ?? ltRate ?? astRate;
285
+ // Historical-average source preference: HL, PAC, LT, AST, then whichever venue quoted.
286
+ const bestRate = rateOf("hyperliquid") ?? rateOf("pacifica") ?? rateOf("lighter") ?? rateOf("aster") ?? s.rates[0];
281
287
  const trend = trendMap.get(s.symbol) ?? chalk.gray("-");
282
288
  return [
283
- chalk.white.bold(s.symbol), pacRate ? formatPercent(pacRate.fundingRate) : chalk.gray("-"),
284
- hlRate ? formatPercent(hlRate.fundingRate) : chalk.gray("-"), ltRate ? formatPercent(ltRate.fundingRate) : chalk.gray("-"),
285
- astRate ? formatPercent(astRate.fundingRate) : chalk.gray("-"),
289
+ chalk.white.bold(s.symbol),
290
+ ...columns.map(v => {
291
+ const r = rateOf(v.id);
292
+ return r ? formatPercent(r.fundingRate) : chalk.gray("-");
293
+ }),
286
294
  spreadColor(`${s.maxSpreadAnnual.toFixed(1)}%`), trend,
287
295
  s.maxSpreadAnnual >= 5 ? `${exAbbr(s.shortExchange)}>${exAbbr(s.longExchange)}` : chalk.gray("-"),
288
296
  formatAvgRate(bestRate?.historicalAvg?.avg8h), formatAvgRate(bestRate?.historicalAvg?.avg24h), formatAvgRate(bestRate?.historicalAvg?.avg7d),
289
297
  ];
290
298
  });
291
- console.log(makeTable(["Symbol", "Pacifica", "Hyperliquid", "Lighter", "Aster", "Spread", "24h", "Direction", "Avg 8h", "Avg 24h", "Avg 7d"], rows));
299
+ console.log(makeTable(["Symbol", ...columns.map(v => v.displayName), "Spread", "24h", "Direction", "Avg 8h", "Avg 24h", "Avg 7d"], rows));
292
300
  console.log(chalk.gray(`\n ${snapshot.symbols.length} symbols compared across exchanges.\n`));
293
301
  }
294
302
  function printFundingExchangeStatus(snapshot) {
@@ -299,7 +307,7 @@ function printFundingExchangeStatus(snapshot) {
299
307
  console.log(chalk.gray(` Exchange status: ${statuses.join(" ")}\n`));
300
308
  }
301
309
  function printDetailedComparison(comparison) {
302
- const exAbbr = (e) => e === "pacifica" ? "PAC" : e === "hyperliquid" ? "HL" : e === "lighter" ? "LT" : e === "aster" ? "AST" : e.toUpperCase();
310
+ const exAbbr = venueAbbr;
303
311
  console.log(chalk.cyan.bold(` ${comparison.symbol} Funding Rate Comparison\n`));
304
312
  console.log(` Mark Price: $${formatUsd(comparison.bestMarkPrice)}\n`);
305
313
  for (const r of comparison.rates) {
@@ -315,6 +323,13 @@ function printDetailedComparison(comparison) {
315
323
  }
316
324
  // registerFundingSubcommands removed — use 'arb scan --rates/--compare/--history/--positions' instead
317
325
  // ── Exported handler functions for use by arb-auto.ts scan routing ──
326
+ /** One-line stderr notice when rows of unverified-funding venues are shown (--include-unverified). */
327
+ function warnUnverifiedFunding(rates) {
328
+ const venues = [...new Set(rates.filter(r => !r.fundingVerified).map(r => r.exchange))];
329
+ if (venues.length === 0)
330
+ return;
331
+ process.stderr.write(`[warn] ${venues.join(", ")}: funding rates are UNVERIFIED (unit not confirmed against funding payments; annualized values overstate venues whose funding accrues only during market hours). Shown on request — not for trading decisions.\n`);
332
+ }
318
333
  export async function handleRates(isJson, opts) {
319
334
  const minSpread = parseFloat(opts.minSpread);
320
335
  let filterSymbols;
@@ -326,9 +341,15 @@ export async function handleRates(isJson, opts) {
326
341
  filterSymbols = TOP_SYMBOLS;
327
342
  if (!isJson())
328
343
  console.log(chalk.cyan(" Fetching funding rates from all exchanges...\n"));
329
- const snapshot = await fetchAllFundingRates({ symbols: filterSymbols, minSpread });
344
+ // With --include-unverified and no symbol filter, show every matched symbol: the default
345
+ // TOP_SYMBOLS list is crypto-only and would hide every market of an equity venue.
346
+ if (opts.includeUnverified === true && !opts.symbol && !opts.symbols)
347
+ filterSymbols = undefined;
348
+ const snapshot = await fetchAllFundingRates({ symbols: filterSymbols, minSpread, includeUnverified: opts.includeUnverified === true });
349
+ warnUnverifiedFunding(snapshot.symbols.flatMap(s => s.rates));
350
+ // Unverified rates are never written to the funding history (it feeds averages and bots).
330
351
  try {
331
- const allRates = snapshot.symbols.flatMap(s => s.rates);
352
+ const allRates = snapshot.symbols.flatMap(s => s.rates).filter(r => r.fundingVerified);
332
353
  if (allRates.length > 0)
333
354
  saveFundingSnapshot(allRates);
334
355
  }
@@ -467,10 +488,12 @@ export async function handleDexScan(isJson, opts) {
467
488
  console.log(chalk.gray(` A: OI>$1M B: OI>$100K C: OI>$10K D: OI<$10K (thin — high risk)`));
468
489
  console.log(chalk.gray(` Note: HIP-3 dexes charge 2x fees. Factor into net profitability.\n`));
469
490
  }
470
- export async function handleCompare(isJson, symbol) {
491
+ export async function handleCompare(isJson, symbol, includeUnverified = false) {
471
492
  if (!isJson())
472
493
  console.log(chalk.cyan(` Fetching funding rates for ${symbol.toUpperCase()}...\n`));
473
- const comparison = await fetchSymbolFundingRates(symbol);
494
+ const comparison = await fetchSymbolFundingRates(symbol, includeUnverified);
495
+ if (comparison)
496
+ warnUnverifiedFunding(comparison.rates);
474
497
  if (!comparison) {
475
498
  if (isJson())
476
499
  return printJson(jsonOk({ symbol: symbol.toUpperCase(), available: false }));
@@ -497,7 +520,7 @@ export async function handleFundingHistory(isJson, opts) {
497
520
  return printJson(jsonOk({ symbol, hours, startTime: startTime.toISOString(), endTime: endTime.toISOString(), rates: data }));
498
521
  }
499
522
  console.log(chalk.cyan.bold(` ${symbol} Funding Rate History (last ${hours}h)\n`));
500
- const exAbbr = (e) => e === "pacifica" ? "PAC" : e === "hyperliquid" ? "HL" : "LT";
523
+ const exAbbr = venueAbbr;
501
524
  let hasData = false;
502
525
  for (const ex of exchanges) {
503
526
  const rates = getHistoricalRates(symbol, ex, startTime, endTime);
@@ -519,16 +542,18 @@ export async function handleFundingPositions(isJson, getAdapterForExchange, opts
519
542
  console.log(chalk.cyan(" Fetching positions and funding rates...\n"));
520
543
  const results = [];
521
544
  const exchangeErrors = {};
545
+ const fundingUnknown = [];
522
546
  await Promise.all(targetExchanges.map(async (exchange) => {
523
547
  try {
524
548
  const adapter = await getAdapterForExchange(exchange);
525
549
  const [positions, markets, fp] = await Promise.all([adapter.getPositions(), adapter.getMarkets(), adapter.getFundingPayments(100).catch(() => [])]);
526
550
  if (positions.length === 0)
527
551
  return;
528
- const fm = new Map();
552
+ /* rate null = the venue reports no funding rate for the market (never read as 0) */ const fm = new Map();
529
553
  for (const m of markets) {
530
554
  const sym = m.symbol.toUpperCase().replace(/-PERP$/, "");
531
- fm.set(sym, { rate: Number(m.fundingRate) || 0, markPrice: Number(m.markPrice) || 0 });
555
+ const rate = m.fundingRate === null || !Number.isFinite(Number(m.fundingRate)) ? null : Number(m.fundingRate);
556
+ fm.set(sym, { rate, markPrice: Number(m.markPrice) || 0, fundingHours: m.fundingHours });
532
557
  }
533
558
  const dayAgo = Date.now() - 86400000;
534
559
  const af = new Map();
@@ -548,13 +573,18 @@ export async function handleFundingPositions(isJson, getAdapterForExchange, opts
548
573
  for (const pos of positions) {
549
574
  const sym = pos.symbol.toUpperCase().replace(/-PERP$/, "");
550
575
  const fd = fm.get(sym);
551
- const fr = fd?.rate ?? 0;
576
+ if (fd === undefined || fd.rate === null) {
577
+ fundingUnknown.push(`${exchange}:${sym}`);
578
+ continue;
579
+ }
580
+ const fr = fd.rate;
552
581
  const mk = Number(pos.markPrice) || fd?.markPrice || 0;
553
582
  const sz = Math.abs(Number(pos.size));
554
583
  const nu = sz * mk;
555
- const hr = toHourlyRate(fr, exchange);
556
- const ap = annualizeRate(fr, exchange);
557
- const hp = estimateHourlyFunding(fr, exchange, nu, pos.side);
584
+ const fh = fd ? fd.fundingHours : null; /* market basis first (§10.1) */
585
+ const hr = fh !== null ? fr / fh : toHourlyRate(fr, exchange);
586
+ const ap = annualizeHourlyRate(hr);
587
+ const hp = estimateHourlyFundingFromHourly(hr, nu, pos.side);
558
588
  const a = af.get(sym);
559
589
  results.push({ exchange, symbol: sym, side: pos.side, size: pos.size, entryPrice: pos.entryPrice, markPrice: pos.markPrice, unrealizedPnl: pos.unrealizedPnl, leverage: pos.leverage, notionalUsd: nu, fundingRate: fr, hourlyRate: hr, annualPct: ap, hourlyPayment: hp, dailyPayment: hp * 24, actualReceived24h: a?.received ?? 0, actualPaid24h: a?.paid ?? 0, actualNet24h: (a?.received ?? 0) - (a?.paid ?? 0) });
560
590
  }
@@ -565,8 +595,8 @@ export async function handleFundingPositions(isJson, getAdapterForExchange, opts
565
595
  }));
566
596
  if (results.length === 0) {
567
597
  if (isJson())
568
- return printJson(jsonOk({ positions: [], totals: { predicted: { hourly: 0, daily: 0 }, actual24h: { net: 0 }, notionalUsd: 0 }, errors: exchangeErrors }));
569
- console.log(chalk.gray(" No open positions.\n"));
598
+ return printJson(jsonOk({ positions: [], totals: { predicted: { hourly: 0, daily: 0 }, actual24h: { net: 0 }, notionalUsd: 0 }, fundingUnknown, errors: exchangeErrors }));
599
+ console.log(chalk.gray(fundingUnknown.length > 0 ? ` No positions with a published funding rate (funding unknown: ${fundingUnknown.join(", ")}).\n` : " No open positions.\n"));
570
600
  return;
571
601
  }
572
602
  results.sort((a, b) => Math.abs(b.dailyPayment) - Math.abs(a.dailyPayment));
@@ -575,11 +605,13 @@ export async function handleFundingPositions(isJson, getAdapterForExchange, opts
575
605
  const tN = results.reduce((s, r) => s + r.notionalUsd, 0);
576
606
  const tA = results.reduce((s, r) => s + r.actualNet24h, 0);
577
607
  if (isJson())
578
- return printJson(jsonOk({ positions: results.map(r => ({ exchange: r.exchange, symbol: r.symbol, side: r.side, size: r.size, notionalUsd: +r.notionalUsd.toFixed(2), fundingRate: r.fundingRate, annualPct: +r.annualPct.toFixed(2), predicted: { hourly: +r.hourlyPayment.toFixed(6), daily: +r.dailyPayment.toFixed(4) }, actual24h: { received: +r.actualReceived24h.toFixed(6), paid: +r.actualPaid24h.toFixed(6), net: +r.actualNet24h.toFixed(6) }, unrealizedPnl: r.unrealizedPnl })), totals: { predicted: { hourly: +tH.toFixed(6), daily: +tD.toFixed(4) }, actual24h: { net: +tA.toFixed(6) }, notionalUsd: +tN.toFixed(2) }, errors: Object.keys(exchangeErrors).length > 0 ? exchangeErrors : undefined }));
579
- const exAbbr = (e) => e === "pacifica" ? "PAC" : e === "hyperliquid" ? "HL" : e === "lighter" ? "LT" : e === "aster" ? "AST" : e.toUpperCase();
608
+ return printJson(jsonOk({ positions: results.map(r => ({ exchange: r.exchange, symbol: r.symbol, side: r.side, size: r.size, notionalUsd: +r.notionalUsd.toFixed(2), fundingRate: r.fundingRate, annualPct: +r.annualPct.toFixed(2), predicted: { hourly: +r.hourlyPayment.toFixed(6), daily: +r.dailyPayment.toFixed(4) }, actual24h: { received: +r.actualReceived24h.toFixed(6), paid: +r.actualPaid24h.toFixed(6), net: +r.actualNet24h.toFixed(6) }, unrealizedPnl: r.unrealizedPnl })), totals: { predicted: { hourly: +tH.toFixed(6), daily: +tD.toFixed(4) }, actual24h: { net: +tA.toFixed(6) }, notionalUsd: +tN.toFixed(2) }, fundingUnknown, errors: Object.keys(exchangeErrors).length > 0 ? exchangeErrors : undefined }));
609
+ const exAbbr = venueAbbr;
580
610
  console.log(chalk.cyan.bold(" Position Funding Impact\n"));
581
611
  const rows = results.map(r => { const sc = r.side === "long" ? chalk.green : chalk.red; const rc = r.fundingRate > 0 ? chalk.red : r.fundingRate < 0 ? chalk.green : chalk.white; const as = r.actualNet24h !== 0 ? (r.actualNet24h > 0 ? chalk.green : chalk.red)(`${r.actualNet24h > 0 ? "+" : ""}$${r.actualNet24h.toFixed(4)}`) : chalk.gray("-"); return [chalk.white.bold(exAbbr(r.exchange)), chalk.white.bold(r.symbol), sc(r.side.toUpperCase()), `$${formatUsd(r.notionalUsd)}`, rc(formatPercent(r.fundingRate)), rc(`${r.annualPct.toFixed(1)}%`), as, formatPnl(r.unrealizedPnl)]; });
582
612
  console.log(makeTable(["Ex", "Symbol", "Side", "Notional", "Rate(now)", "Annual(now)", "Actual 24h", "uPnL"], rows));
583
613
  console.log(`\n Total: $${formatUsd(tN)} | Actual 24h: ${tA >= 0 ? "+" : ""}$${tA.toFixed(4)} | Predicted: ${tD >= 0 ? "-" : "+"}$${Math.abs(tD).toFixed(4)}/d\n`);
614
+ if (fundingUnknown.length > 0)
615
+ console.log(chalk.yellow(` Funding rate not published (excluded, not counted as 0): ${fundingUnknown.join(", ")}\n`));
584
616
  });
585
617
  }