@usherlabs/cex-broker 0.2.12 → 0.2.13
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.
- package/README.md +206 -14
- package/dist/commands/cli.js +9985 -8160
- package/dist/handlers/execute-action/context.d.ts +40 -0
- package/dist/handlers/execute-action/deposit.d.ts +2 -0
- package/dist/handlers/execute-action/handler.d.ts +14 -0
- package/dist/handlers/execute-action/index.d.ts +10 -0
- package/dist/handlers/execute-action/internal-transfer.d.ts +2 -0
- package/dist/handlers/execute-action/order-book-call.d.ts +3 -0
- package/dist/handlers/execute-action/orders.d.ts +2 -0
- package/dist/handlers/execute-action/pass-through.d.ts +2 -0
- package/dist/handlers/execute-action/perp-config.d.ts +2 -0
- package/dist/handlers/execute-action/registry.d.ts +5 -0
- package/dist/handlers/execute-action/treasury-call.d.ts +2 -0
- package/dist/handlers/execute-action/withdraw.d.ts +2 -0
- package/dist/handlers/subscribe/handler.d.ts +12 -0
- package/dist/handlers/subscribe/index.d.ts +1 -0
- package/dist/handlers/types.d.ts +23 -0
- package/dist/helpers/auth.d.ts +5 -0
- package/dist/helpers/binance-user-data-stream.d.ts +28 -0
- package/dist/helpers/broker.d.ts +38 -0
- package/dist/helpers/constants.d.ts +2 -0
- package/dist/helpers/deposit.d.ts +5 -0
- package/dist/helpers/exchange-credentials.d.ts +10 -0
- package/dist/helpers/grpc/broker.d.ts +5 -0
- package/dist/helpers/grpc/callbacks.d.ts +9 -0
- package/dist/helpers/grpc/payload.d.ts +9 -0
- package/dist/helpers/grpc/status.d.ts +8 -0
- package/dist/helpers/index.d.ts +8 -41
- package/dist/helpers/market-type.d.ts +16 -0
- package/dist/helpers/order-book.d.ts +79 -0
- package/dist/helpers/order-telemetry.d.ts +48 -0
- package/dist/helpers/shared/errors.d.ts +2 -0
- package/dist/helpers/shared/guards.d.ts +2 -0
- package/dist/helpers/transfer-network.d.ts +12 -0
- package/dist/helpers/treasury-discovery.d.ts +17 -0
- package/dist/helpers/verity.d.ts +5 -0
- package/dist/index.js +9736 -7911
- package/dist/index.js.map +78 -49
- package/dist/proto/node.descriptor.d.ts +2 -0
- package/dist/proto/node.descriptor.ts +3 -1
- package/dist/proto/node.proto +2 -0
- package/dist/schemas/action-payloads.d.ts +22 -0
- package/dist/server.d.ts +1 -1
- package/package.json +3 -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
|
-
- `
|
|
306
|
-
- `
|
|
307
|
-
- `
|
|
308
|
-
- `
|
|
309
|
-
- `
|
|
310
|
-
- `
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
│ ├──
|
|
559
|
-
│
|
|
560
|
-
│ │ ├── index.
|
|
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
|
|
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
|