@usherlabs/cex-broker 0.2.12 → 0.2.14

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 (44) hide show
  1. package/README.md +206 -14
  2. package/dist/commands/cli.js +10115 -8160
  3. package/dist/handlers/execute-action/context.d.ts +40 -0
  4. package/dist/handlers/execute-action/deposit.d.ts +2 -0
  5. package/dist/handlers/execute-action/handler.d.ts +14 -0
  6. package/dist/handlers/execute-action/index.d.ts +10 -0
  7. package/dist/handlers/execute-action/internal-transfer.d.ts +2 -0
  8. package/dist/handlers/execute-action/order-book-call.d.ts +3 -0
  9. package/dist/handlers/execute-action/orders.d.ts +2 -0
  10. package/dist/handlers/execute-action/pass-through.d.ts +2 -0
  11. package/dist/handlers/execute-action/perp-config.d.ts +2 -0
  12. package/dist/handlers/execute-action/registry.d.ts +5 -0
  13. package/dist/handlers/execute-action/treasury-call.d.ts +2 -0
  14. package/dist/handlers/execute-action/withdraw.d.ts +2 -0
  15. package/dist/handlers/subscribe/handler.d.ts +12 -0
  16. package/dist/handlers/subscribe/index.d.ts +1 -0
  17. package/dist/handlers/types.d.ts +23 -0
  18. package/dist/helpers/auth.d.ts +5 -0
  19. package/dist/helpers/binance-user-data-stream.d.ts +46 -0
  20. package/dist/helpers/broker.d.ts +38 -0
  21. package/dist/helpers/constants.d.ts +2 -0
  22. package/dist/helpers/deposit.d.ts +5 -0
  23. package/dist/helpers/exchange-credentials.d.ts +10 -0
  24. package/dist/helpers/grpc/broker.d.ts +5 -0
  25. package/dist/helpers/grpc/callbacks.d.ts +9 -0
  26. package/dist/helpers/grpc/payload.d.ts +9 -0
  27. package/dist/helpers/grpc/status.d.ts +8 -0
  28. package/dist/helpers/index.d.ts +8 -41
  29. package/dist/helpers/market-type.d.ts +16 -0
  30. package/dist/helpers/order-book.d.ts +79 -0
  31. package/dist/helpers/order-telemetry.d.ts +48 -0
  32. package/dist/helpers/shared/errors.d.ts +2 -0
  33. package/dist/helpers/shared/guards.d.ts +2 -0
  34. package/dist/helpers/transfer-network.d.ts +12 -0
  35. package/dist/helpers/treasury-discovery.d.ts +17 -0
  36. package/dist/helpers/verity.d.ts +5 -0
  37. package/dist/index.js +9867 -7911
  38. package/dist/index.js.map +78 -49
  39. package/dist/proto/node.descriptor.d.ts +2 -0
  40. package/dist/proto/node.descriptor.ts +3 -1
  41. package/dist/proto/node.proto +2 -0
  42. package/dist/schemas/action-payloads.d.ts +22 -0
  43. package/dist/server.d.ts +1 -1
  44. package/package.json +5 -2
package/README.md CHANGED
@@ -78,6 +78,81 @@ OTEL_SERVICE_NAME=cex-broker
78
78
 
79
79
  **Note**: Only configure API keys for exchanges you plan to use. The system will automatically detect and initialize configured exchanges.
80
80
 
81
+ #### Wallet-authenticated exchanges
82
+
83
+ Some exchanges (for example Hyperliquid, Vertex, Paradex, and Derive) authenticate with an on-chain wallet instead of exchange-issued API keys. The broker keeps the same `API_KEY` / `API_SECRET` interface and maps credentials internally based on each exchange's CCXT `requiredCredentials`:
84
+
85
+ - `CEX_BROKER_<EXCHANGE>_API_KEY` → wallet address (`0x…`)
86
+ - `CEX_BROKER_<EXCHANGE>_API_SECRET` → private key (`0x…` hex)
87
+
88
+ Example:
89
+
90
+ ```env
91
+ CEX_BROKER_HYPERLIQUID_API_KEY=0x1234567890abcdef1234567890abcdef12345678
92
+ CEX_BROKER_HYPERLIQUID_API_SECRET=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
93
+ ```
94
+
95
+ gRPC metadata uses the same parity interface: `api-key` carries the wallet address and `api-secret` carries the private key.
96
+
97
+ Detection is automatic from CCXT `requiredCredentials`. A `dex: true` flag does not imply wallet auth; exchanges such as WOOFi Pro and Modetrade still use API keys.
98
+
99
+ Treat `API_SECRET` values for wallet exchanges as signing keys with the same operational security as API secrets.
100
+
101
+ #### Spot vs perp (`marketType`)
102
+
103
+ The broker **defaults to spot everywhere** unless a request explicitly opts into perps/futures. This overrides exchange-level CCXT defaults (for example Hyperliquid's internal `defaultType: swap`).
104
+
105
+ Pass `marketType` in action payloads (string map) or subscribe `options`:
106
+
107
+ | `marketType` | Meaning |
108
+ |--------------|---------|
109
+ | omitted / `spot` | Spot markets and spot balances |
110
+ | `swap` or `perp` | Perpetuals (resolves symbols like `ETH/USDC:USDC` on Hyperliquid) |
111
+ | `future` | Dated futures where supported |
112
+
113
+ Examples:
114
+
115
+ ```json
116
+ // CreateOrder payload
117
+ {
118
+ "fromToken": "ETH",
119
+ "toToken": "USDC",
120
+ "amount": "1",
121
+ "price": "2500",
122
+ "marketType": "swap",
123
+ "params": { "slippage": "0.05" }
124
+ }
125
+ ```
126
+
127
+ ```json
128
+ // FetchBalances payload
129
+ { "marketType": "swap", "balanceType": "total" }
130
+ ```
131
+
132
+ Policy markets support optional suffixes:
133
+
134
+ - `HYPERLIQUID:ETH/USDC@swap` — perp only
135
+ - `HYPERLIQUID:ETH/USDC@spot` — spot only
136
+ - `HYPERLIQUID:ETH/USDC:USDC` — explicit unified perp symbol
137
+ - `BINANCEUSDM:ETH/USDT` — use the futures exchange id directly
138
+
139
+ For split futures exchanges (`binanceusdm`, `krakenfutures`, `kucoinfutures`), register the futures `cex` id separately. Fund movement between spot and futures wallets uses `Action.Call` or exchange-specific transfer actions.
140
+
141
+ #### Perp configuration actions
142
+
143
+ Two capability-gated actions complement `Action.Call`:
144
+
145
+ | Action | Value | Requires CCXT | Purpose |
146
+ |--------|-------|---------------|---------|
147
+ | `GetPerpConfigState` | `14` | `fetchPositions` | Read positions and per-symbol leverage/margin mode |
148
+ | `SetPerpConfigState` | `15` | `setLeverage` | Set leverage (and margin mode) for a symbol |
149
+
150
+ `GetPerpConfigState` payload: optional `symbol`, optional `params` (JSON).
151
+
152
+ `SetPerpConfigState` payload: `symbol`, `leverage`, optional `marginMode` (`cross` | `isolated`), optional `params`.
153
+
154
+ Exchanges without the required capability return gRPC `UNIMPLEMENTED`. Use `Action.Call` for other perp operations (`transfer`, `addMargin`, `closePosition`, etc.).
155
+
81
156
  **Metrics (OpenTelemetry)**: Metrics are exported via OTLP. If neither `OTEL_EXPORTER_OTLP_ENDPOINT` nor `CEX_BROKER_OTEL_HOST` (or legacy `CEX_BROKER_CLICKHOUSE_HOST`) is set, metrics are disabled. When enabled, the broker sends metrics to the configured OTLP endpoint (e.g. an OpenTelemetry Collector).
82
157
 
83
158
  ### Policy Configuration
@@ -86,6 +161,10 @@ Configure trading policies in `policy/policy.json`.
86
161
 
87
162
  - **Full reference**: see `POLICY.md` (supported options, matching rules, reload behaviour, and troubleshooting)
88
163
  - **Example policy**: `policy/policy.json`
164
+ - **Treasury corridor example**: `policy/policy.binance-mexc-usdc-bep20.example.json`
165
+ permits only USDC over the normalized BNB/BSC/BEP20 network between Binance
166
+ and MEXC; use explicit ceremony-time overrides for non-default acquired-asset
167
+ transfers.
89
168
 
90
169
  ```json
91
170
  {
@@ -220,6 +299,78 @@ message ActionResponse {
220
299
  - `FetchCurrency` (9): Get currency metadata (networks, fees, etc.) for a symbol
221
300
  - `Call` (10): Generic method invocation on the underlying broker instance. Provide `functionName`, optional `args` array, and optional `params` object.
222
301
 
302
+ #### Order Book Call Methods
303
+
304
+ `Call` also supports broker-defined order-book methods for HB strategy compatibility. These methods use the `method` payload field and return JSON in `ActionResponse.result`.
305
+
306
+ ```typescript
307
+ // Discover order-book capability
308
+ const capabilityRequest = {
309
+ action: 10, // Call
310
+ cex: "mexc",
311
+ symbol: "ARB/USDT",
312
+ payload: {
313
+ method: "fetch_order_book_capability",
314
+ depthLimit: "100",
315
+ constructionMode: "sampled_top_n_snapshot"
316
+ }
317
+ };
318
+
319
+ // Fetch current top-N order-book snapshot
320
+ const snapshotRequest = {
321
+ action: 10, // Call
322
+ cex: "binance",
323
+ symbol: "BTC/USDT",
324
+ payload: {
325
+ method: "fetch_order_book_snapshot",
326
+ depthLimit: "100"
327
+ }
328
+ };
329
+
330
+ // Request historical sampled snapshots
331
+ const historicalRequest = {
332
+ action: 10, // Call
333
+ cex: "mexc",
334
+ symbol: "ARB/USDT",
335
+ payload: {
336
+ method: "fetch_historical_order_book_snapshots",
337
+ start: "2026-06-02T00:00:00Z",
338
+ end: "2026-06-02T00:01:00Z",
339
+ cadence: "1s",
340
+ depthLimit: "100",
341
+ constructionMode: "sampled_top_n_snapshot"
342
+ }
343
+ };
344
+ ```
345
+
346
+ Current snapshot responses include top-level `bids` and `asks` arrays plus metadata:
347
+
348
+ ```json
349
+ {
350
+ "bids": [[100.0, 1.0]],
351
+ "asks": [[101.0, 2.0]],
352
+ "timestamp": 1760000000000,
353
+ "receivedTimestamp": 1760000000100,
354
+ "exchange": "binance",
355
+ "symbol": "BTC/USDT",
356
+ "sequence": 123,
357
+ "depthLimit": 100
358
+ }
359
+ ```
360
+
361
+ If historical sampled top-N depth is unavailable, the broker returns a typed unsupported result instead of a gRPC transport failure:
362
+
363
+ ```json
364
+ {
365
+ "exchange": "mexc",
366
+ "symbol": "ARB/USDT",
367
+ "unsupported": true,
368
+ "unsupportedReason": "historical_order_book_provider_unsupported"
369
+ }
370
+ ```
371
+
372
+ Capability responses are conservative: current snapshot and live stream support reflect available broker/provider methods, historical sampled top-N support is only true when implemented for the requested parameters, and exact L2 reconstruction remains false until a validated snapshot-plus-delta reconstruction path exists.
373
+
223
374
  **Example Usage:**
224
375
 
225
376
  ```typescript
@@ -302,12 +453,17 @@ message SubscribeResponse {
302
453
  ```
303
454
 
304
455
  **Available Subscription Types:**
305
- - `ORDERBOOK` (0): Real-time order book updates
306
- - `TRADES` (1): Live trade feed
307
- - `TICKER` (2): Ticker information updates
308
- - `OHLCV` (3): Candlestick data (configurable timeframe)
309
- - `BALANCE` (4): Account balance updates
310
- - `ORDERS` (5): Order status updates
456
+ - `NO_ACTION` (0): Compatibility default; resolved to `ORDERBOOK`
457
+ - `ORDERBOOK` (1): Real-time order book updates
458
+ - `TRADES` (2): Live trade feed
459
+ - `TICKER` (3): Ticker information updates
460
+ - `OHLCV` (4): Candlestick data (configurable timeframe)
461
+ - `BALANCE` (5): Account balance updates
462
+ - `ORDERS` (6): Order status updates
463
+
464
+ For backward compatibility, omitted, `NO_ACTION`, or invalid subscription type values are resolved to `ORDERBOOK`.
465
+
466
+ For Binance spot account streams, `BALANCE` and `ORDERS` use Binance's WebSocket API user-data subscription (`userDataStream.subscribe.signature`). They use the broker account selected by request metadata and do not rely on the retired Spot listenKey REST lifecycle.
311
467
 
312
468
  **Example Usage:**
313
469
 
@@ -316,15 +472,17 @@ message SubscribeResponse {
316
472
  const orderbookRequest = {
317
473
  cex: "binance",
318
474
  symbol: "BTC/USDT",
319
- type: 0, // ORDERBOOK
320
- options: {}
475
+ type: 1, // ORDERBOOK
476
+ options: {
477
+ depthLimit: "100"
478
+ }
321
479
  };
322
480
 
323
481
  // Subscribe to OHLCV with custom timeframe
324
482
  const ohlcvRequest = {
325
483
  cex: "binance",
326
484
  symbol: "BTC/USDT",
327
- type: 3, // OHLCV
485
+ type: 4, // OHLCV
328
486
  options: {
329
487
  timeframe: "1h"
330
488
  }
@@ -521,11 +679,43 @@ The following metrics are exported as OTLP counters and histograms:
521
679
  - `execute_action_success_total` (counter): Successful ExecuteAction requests
522
680
  - `execute_action_errors_total` (counter): Failed ExecuteAction requests
523
681
  - `execute_action_duration_ms` (histogram): ExecuteAction latency
682
+ - `cex_market_action_executions_total` (counter): CreateOrder/GetOrderDetails execution telemetry events, tagged by action, exchange, account label, symbol, side, order type, status, and result
683
+ - `cex_market_action_requested_quantity` (histogram): Requested base quantity when known
684
+ - `cex_market_action_requested_notional` (histogram): Requested notional from payload amount * price when known
685
+ - `cex_market_action_executed_base_quantity` (histogram): Executed base quantity reported by the exchange
686
+ - `cex_market_action_executed_quote_quantity` (histogram): Executed quote quantity/cost reported by the exchange
687
+ - `cex_market_action_average_execution_price` (histogram): Exchange-reported or derived average execution price
688
+ - `cex_market_action_filled_amount` (histogram): Filled amount reported by the exchange
689
+ - `cex_market_action_remaining_amount` (histogram): Remaining amount reported by the exchange
690
+ - `cex_market_action_fee_amount` (histogram): Fee amount when provided by the exchange
691
+ - `cex_market_action_fee_rate` (histogram): Fee rate when provided by the exchange
524
692
  - `subscribe_requests_total` (counter): Total Subscribe requests
525
693
  - `subscribe_errors_total` (counter): Failed Subscribe requests
526
694
  - `subscribe_duration_ms` (histogram): Subscribe stream duration
527
695
 
528
- All metrics include attributes: `action`, `cex`, `symbol`, `error_type`, `service`.
696
+ General request metrics include attributes such as `action`, `cex`, `symbol`, `error_type`, and `service`. Market-action execution metrics intentionally use low-cardinality attributes only: `action`, `cex`, `account`, `symbol`, `side`, `order_type`, `status`, `result`, and `service`.
697
+
698
+ ### Market Action Accounting Telemetry
699
+
700
+ Every successful `CreateOrder` response, successful `GetOrderDetails` response, rejected order response, and failed create-order attempt emits a structured log event named `cex_market_action_execution`. The event includes the low-cardinality metric attributes above plus join identifiers and accounting values:
701
+
702
+ - Join identifiers: `orderId`, `clientOrderId`, `idempotencyId`, `makerActionId`
703
+ - Execution values: requested quantity/notional, executed base quantity, executed quote quantity/cost, average execution price, filled amount, remaining amount, fee amount, fee currency, fee rate
704
+ - Timing: exchange timestamp when present and broker observed timestamp
705
+
706
+ Use metrics for aggregations and alerts, and use structured logs/events for joins back to Maker actions. For ClickHouse-backed OTel pipelines, analysts can join Maker action rows to broker telemetry using `makerActionId`, `idempotencyId`, `clientOrderId`, or the exchange `orderId`, then compare Maker propAMM execution price against `averageExecutionPrice` and fees. The broker does not emit raw exchange payloads, API keys, secrets, or credentials in these telemetry fields.
707
+
708
+ ### Telemetry Test Harness
709
+
710
+ Order telemetry tests use `test/order-telemetry-fixtures.ts` to run the real gRPC server with mocked CCXT exchanges. The fixture can simulate create-order responses, order-detail responses, partial fills, rejected orders, failed create-order calls, and fee/no-fee exchange payloads without live credentials.
711
+
712
+ Run only the focused telemetry suite:
713
+
714
+ ```bash
715
+ bun test test/order-telemetry.test.ts
716
+ ```
717
+
718
+ To extend coverage for another exchange response shape, add a mocked CCXT order object to `createOrderExchangeFixture` usage in `test/order-telemetry.test.ts` and assert the captured `CapturingOtelMetrics` calls.
529
719
 
530
720
  ### Setting Up Metrics
531
721
 
@@ -555,16 +745,18 @@ cex-broker/
555
745
  │ ├── client.dev.ts # Development client
556
746
  │ ├── commands/ # CLI commands
557
747
  │ │ └── start-broker.ts # Broker startup command
558
- │ ├── helpers/ # Utility functions
559
- ├── index.ts # Policy validation helpers
560
- │ │ ├── index.test.ts # Helper tests
748
+ │ ├── handlers/ # RPC dispatch (execute-action, subscribe)
749
+ │ ├── helpers/ # Domain utilities (shared/, grpc/, order-book, …)
750
+ │ │ ├── index.ts # Broker pool and policy helpers
751
+ │ │ ├── shared/ # Cross-cutting guards and errors
752
+ │ │ ├── grpc/ # Payload validation and status mapping
561
753
  │ │ └── logger.ts # Logging configuration
562
754
  │ ├── index.ts # Main broker class
563
755
  │ ├── proto/ # Generated protobuf types
564
756
  │ │ ├── cex_broker/ # Generated broker types
565
757
  │ │ ├── node.proto # Service definition
566
758
  │ │ └── node.ts # Type exports
567
- │ ├── server.ts # gRPC server implementation
759
+ │ ├── server.ts # gRPC wiring only (delegates to handlers/)
568
760
  │ └── types.ts # TypeScript type definitions
569
761
  ├── proto/ # Protocol buffer definitions
570
762
  │ ├── cexBroker/ # Legacy generated types