perp-cli 0.9.8 → 0.12.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 (254) hide show
  1. package/README.md +30 -25
  2. package/dist/_stderr-filter.d.ts +0 -0
  3. package/dist/_stderr-filter.js +30 -0
  4. package/dist/agent-wallet/expiry.d.ts +15 -0
  5. package/dist/agent-wallet/expiry.js +26 -0
  6. package/dist/agent-wallet/lighter-keystore.d.ts +34 -0
  7. package/dist/agent-wallet/lighter-keystore.js +232 -0
  8. package/dist/agent-wallet/passphrase.d.ts +13 -0
  9. package/dist/agent-wallet/passphrase.js +54 -0
  10. package/dist/agent-wallet/signing-strategy.d.ts +67 -0
  11. package/dist/agent-wallet/signing-strategy.js +51 -0
  12. package/dist/agent-wallet/store.d.ts +37 -0
  13. package/dist/agent-wallet/store.js +172 -0
  14. package/dist/api/public/_http.d.ts +15 -0
  15. package/dist/api/public/_http.js +24 -0
  16. package/dist/api/public/hyperliquid.js +36 -24
  17. package/dist/api/public/lighter.d.ts +7 -1
  18. package/dist/api/public/lighter.js +85 -37
  19. package/dist/api/public/pacifica.js +47 -18
  20. package/dist/bot/engine.js +23 -4
  21. package/dist/bot/presets.js +3 -3
  22. package/dist/bot/strategies/funding-arb-strategy.d.ts +0 -23
  23. package/dist/bot/strategies/funding-arb-strategy.js +41 -176
  24. package/dist/bot/strategies/funding-auto.js +2 -2
  25. package/dist/bridge-engine.js +102 -49
  26. package/dist/cli-spec.js +1 -2
  27. package/dist/commands/account.js +2 -500
  28. package/dist/commands/agent.d.ts +8 -2
  29. package/dist/commands/agent.js +1903 -366
  30. package/dist/commands/alerts.js +3 -1
  31. package/dist/commands/arb/index.js +37 -7
  32. package/dist/commands/arb-auto.js +44 -11
  33. package/dist/commands/arb.js +83 -34
  34. package/dist/commands/bot.d.ts +1 -1
  35. package/dist/commands/bot.js +20 -16
  36. package/dist/commands/bridge.d.ts +1 -1
  37. package/dist/commands/bridge.js +4 -4
  38. package/dist/commands/funds.d.ts +1 -1
  39. package/dist/commands/funds.js +18 -68
  40. package/dist/commands/jobs.d.ts +1 -1
  41. package/dist/commands/jobs.js +2 -2
  42. package/dist/commands/manage.d.ts +1 -1
  43. package/dist/commands/manage.js +12 -84
  44. package/dist/commands/plan.d.ts +1 -1
  45. package/dist/commands/plan.js +2 -2
  46. package/dist/commands/portfolio.d.ts +19 -3
  47. package/dist/commands/portfolio.js +747 -163
  48. package/dist/commands/rebalance.d.ts +1 -1
  49. package/dist/commands/rebalance.js +18 -12
  50. package/dist/commands/risk.js +2 -6
  51. package/dist/commands/settings.js +30 -53
  52. package/dist/commands/trade.js +16 -15
  53. package/dist/commands/wallet.d.ts +2 -1
  54. package/dist/commands/wallet.js +1122 -176
  55. package/dist/config.d.ts +9 -0
  56. package/dist/config.js +55 -9
  57. package/dist/errors.d.ts +64 -0
  58. package/dist/errors.js +82 -2
  59. package/dist/event-stream.js +12 -1
  60. package/dist/exchanges/aster-typed-data.d.ts +156 -0
  61. package/dist/exchanges/aster-typed-data.js +189 -0
  62. package/dist/exchanges/aster.d.ts +60 -11
  63. package/dist/exchanges/aster.js +278 -136
  64. package/dist/exchanges/hyperliquid.d.ts +14 -0
  65. package/dist/exchanges/hyperliquid.js +88 -34
  66. package/dist/exchanges/lighter-spot.js +19 -5
  67. package/dist/exchanges/lighter.d.ts +66 -0
  68. package/dist/exchanges/lighter.js +213 -31
  69. package/dist/exchanges/pacifica-typed-data.d.ts +75 -0
  70. package/dist/exchanges/pacifica-typed-data.js +74 -0
  71. package/dist/exchanges/pacifica.d.ts +29 -1
  72. package/dist/exchanges/pacifica.js +94 -6
  73. package/dist/funding/rates.js +59 -21
  74. package/dist/guardrail/contracts.d.ts +14 -0
  75. package/dist/guardrail/contracts.js +72 -0
  76. package/dist/guardrail/perp-guardrail.d.ts +21 -0
  77. package/dist/guardrail/perp-guardrail.js +145 -0
  78. package/dist/index.d.ts +1 -1
  79. package/dist/index.js +307 -362
  80. package/dist/jobs.js +3 -1
  81. package/dist/mcp-server.js +92 -88
  82. package/dist/position-history.js +47 -4
  83. package/dist/settings.d.ts +69 -3
  84. package/dist/settings.js +3 -2
  85. package/dist/signer/index.d.ts +2 -0
  86. package/dist/signer/index.js +2 -0
  87. package/dist/signer/ows-evm.d.ts +32 -0
  88. package/dist/signer/ows-evm.js +86 -0
  89. package/dist/signer/ows-loader.d.ts +2 -0
  90. package/dist/signer/ows-loader.js +6 -0
  91. package/dist/signer/ows-solana.d.ts +25 -0
  92. package/dist/signer/ows-solana.js +56 -0
  93. package/dist/smart-order.d.ts +8 -2
  94. package/dist/smart-order.js +46 -11
  95. package/dist/strategies/funding-arb.js +29 -8
  96. package/dist/trade-validator.js +30 -5
  97. package/dist/utils.d.ts +10 -0
  98. package/dist/utils.js +19 -0
  99. package/package.json +4 -2
  100. package/skills/perp-cli/SKILL.md +23 -14
  101. package/skills/perp-cli/references/agent-operations.md +6 -4
  102. package/skills/perp-cli/references/commands.md +55 -34
  103. package/skills/perp-cli/scripts/preflight.sh +4 -4
  104. package/skills/perp-cli/scripts/spot-perp-scan.sh +2 -2
  105. package/dist/__tests__/alert-logic.test.d.ts +0 -1
  106. package/dist/__tests__/alert-logic.test.js +0 -107
  107. package/dist/__tests__/arb-auto-3dex.test.d.ts +0 -1
  108. package/dist/__tests__/arb-auto-3dex.test.js +0 -397
  109. package/dist/__tests__/arb-history-stats.test.d.ts +0 -1
  110. package/dist/__tests__/arb-history-stats.test.js +0 -176
  111. package/dist/__tests__/arb-logic.test.d.ts +0 -1
  112. package/dist/__tests__/arb-logic.test.js +0 -84
  113. package/dist/__tests__/arb-manage.test.d.ts +0 -1
  114. package/dist/__tests__/arb-manage.test.js +0 -253
  115. package/dist/__tests__/arb-new-features.test.d.ts +0 -1
  116. package/dist/__tests__/arb-new-features.test.js +0 -457
  117. package/dist/__tests__/arb-sizing.test.d.ts +0 -1
  118. package/dist/__tests__/arb-sizing.test.js +0 -48
  119. package/dist/__tests__/arb-state.test.d.ts +0 -1
  120. package/dist/__tests__/arb-state.test.js +0 -284
  121. package/dist/__tests__/arb-userflow.test.d.ts +0 -1
  122. package/dist/__tests__/arb-userflow.test.js +0 -945
  123. package/dist/__tests__/arb-utils.test.d.ts +0 -1
  124. package/dist/__tests__/arb-utils.test.js +0 -264
  125. package/dist/__tests__/bot-conditions.test.d.ts +0 -1
  126. package/dist/__tests__/bot-conditions.test.js +0 -341
  127. package/dist/__tests__/client-id-tracker.test.d.ts +0 -1
  128. package/dist/__tests__/client-id-tracker.test.js +0 -137
  129. package/dist/__tests__/commands/new-atomic-commands.test.d.ts +0 -1
  130. package/dist/__tests__/commands/new-atomic-commands.test.js +0 -502
  131. package/dist/__tests__/commands/order-intent.test.d.ts +0 -1
  132. package/dist/__tests__/commands/order-intent.test.js +0 -600
  133. package/dist/__tests__/commands/trade-commands.test.d.ts +0 -1
  134. package/dist/__tests__/commands/trade-commands.test.js +0 -821
  135. package/dist/__tests__/config.test.d.ts +0 -1
  136. package/dist/__tests__/config.test.js +0 -86
  137. package/dist/__tests__/cross-chain-margin.test.d.ts +0 -1
  138. package/dist/__tests__/cross-chain-margin.test.js +0 -287
  139. package/dist/__tests__/dex-asset-map.test.d.ts +0 -1
  140. package/dist/__tests__/dex-asset-map.test.js +0 -191
  141. package/dist/__tests__/errors.test.d.ts +0 -1
  142. package/dist/__tests__/errors.test.js +0 -110
  143. package/dist/__tests__/event-stream.test.d.ts +0 -1
  144. package/dist/__tests__/event-stream.test.js +0 -276
  145. package/dist/__tests__/exchanges/interface.test.d.ts +0 -1
  146. package/dist/__tests__/exchanges/interface.test.js +0 -132
  147. package/dist/__tests__/exchanges/mock-adapter.d.ts +0 -69
  148. package/dist/__tests__/exchanges/mock-adapter.js +0 -137
  149. package/dist/__tests__/execution-log.test.d.ts +0 -1
  150. package/dist/__tests__/execution-log.test.js +0 -106
  151. package/dist/__tests__/funding-calc.test.d.ts +0 -1
  152. package/dist/__tests__/funding-calc.test.js +0 -71
  153. package/dist/__tests__/funding-history.test.d.ts +0 -1
  154. package/dist/__tests__/funding-history.test.js +0 -343
  155. package/dist/__tests__/funding-rates.test.d.ts +0 -1
  156. package/dist/__tests__/funding-rates.test.js +0 -342
  157. package/dist/__tests__/funding.test.d.ts +0 -1
  158. package/dist/__tests__/funding.test.js +0 -173
  159. package/dist/__tests__/gap-logic.test.d.ts +0 -1
  160. package/dist/__tests__/gap-logic.test.js +0 -43
  161. package/dist/__tests__/hip3-dex.test.d.ts +0 -1
  162. package/dist/__tests__/hip3-dex.test.js +0 -234
  163. package/dist/__tests__/integration/agent-features.integration.test.d.ts +0 -1
  164. package/dist/__tests__/integration/agent-features.integration.test.js +0 -553
  165. package/dist/__tests__/integration/atomic-commands.integration.test.d.ts +0 -13
  166. package/dist/__tests__/integration/atomic-commands.integration.test.js +0 -246
  167. package/dist/__tests__/integration/bridge-simulation.integration.test.d.ts +0 -1
  168. package/dist/__tests__/integration/bridge-simulation.integration.test.js +0 -453
  169. package/dist/__tests__/integration/bridge-strict.integration.test.d.ts +0 -1
  170. package/dist/__tests__/integration/bridge-strict.integration.test.js +0 -812
  171. package/dist/__tests__/integration/bridge.integration.test.d.ts +0 -1
  172. package/dist/__tests__/integration/bridge.integration.test.js +0 -309
  173. package/dist/__tests__/integration/cli-e2e.integration.test.d.ts +0 -1
  174. package/dist/__tests__/integration/cli-e2e.integration.test.js +0 -202
  175. package/dist/__tests__/integration/dex-arb.integration.test.d.ts +0 -1
  176. package/dist/__tests__/integration/dex-arb.integration.test.js +0 -116
  177. package/dist/__tests__/integration/envelope-consistency.integration.test.d.ts +0 -13
  178. package/dist/__tests__/integration/envelope-consistency.integration.test.js +0 -205
  179. package/dist/__tests__/integration/hip3-dex.integration.test.d.ts +0 -1
  180. package/dist/__tests__/integration/hip3-dex.integration.test.js +0 -147
  181. package/dist/__tests__/integration/hyperliquid.integration.test.d.ts +0 -1
  182. package/dist/__tests__/integration/hyperliquid.integration.test.js +0 -79
  183. package/dist/__tests__/integration/lighter.integration.test.d.ts +0 -1
  184. package/dist/__tests__/integration/lighter.integration.test.js +0 -53
  185. package/dist/__tests__/integration/new-commands-e2e.integration.test.d.ts +0 -9
  186. package/dist/__tests__/integration/new-commands-e2e.integration.test.js +0 -236
  187. package/dist/__tests__/integration/order-verification.integration.test.d.ts +0 -1
  188. package/dist/__tests__/integration/order-verification.integration.test.js +0 -321
  189. package/dist/__tests__/integration/pacifica.integration.test.d.ts +0 -1
  190. package/dist/__tests__/integration/pacifica.integration.test.js +0 -75
  191. package/dist/__tests__/integration/response-shapes.integration.test.d.ts +0 -1
  192. package/dist/__tests__/integration/response-shapes.integration.test.js +0 -278
  193. package/dist/__tests__/liquidity.test.d.ts +0 -1
  194. package/dist/__tests__/liquidity.test.js +0 -225
  195. package/dist/__tests__/plan-executor.test.d.ts +0 -1
  196. package/dist/__tests__/plan-executor.test.js +0 -314
  197. package/dist/__tests__/position-history.test.d.ts +0 -1
  198. package/dist/__tests__/position-history.test.js +0 -367
  199. package/dist/__tests__/retry.test.d.ts +0 -1
  200. package/dist/__tests__/retry.test.js +0 -310
  201. package/dist/__tests__/risk-assessment.test.d.ts +0 -1
  202. package/dist/__tests__/risk-assessment.test.js +0 -288
  203. package/dist/__tests__/security-adversarial.test.d.ts +0 -1
  204. package/dist/__tests__/security-adversarial.test.js +0 -574
  205. package/dist/__tests__/strategies.test.d.ts +0 -1
  206. package/dist/__tests__/strategies.test.js +0 -539
  207. package/dist/__tests__/trade-execution.test.d.ts +0 -1
  208. package/dist/__tests__/trade-execution.test.js +0 -129
  209. package/dist/__tests__/trade-validator.test.d.ts +0 -1
  210. package/dist/__tests__/trade-validator.test.js +0 -655
  211. package/dist/__tests__/utils.test.d.ts +0 -1
  212. package/dist/__tests__/utils.test.js +0 -76
  213. package/dist/arb/reconcile.d.ts +0 -28
  214. package/dist/arb/reconcile.js +0 -162
  215. package/dist/commands/alert.d.ts +0 -2
  216. package/dist/commands/alert.js +0 -421
  217. package/dist/commands/analytics.d.ts +0 -3
  218. package/dist/commands/analytics.js +0 -311
  219. package/dist/commands/arb-manage.d.ts +0 -5
  220. package/dist/commands/arb-manage.js +0 -5
  221. package/dist/commands/dashboard.d.ts +0 -3
  222. package/dist/commands/dashboard.js +0 -176
  223. package/dist/commands/deposit.d.ts +0 -4
  224. package/dist/commands/deposit.js +0 -573
  225. package/dist/commands/dex.d.ts +0 -3
  226. package/dist/commands/dex.js +0 -120
  227. package/dist/commands/env.d.ts +0 -2
  228. package/dist/commands/env.js +0 -136
  229. package/dist/commands/funding.d.ts +0 -3
  230. package/dist/commands/funding.js +0 -554
  231. package/dist/commands/gap.d.ts +0 -2
  232. package/dist/commands/gap.js +0 -305
  233. package/dist/commands/health.d.ts +0 -2
  234. package/dist/commands/health.js +0 -67
  235. package/dist/commands/multileg.d.ts +0 -16
  236. package/dist/commands/multileg.js +0 -174
  237. package/dist/commands/pnl.d.ts +0 -12
  238. package/dist/commands/pnl.js +0 -243
  239. package/dist/commands/run.d.ts +0 -3
  240. package/dist/commands/run.js +0 -202
  241. package/dist/commands/stream.d.ts +0 -5
  242. package/dist/commands/stream.js +0 -200
  243. package/dist/commands/withdraw.d.ts +0 -3
  244. package/dist/commands/withdraw.js +0 -187
  245. package/dist/exchanges/edgex.d.ts +0 -62
  246. package/dist/exchanges/edgex.js +0 -552
  247. package/dist/exchanges/nado.d.ts +0 -52
  248. package/dist/exchanges/nado.js +0 -223
  249. package/dist/funding/index.d.ts +0 -3
  250. package/dist/funding/index.js +0 -3
  251. package/dist/retry.d.ts +0 -74
  252. package/dist/retry.js +0 -129
  253. package/dist/ws/market-feed.d.ts +0 -74
  254. package/dist/ws/market-feed.js +0 -227
@@ -1,227 +0,0 @@
1
- /**
2
- * Unified market data feeds for CLI streaming commands.
3
- *
4
- * - Hyperliquid: native WebSocket (allMids, l2Book, trades, candle)
5
- * - Lighter: REST polling (no public market data WS)
6
- * - Pacifica: handled via existing PacificaWSClient in stream.ts
7
- */
8
- import { EventEmitter } from "events";
9
- // ── Hyperliquid Market Feed (native WebSocket) ──
10
- export class HyperliquidMarketFeed extends EventEmitter {
11
- ws = null;
12
- closed = false;
13
- reconnectTimer = null;
14
- subs = [];
15
- get wsUrl() { return "wss://api.hyperliquid.xyz/ws"; }
16
- async connect() {
17
- const { WebSocket } = await import("ws");
18
- return new Promise((resolve, reject) => {
19
- this.ws = new WebSocket(this.wsUrl);
20
- this.ws.on("open", () => {
21
- // Re-subscribe on reconnect
22
- for (const sub of this.subs)
23
- this.send({ method: "subscribe", subscription: sub });
24
- this.emit("connected");
25
- resolve();
26
- });
27
- this.ws.on("error", (err) => {
28
- if (!this.closed)
29
- reject(err);
30
- });
31
- this.ws.on("close", () => {
32
- if (!this.closed) {
33
- this.emit("disconnected");
34
- this.scheduleReconnect();
35
- }
36
- });
37
- this.ws.on("message", (raw) => {
38
- try {
39
- this.handleMessage(JSON.parse(String(raw)));
40
- }
41
- catch { /* ignore */ }
42
- });
43
- });
44
- }
45
- send(data) {
46
- if (this.ws?.readyState === 1)
47
- this.ws.send(JSON.stringify(data));
48
- }
49
- sub(subscription) {
50
- this.subs.push(subscription);
51
- this.send({ method: "subscribe", subscription });
52
- }
53
- scheduleReconnect() {
54
- if (this.closed)
55
- return;
56
- this.reconnectTimer = setTimeout(async () => {
57
- try {
58
- await this.connect();
59
- }
60
- catch {
61
- this.scheduleReconnect();
62
- }
63
- }, 3000);
64
- }
65
- subscribePrices() { this.sub({ type: "allMids" }); }
66
- subscribeBook(symbol) { this.sub({ type: "l2Book", coin: symbol.toUpperCase() }); }
67
- subscribeTrades(symbol) { this.sub({ type: "trades", coin: symbol.toUpperCase() }); }
68
- subscribeCandle(symbol, interval) {
69
- this.sub({ type: "candle", coin: symbol.toUpperCase(), interval });
70
- }
71
- handleMessage(msg) {
72
- const channel = String(msg.channel ?? "");
73
- const data = msg.data;
74
- if (!data)
75
- return;
76
- if (channel === "allMids") {
77
- const mids = (data.mids ?? data);
78
- const updates = Object.entries(mids).map(([symbol, mid]) => ({
79
- symbol, mid: Number(mid),
80
- }));
81
- this.emit("prices", updates);
82
- }
83
- else if (channel === "l2Book") {
84
- const d = data;
85
- const levels = d.levels;
86
- if (levels) {
87
- this.emit("book", {
88
- bids: levels[0].map((l) => [l.px, l.sz]),
89
- asks: levels[1].map((l) => [l.px, l.sz]),
90
- });
91
- }
92
- }
93
- else if (channel === "trades") {
94
- const trades = Array.isArray(data) ? data : [];
95
- for (const t of trades) {
96
- // HL side: "A" = sell (ask), "B" = buy (bid)
97
- const rawSide = String(t.side ?? "");
98
- this.emit("trade", {
99
- side: rawSide === "A" ? "sell" : rawSide === "B" ? "buy" : rawSide,
100
- price: String(t.px ?? ""),
101
- size: String(t.sz ?? ""),
102
- time: Number(t.time ?? Date.now()),
103
- });
104
- }
105
- }
106
- else if (channel === "candle") {
107
- const d = data;
108
- this.emit("candle", {
109
- o: String(d.o ?? ""), h: String(d.h ?? ""), l: String(d.l ?? ""),
110
- c: String(d.c ?? ""), v: String(d.v ?? ""), t: Number(d.t ?? 0),
111
- });
112
- }
113
- }
114
- close() {
115
- this.closed = true;
116
- if (this.reconnectTimer)
117
- clearTimeout(this.reconnectTimer);
118
- if (this.ws) {
119
- this.ws.close();
120
- this.ws = null;
121
- }
122
- }
123
- }
124
- // ── Lighter Market Feed (REST polling) ──
125
- const LIGHTER_BASE = "https://mainnet.zklighter.elliot.ai/api/v1";
126
- export class LighterMarketFeed extends EventEmitter {
127
- closed = false;
128
- timers = [];
129
- marketMap = new Map();
130
- pricesMs;
131
- bookMs;
132
- candleMs;
133
- constructor(opts) {
134
- super();
135
- this.pricesMs = opts?.pricesIntervalMs ?? 3000;
136
- this.bookMs = opts?.bookIntervalMs ?? 2000;
137
- this.candleMs = opts?.candleIntervalMs ?? 5000;
138
- }
139
- async connect() {
140
- const res = await fetch(`${LIGHTER_BASE}/orderBookDetails`);
141
- const json = await res.json();
142
- for (const m of json.order_book_details ?? []) {
143
- if (m.market_type === "perp")
144
- this.marketMap.set(m.symbol.toUpperCase(), m.market_id);
145
- }
146
- this.emit("connected");
147
- }
148
- getMarketId(symbol) {
149
- const id = this.marketMap.get(symbol.toUpperCase());
150
- if (id === undefined)
151
- throw new Error(`Unknown Lighter market: ${symbol}`);
152
- return id;
153
- }
154
- poll(fn, intervalMs) {
155
- fn().catch(() => { });
156
- this.timers.push(setInterval(() => { if (!this.closed)
157
- fn().catch(() => { }); }, intervalMs));
158
- }
159
- subscribePrices() {
160
- this.poll(async () => {
161
- const res = await fetch(`${LIGHTER_BASE}/orderBookDetails`);
162
- const json = await res.json();
163
- const updates = (json.order_book_details ?? [])
164
- .filter(m => m.market_type === "perp")
165
- .map(m => ({ symbol: m.symbol, mid: m.last_trade_price }));
166
- this.emit("prices", updates);
167
- }, this.pricesMs);
168
- }
169
- subscribeBook(symbol) {
170
- const marketId = this.getMarketId(symbol);
171
- this.poll(async () => {
172
- const res = await fetch(`${LIGHTER_BASE}/orderBookOrders?market_id=${marketId}&limit=20`);
173
- const json = await res.json();
174
- this.emit("book", {
175
- bids: (json.bids ?? []).map(b => [b.price, b.remaining_base_amount]),
176
- asks: (json.asks ?? []).map(a => [a.price, a.remaining_base_amount]),
177
- });
178
- }, this.bookMs);
179
- }
180
- subscribeTrades(symbol) {
181
- const marketId = this.getMarketId(symbol);
182
- let lastTid = 0;
183
- this.poll(async () => {
184
- const res = await fetch(`${LIGHTER_BASE}/recentTrades?market_id=${marketId}&limit=20`);
185
- const json = await res.json();
186
- for (const t of json.trades ?? []) {
187
- if (t.timestamp > lastTid) {
188
- lastTid = t.timestamp;
189
- this.emit("trade", {
190
- side: t.is_maker_ask ? "buy" : "sell",
191
- price: t.price,
192
- size: t.size,
193
- time: t.timestamp,
194
- });
195
- }
196
- }
197
- }, this.bookMs);
198
- }
199
- subscribeCandle(symbol, interval) {
200
- const marketId = this.getMarketId(symbol);
201
- this.poll(async () => {
202
- const now = Math.floor(Date.now() / 1000);
203
- const res = await fetch(`${LIGHTER_BASE}/candles?market_id=${marketId}&resolution=${interval}&count_back=1&end_timestamp=${now}`);
204
- const json = await res.json();
205
- const c = json.candles?.[0];
206
- if (c) {
207
- this.emit("candle", {
208
- o: c.open, h: c.high, l: c.low, c: c.close, v: c.volume, t: c.timestamp,
209
- });
210
- }
211
- }, this.candleMs);
212
- }
213
- close() {
214
- this.closed = true;
215
- for (const t of this.timers)
216
- clearInterval(t);
217
- this.timers = [];
218
- }
219
- }
220
- // ── Factory ──
221
- export function createMarketFeed(exchange) {
222
- if (exchange === "hyperliquid")
223
- return new HyperliquidMarketFeed();
224
- if (exchange === "lighter")
225
- return new LighterMarketFeed();
226
- throw new Error(`Use PacificaWSClient for pacifica, not createMarketFeed`);
227
- }