@imbingox/acex 0.1.0-beta.0 → 0.1.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.
- package/README.md +334 -40
- package/dist/adapters/binance/composite-adapter.d.ts +116 -0
- package/dist/adapters/binance/composite-adapter.js +121 -0
- package/dist/adapters/binance/market-types.d.ts +63 -0
- package/dist/adapters/binance/market-types.js +1 -0
- package/dist/adapters/binance/native-market-adapter.d.ts +102 -0
- package/dist/adapters/binance/native-market-adapter.js +455 -0
- package/dist/adapters/binance/normalizers.d.ts +8 -0
- package/dist/adapters/binance/normalizers.js +123 -0
- package/dist/adapters/binance/rest-client.d.ts +17 -0
- package/dist/adapters/binance/rest-client.js +66 -0
- package/dist/adapters/binance/symbol-router.d.ts +9 -0
- package/dist/adapters/binance/symbol-router.js +174 -0
- package/dist/adapters/binance/ws-client.d.ts +24 -0
- package/dist/adapters/binance/ws-client.js +261 -0
- package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.d.ts +1 -0
- package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.js +6 -4
- package/dist/adapters/ccxt/binance-usdm-exchange.d.ts +22 -0
- package/dist/adapters/ccxt/binance-usdm-exchange.js +23 -0
- package/dist/core/client.d.ts +18 -5
- package/dist/core/client.js +360 -2
- package/dist/index.d.ts +2 -1
- package/dist/runtime/ws-connection-supervisor.d.ts +76 -0
- package/dist/runtime/ws-connection-supervisor.js +522 -0
- package/dist/testing/create-fake-runtime.d.ts +1 -1
- package/dist/types/public.d.ts +0 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,65 +1,359 @@
|
|
|
1
1
|
# acex
|
|
2
2
|
|
|
3
|
-
Bun
|
|
3
|
+
`acex` 是一个面向 Bun 的交易 SDK。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
当前 public `createClient()` 的可用范围是:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- 只支持 `binance`
|
|
8
|
+
- 只支持单账户
|
|
9
|
+
- 默认走 `sandbox: true`
|
|
10
|
+
- 当前官方验证环境是 Binance USD-M demo/testnet
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
当前 Binance 路径分为两层:
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
- market 行情层已经走 native adapter,支持 `spot`、`USDⓈ-M perpetual`、`COIN-M perpetual`、`COIN-M delivery`
|
|
15
|
+
- `subscribeFundingRate()` 只对 perpetual 市场可用
|
|
16
|
+
- account / order 仍沿用当前 Binance USD-M private 路径
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
- private WebSocket connectivity
|
|
17
|
-
- baseline bootstrap for runtime readiness
|
|
18
|
-
- market `placeOrder`
|
|
19
|
-
- reduce-only market `placeOrder`
|
|
18
|
+
包名:
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
```bash
|
|
21
|
+
@imbingox/acex
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 安装
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
bun
|
|
27
|
+
bun add @imbingox/acex
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 你会怎么用它
|
|
31
|
+
|
|
32
|
+
典型流程只有 5 步:
|
|
33
|
+
|
|
34
|
+
1. `createClient()` 创建客户端
|
|
35
|
+
2. `registerAccount()` 注册账户
|
|
36
|
+
3. `start()` 启动运行时
|
|
37
|
+
4. `subscribe...()` 建立你关心的数据订阅
|
|
38
|
+
5. 用 `get...()` 读取当前最新快照,或用下单 API 发命令
|
|
39
|
+
|
|
40
|
+
## 最小示例
|
|
41
|
+
|
|
42
|
+
下面这段就是当前推荐的接入方式:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { createClient } from "@imbingox/acex";
|
|
46
|
+
|
|
47
|
+
async function main() {
|
|
48
|
+
const client = createClient({
|
|
49
|
+
sandbox: true,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await client.registerAccount({
|
|
53
|
+
accountId: "main-binance",
|
|
54
|
+
exchange: "binance",
|
|
55
|
+
credentials: {
|
|
56
|
+
apiKey: process.env.BINANCE_API_KEY!,
|
|
57
|
+
secret: process.env.BINANCE_API_SECRET!,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await client.start();
|
|
62
|
+
|
|
63
|
+
await client.market.subscribeL1Book({
|
|
64
|
+
exchange: "binance",
|
|
65
|
+
symbol: "BTC/USDT",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await client.market.subscribeL1Book({
|
|
69
|
+
exchange: "binance",
|
|
70
|
+
symbol: "BTC/USDT:USDT",
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await client.market.subscribeFundingRate({
|
|
74
|
+
exchange: "binance",
|
|
75
|
+
symbol: "BTC/USDT:USDT",
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await client.account.subscribeAccount({
|
|
79
|
+
accountId: "main-binance",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await client.order.subscribeOrders({
|
|
83
|
+
accountId: "main-binance",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const book = client.market.getL1Book({
|
|
87
|
+
exchange: "binance",
|
|
88
|
+
symbol: "BTC/USDT:USDT",
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const account = client.account.getAccountSnapshot("main-binance");
|
|
92
|
+
const orderStatus = client.order.getOrderStatus("main-binance");
|
|
93
|
+
|
|
94
|
+
console.log({
|
|
95
|
+
status: client.getStatus(),
|
|
96
|
+
health: client.getHealth(),
|
|
97
|
+
book,
|
|
98
|
+
account,
|
|
99
|
+
orderStatus,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await client.stop();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
void main();
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 运行顺序说明
|
|
109
|
+
|
|
110
|
+
### 1. 创建客户端
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const client = createClient({
|
|
114
|
+
sandbox: true,
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
当前只支持一个选项:
|
|
119
|
+
|
|
120
|
+
- `sandbox`
|
|
121
|
+
|
|
122
|
+
说明:
|
|
123
|
+
|
|
124
|
+
- `sandbox` 默认就是 `true`
|
|
125
|
+
- 对当前实现来说,`sandbox: true` 对应 Binance USD-M demo/testnet 路径
|
|
126
|
+
|
|
127
|
+
### 2. 注册账户
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await client.registerAccount({
|
|
131
|
+
accountId: "main-binance",
|
|
132
|
+
exchange: "binance",
|
|
133
|
+
credentials: {
|
|
134
|
+
apiKey: process.env.BINANCE_API_KEY!,
|
|
135
|
+
secret: process.env.BINANCE_API_SECRET!,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
当前约束:
|
|
141
|
+
|
|
142
|
+
- `accountId` 不能为空
|
|
143
|
+
- `exchange` 只能是 `binance`
|
|
144
|
+
- `apiKey` 和 `secret` 不能为空
|
|
145
|
+
- 一个 `client` 现在只能注册一个账户
|
|
146
|
+
|
|
147
|
+
### 3. 启动运行时
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
await client.start();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`start()` 之后,SDK 才会真正建立底层 runtime。
|
|
154
|
+
|
|
155
|
+
如果你在 `start()` 之前调用:
|
|
156
|
+
|
|
157
|
+
- `subscribeL1Book()`
|
|
158
|
+
- `subscribeAccount()`
|
|
159
|
+
- `subscribeOrders()`
|
|
160
|
+
- 下单相关 API
|
|
161
|
+
|
|
162
|
+
会直接抛错。
|
|
163
|
+
|
|
164
|
+
### 4. 订阅你要的数据
|
|
165
|
+
|
|
166
|
+
行情:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
await client.market.subscribeL1Book({
|
|
170
|
+
exchange: "binance",
|
|
171
|
+
symbol: "BTC/USDT",
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await client.market.subscribeL1Book({
|
|
175
|
+
exchange: "binance",
|
|
176
|
+
symbol: "BTC/USDT:USDT",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await client.market.subscribeFundingRate({
|
|
180
|
+
exchange: "binance",
|
|
181
|
+
symbol: "BTC/USDT:USDT",
|
|
182
|
+
});
|
|
25
183
|
```
|
|
26
184
|
|
|
27
|
-
|
|
185
|
+
账户基线:
|
|
28
186
|
|
|
29
|
-
|
|
187
|
+
```ts
|
|
188
|
+
await client.account.subscribeAccount({
|
|
189
|
+
accountId: "main-binance",
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
订单基线:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
await client.order.subscribeOrders({
|
|
197
|
+
accountId: "main-binance",
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
建议:
|
|
202
|
+
|
|
203
|
+
- 要读余额/仓位前,先做 `subscribeAccount()`
|
|
204
|
+
- 要读 open orders / order status 前,先做 `subscribeOrders()`
|
|
205
|
+
|
|
206
|
+
### 5. 读取最新快照
|
|
207
|
+
|
|
208
|
+
行情快照:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
const book = client.market.getL1Book({
|
|
212
|
+
exchange: "binance",
|
|
213
|
+
symbol: "BTC/USDT:USDT",
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
账户快照:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
const account = client.account.getAccountSnapshot("main-binance");
|
|
221
|
+
const balances = client.account.getBalances("main-binance");
|
|
222
|
+
const positions = client.account.getPositions("main-binance");
|
|
223
|
+
const risk = client.account.getRiskSnapshot("main-binance");
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
订单投影:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
const openOrders = client.order.getOpenOrders("main-binance");
|
|
230
|
+
const orderStatus = client.order.getOrderStatus("main-binance");
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## 下单相关 API
|
|
234
|
+
|
|
235
|
+
当前 public API 已暴露这些命令:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
await client.order.placeOrder({
|
|
239
|
+
accountId: "main-binance",
|
|
240
|
+
exchange: "binance",
|
|
241
|
+
symbol: "BTC/USDT:USDT",
|
|
242
|
+
side: "buy",
|
|
243
|
+
amount: "0.001",
|
|
244
|
+
clientOrderId: "demo-open-1",
|
|
245
|
+
type: "market",
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
await client.order.cancelOrder({
|
|
251
|
+
accountId: "main-binance",
|
|
252
|
+
exchange: "binance",
|
|
253
|
+
clientOrderId: "demo-open-1",
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
await client.order.amendOrder({
|
|
259
|
+
accountId: "main-binance",
|
|
260
|
+
exchange: "binance",
|
|
261
|
+
clientOrderId: "demo-open-1",
|
|
262
|
+
newPrice: "65000",
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
await client.order.cancelAllOrders({
|
|
268
|
+
accountId: "main-binance",
|
|
269
|
+
exchange: "binance",
|
|
270
|
+
});
|
|
271
|
+
```
|
|
30
272
|
|
|
31
|
-
|
|
32
|
-
- `BINANCE_USDM_API_SECRET`
|
|
33
|
-
- `BINANCE_USDM_SYMBOL`
|
|
34
|
-
- `BINANCE_USDM_ORDER_SIZE`
|
|
35
|
-
- `BINANCE_USDM_ORDER_PRICE`
|
|
273
|
+
读取单个订单:
|
|
36
274
|
|
|
37
|
-
|
|
275
|
+
```ts
|
|
276
|
+
const order = client.order.getOrder({
|
|
277
|
+
accountId: "main-binance",
|
|
278
|
+
exchange: "binance",
|
|
279
|
+
clientOrderId: "demo-open-1",
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 健康状态和错误流
|
|
284
|
+
|
|
285
|
+
客户端状态:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
const status = client.getStatus();
|
|
289
|
+
const health = client.getHealth();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
监听 health:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
for await (const event of client.watchHealth()) {
|
|
296
|
+
console.log("health", event);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
监听内部错误:
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
for await (const event of client.watchErrors()) {
|
|
304
|
+
console.error("internal error", event);
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## 当前最值得记住的限制
|
|
309
|
+
|
|
310
|
+
- 这是 `Bun-only` SDK
|
|
311
|
+
- 当前 public 入口只接通了 `binance`
|
|
312
|
+
- 当前 public 入口只支持单账户
|
|
313
|
+
- 默认就是 `sandbox: true`
|
|
314
|
+
- symbol 使用 CCXT unified symbol,例如 `BTC/USDT:USDT`
|
|
315
|
+
- `createClient()` 适合直接接入;仓库里的 verification script 主要用于内部验收
|
|
38
316
|
|
|
39
|
-
##
|
|
317
|
+
## 当前已验证的路径
|
|
40
318
|
|
|
41
|
-
-
|
|
42
|
-
- Verified product: `USD-M`
|
|
43
|
-
- Verified environment: `demo trading / testnet-style`
|
|
44
|
-
- Verified date: `2026-03-31`
|
|
45
|
-
- Verified runtime paths: `subscribeL1Book`, `fetchAccountBaseline`, `fetchOpenOrdersBaseline`, market `placeOrder`, reduce-only market `placeOrder`
|
|
46
|
-
- Verified transports with direct evidence: `public WS (bookTicker)`, `private WS (runtime-level order confirmation + balance confirmation)`, `REST baseline`
|
|
47
|
-
- Supplementary low-level evidence: direct `ccxt.pro.binanceusdm.watchOrders()` and `watchBalance()` both returned during the real demo open/close verification flow on `2026-03-31`
|
|
48
|
-
- Deferred coverage: `amendOrder`, `cancelAllOrders`
|
|
319
|
+
截至 `2026-03-31`,Binance USD-M demo/testnet 已验证:
|
|
49
320
|
|
|
50
|
-
|
|
321
|
+
- `subscribeL1Book`
|
|
322
|
+
- `fetchAccountBaseline`
|
|
323
|
+
- `fetchOpenOrdersBaseline`
|
|
324
|
+
- market `placeOrder`
|
|
325
|
+
- reduce-only market `placeOrder`
|
|
326
|
+
- public WS
|
|
327
|
+
- private WS
|
|
328
|
+
- REST baseline
|
|
329
|
+
|
|
330
|
+
这意味着:
|
|
331
|
+
|
|
332
|
+
- README 里的最小接入流程是当前实现重点保障的使用方式
|
|
333
|
+
- `amendOrder` 和 `cancelAllOrders` 已有 API,但不属于首轮官方实盘验收重点
|
|
51
334
|
|
|
52
|
-
|
|
53
|
-
- `fetchOpenOrders()` without `symbol` requires `warnOnFetchOpenOrdersWithoutSymbol = false` on the CCXT Binance USD-M exchange instance.
|
|
54
|
-
- Under Bun + CCXT Pro, websocket handles can remain alive after verification. The CLI script now exits explicitly after emitting the result so the verification command terminates deterministically.
|
|
55
|
-
- A simple `place/cancel` flow was insufficient to trigger `watchBalance()` on Binance demo during the 2026-03-31 investigation; the verification script now uses a real market open followed by a reduce-only market close so balance private-WS confirmation is part of the success gate.
|
|
335
|
+
## 本地开发
|
|
56
336
|
|
|
57
|
-
|
|
337
|
+
安装依赖:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
bun install
|
|
341
|
+
```
|
|
58
342
|
|
|
59
|
-
|
|
343
|
+
常用命令:
|
|
60
344
|
|
|
61
345
|
```bash
|
|
62
|
-
bun run
|
|
346
|
+
bun run typecheck
|
|
347
|
+
bun test
|
|
348
|
+
bun run lint
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## 仓库里的验证脚本
|
|
352
|
+
|
|
353
|
+
如果你想直接验证 Binance demo/testnet 路径,可以跑:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
bun run scripts/verify-binance-usdm-testnet.ts
|
|
63
357
|
```
|
|
64
358
|
|
|
65
|
-
|
|
359
|
+
这个脚本更偏“仓库验收”,不是普通业务接入时必须使用的入口。
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { ExchangeAdapter, NormalizedAccountEvent, NormalizedMarketEvent, NormalizedOrderEvent } from "../types.js";
|
|
2
|
+
interface BinanceMarketInfoRecord {
|
|
3
|
+
exchange: string;
|
|
4
|
+
symbol: string;
|
|
5
|
+
baseAsset: string;
|
|
6
|
+
quoteAsset: string;
|
|
7
|
+
marketType: string;
|
|
8
|
+
pricePrecision: number;
|
|
9
|
+
amountPrecision: number;
|
|
10
|
+
active: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface BinanceCompositeMarketAdapter extends ExchangeAdapter {
|
|
13
|
+
fetchMarketInfo(): Promise<BinanceMarketInfoRecord[]>;
|
|
14
|
+
}
|
|
15
|
+
export declare class BinanceCompositeAdapter implements ExchangeAdapter {
|
|
16
|
+
private readonly input;
|
|
17
|
+
readonly exchange = "binance";
|
|
18
|
+
constructor(input: {
|
|
19
|
+
marketAdapter: BinanceCompositeMarketAdapter;
|
|
20
|
+
privateAdapter: ExchangeAdapter;
|
|
21
|
+
});
|
|
22
|
+
get capabilities(): {
|
|
23
|
+
publicWs: boolean;
|
|
24
|
+
l1BookStream: boolean;
|
|
25
|
+
fundingRateStream: boolean;
|
|
26
|
+
fetchMarketInfo: boolean;
|
|
27
|
+
privateWs: boolean;
|
|
28
|
+
accountStream: boolean;
|
|
29
|
+
orderStream: boolean;
|
|
30
|
+
fetchBalances: boolean;
|
|
31
|
+
fetchPositions: boolean;
|
|
32
|
+
fetchRisk: boolean;
|
|
33
|
+
fetchOpenOrders: boolean;
|
|
34
|
+
fetchMyTrades: boolean;
|
|
35
|
+
fetchOrderById: boolean;
|
|
36
|
+
};
|
|
37
|
+
start(): Promise<void>;
|
|
38
|
+
stop(): Promise<void>;
|
|
39
|
+
subscribeL1Book(input: {
|
|
40
|
+
exchange: string;
|
|
41
|
+
symbol: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
subscribeFundingRate(input: {
|
|
44
|
+
exchange: string;
|
|
45
|
+
symbol: string;
|
|
46
|
+
}): Promise<void>;
|
|
47
|
+
fetchMarketInfo(): Promise<BinanceMarketInfoRecord[]>;
|
|
48
|
+
watchMarketEvents(): AsyncIterable<NormalizedMarketEvent>;
|
|
49
|
+
setMarketEventSink(sink: ((event: NormalizedMarketEvent) => void) | undefined): void;
|
|
50
|
+
watchInternalErrors(): AsyncGenerator<Error, void, any>;
|
|
51
|
+
subscribeOrders(input: {
|
|
52
|
+
accountId: string;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
fetchOpenOrdersBaseline(accountId: string): Promise<({
|
|
55
|
+
accountId: string;
|
|
56
|
+
exchange: string;
|
|
57
|
+
symbol: string;
|
|
58
|
+
side: "buy" | "sell";
|
|
59
|
+
type: string;
|
|
60
|
+
status: string;
|
|
61
|
+
amount: string;
|
|
62
|
+
filled: string;
|
|
63
|
+
price?: string;
|
|
64
|
+
seq: number;
|
|
65
|
+
receivedAt: number;
|
|
66
|
+
updatedAt: number;
|
|
67
|
+
orderId?: string;
|
|
68
|
+
clientOrderId?: string;
|
|
69
|
+
} | {
|
|
70
|
+
accountId: string;
|
|
71
|
+
exchange: string;
|
|
72
|
+
symbol: string;
|
|
73
|
+
side: "buy" | "sell";
|
|
74
|
+
type: string;
|
|
75
|
+
status: string;
|
|
76
|
+
amount: string;
|
|
77
|
+
filled: string;
|
|
78
|
+
price?: string;
|
|
79
|
+
seq: number;
|
|
80
|
+
receivedAt: number;
|
|
81
|
+
updatedAt: number;
|
|
82
|
+
orderId?: string;
|
|
83
|
+
clientOrderId?: string;
|
|
84
|
+
})[]>;
|
|
85
|
+
watchOrderEvents(): AsyncIterable<NormalizedOrderEvent>;
|
|
86
|
+
setOrderEventSink(sink: ((event: NormalizedOrderEvent) => void) | undefined): void;
|
|
87
|
+
fetchAccountBaseline(accountId: string): Promise<import("../types.js").AdapterAccountBaseline>;
|
|
88
|
+
watchAccountEvents(): AsyncIterable<NormalizedAccountEvent>;
|
|
89
|
+
setAccountEventSink(sink: ((event: NormalizedAccountEvent) => void) | undefined): void;
|
|
90
|
+
placeOrder(input: Parameters<ExchangeAdapter["placeOrder"]>[0]): Promise<{
|
|
91
|
+
clientOrderId?: string;
|
|
92
|
+
orderId?: string;
|
|
93
|
+
receivedAt: number;
|
|
94
|
+
}>;
|
|
95
|
+
amendOrder(input: Parameters<ExchangeAdapter["amendOrder"]>[0]): Promise<{
|
|
96
|
+
clientOrderId?: string;
|
|
97
|
+
orderId?: string;
|
|
98
|
+
receivedAt: number;
|
|
99
|
+
}>;
|
|
100
|
+
cancelOrder(input: Parameters<ExchangeAdapter["cancelOrder"]>[0]): Promise<{
|
|
101
|
+
clientOrderId?: string;
|
|
102
|
+
orderId?: string;
|
|
103
|
+
receivedAt: number;
|
|
104
|
+
}>;
|
|
105
|
+
cancelAllOrders(input: Parameters<ExchangeAdapter["cancelAllOrders"]>[0]): Promise<{
|
|
106
|
+
accountId: string;
|
|
107
|
+
exchange: string;
|
|
108
|
+
canceledCount: number;
|
|
109
|
+
}>;
|
|
110
|
+
getHealth(): {
|
|
111
|
+
exchange: string;
|
|
112
|
+
status: string;
|
|
113
|
+
wsConnected: boolean;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createAsyncQueue } from "../../runtime/async-queue.js";
|
|
2
|
+
function toError(error) {
|
|
3
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
4
|
+
}
|
|
5
|
+
async function* mergeErrors(left, right) {
|
|
6
|
+
const queue = createAsyncQueue({ maxBufferSize: 20 });
|
|
7
|
+
let completedStreams = 0;
|
|
8
|
+
const forward = async (source) => {
|
|
9
|
+
try {
|
|
10
|
+
for await (const error of source) {
|
|
11
|
+
queue.push(error);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
queue.push(toError(error));
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
completedStreams += 1;
|
|
19
|
+
if (completedStreams === 2) {
|
|
20
|
+
queue.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
void forward(left);
|
|
25
|
+
void forward(right);
|
|
26
|
+
yield* queue;
|
|
27
|
+
}
|
|
28
|
+
export class BinanceCompositeAdapter {
|
|
29
|
+
input;
|
|
30
|
+
exchange = "binance";
|
|
31
|
+
constructor(input) {
|
|
32
|
+
this.input = input;
|
|
33
|
+
}
|
|
34
|
+
get capabilities() {
|
|
35
|
+
return {
|
|
36
|
+
...this.input.privateAdapter.capabilities,
|
|
37
|
+
publicWs: this.input.marketAdapter.capabilities.publicWs,
|
|
38
|
+
l1BookStream: this.input.marketAdapter.capabilities.l1BookStream,
|
|
39
|
+
fundingRateStream: this.input.marketAdapter.capabilities.fundingRateStream,
|
|
40
|
+
fetchMarketInfo: this.input.marketAdapter.capabilities.fetchMarketInfo,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async start() {
|
|
44
|
+
await this.input.marketAdapter.start();
|
|
45
|
+
try {
|
|
46
|
+
await this.input.privateAdapter.start();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
await this.input.marketAdapter.stop();
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async stop() {
|
|
54
|
+
await Promise.allSettled([this.input.marketAdapter.stop(), this.input.privateAdapter.stop()]);
|
|
55
|
+
}
|
|
56
|
+
async subscribeL1Book(input) {
|
|
57
|
+
return this.input.marketAdapter.subscribeL1Book(input);
|
|
58
|
+
}
|
|
59
|
+
async subscribeFundingRate(input) {
|
|
60
|
+
return this.input.marketAdapter.subscribeFundingRate(input);
|
|
61
|
+
}
|
|
62
|
+
async fetchMarketInfo() {
|
|
63
|
+
return this.input.marketAdapter.fetchMarketInfo();
|
|
64
|
+
}
|
|
65
|
+
watchMarketEvents() {
|
|
66
|
+
return this.input.marketAdapter.watchMarketEvents();
|
|
67
|
+
}
|
|
68
|
+
setMarketEventSink(sink) {
|
|
69
|
+
this.input.marketAdapter.setMarketEventSink?.(sink);
|
|
70
|
+
}
|
|
71
|
+
watchInternalErrors() {
|
|
72
|
+
return mergeErrors(this.input.marketAdapter.watchInternalErrors(), this.input.privateAdapter.watchInternalErrors());
|
|
73
|
+
}
|
|
74
|
+
async subscribeOrders(input) {
|
|
75
|
+
return this.input.privateAdapter.subscribeOrders(input);
|
|
76
|
+
}
|
|
77
|
+
async fetchOpenOrdersBaseline(accountId) {
|
|
78
|
+
return this.input.privateAdapter.fetchOpenOrdersBaseline(accountId);
|
|
79
|
+
}
|
|
80
|
+
watchOrderEvents() {
|
|
81
|
+
return this.input.privateAdapter.watchOrderEvents();
|
|
82
|
+
}
|
|
83
|
+
setOrderEventSink(sink) {
|
|
84
|
+
this.input.privateAdapter.setOrderEventSink?.(sink);
|
|
85
|
+
}
|
|
86
|
+
async fetchAccountBaseline(accountId) {
|
|
87
|
+
return this.input.privateAdapter.fetchAccountBaseline(accountId);
|
|
88
|
+
}
|
|
89
|
+
watchAccountEvents() {
|
|
90
|
+
return this.input.privateAdapter.watchAccountEvents();
|
|
91
|
+
}
|
|
92
|
+
setAccountEventSink(sink) {
|
|
93
|
+
this.input.privateAdapter.setAccountEventSink?.(sink);
|
|
94
|
+
}
|
|
95
|
+
async placeOrder(input) {
|
|
96
|
+
return this.input.privateAdapter.placeOrder(input);
|
|
97
|
+
}
|
|
98
|
+
async amendOrder(input) {
|
|
99
|
+
return this.input.privateAdapter.amendOrder(input);
|
|
100
|
+
}
|
|
101
|
+
async cancelOrder(input) {
|
|
102
|
+
return this.input.privateAdapter.cancelOrder(input);
|
|
103
|
+
}
|
|
104
|
+
async cancelAllOrders(input) {
|
|
105
|
+
return this.input.privateAdapter.cancelAllOrders(input);
|
|
106
|
+
}
|
|
107
|
+
getHealth() {
|
|
108
|
+
const market = this.input.marketAdapter.getHealth();
|
|
109
|
+
const privateHealth = this.input.privateAdapter.getHealth();
|
|
110
|
+
const status = market.status === "healthy" && privateHealth.status === "healthy"
|
|
111
|
+
? "healthy"
|
|
112
|
+
: market.status === "idle" && privateHealth.status === "idle"
|
|
113
|
+
? "idle"
|
|
114
|
+
: "degraded";
|
|
115
|
+
return {
|
|
116
|
+
exchange: this.exchange,
|
|
117
|
+
status,
|
|
118
|
+
wsConnected: market.wsConnected && privateHealth.wsConnected,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type BinanceMarketFamily = "spot" | "usdm" | "coinm";
|
|
2
|
+
export interface BinanceSymbolFilter {
|
|
3
|
+
filterType: string;
|
|
4
|
+
tickSize?: string;
|
|
5
|
+
stepSize?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BinanceSpotExchangeInfo {
|
|
8
|
+
symbols: Array<{
|
|
9
|
+
symbol: string;
|
|
10
|
+
status: string;
|
|
11
|
+
baseAsset: string;
|
|
12
|
+
quoteAsset: string;
|
|
13
|
+
filters: BinanceSymbolFilter[];
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export interface BinanceUsdmExchangeInfo {
|
|
17
|
+
symbols: Array<{
|
|
18
|
+
symbol: string;
|
|
19
|
+
pair: string;
|
|
20
|
+
status: string;
|
|
21
|
+
contractType: string;
|
|
22
|
+
baseAsset: string;
|
|
23
|
+
quoteAsset: string;
|
|
24
|
+
marginAsset: string;
|
|
25
|
+
pricePrecision: number;
|
|
26
|
+
quantityPrecision: number;
|
|
27
|
+
filters: BinanceSymbolFilter[];
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
export interface BinanceCoinmExchangeInfo {
|
|
31
|
+
symbols: Array<{
|
|
32
|
+
symbol: string;
|
|
33
|
+
pair: string;
|
|
34
|
+
contractType: string;
|
|
35
|
+
contractStatus: string;
|
|
36
|
+
baseAsset: string;
|
|
37
|
+
quoteAsset: string;
|
|
38
|
+
marginAsset: string;
|
|
39
|
+
deliveryDate?: number;
|
|
40
|
+
pricePrecision: number;
|
|
41
|
+
quantityPrecision: number;
|
|
42
|
+
filters: BinanceSymbolFilter[];
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export interface BinanceMarketRecord {
|
|
46
|
+
exchange: "binance";
|
|
47
|
+
family: BinanceMarketFamily;
|
|
48
|
+
nativeSymbol: string;
|
|
49
|
+
unifiedSymbol: string;
|
|
50
|
+
baseAsset: string;
|
|
51
|
+
quoteAsset: string;
|
|
52
|
+
settleAsset?: string;
|
|
53
|
+
contractType?: string;
|
|
54
|
+
fundingEligible: boolean;
|
|
55
|
+
active: boolean;
|
|
56
|
+
pricePrecision: number;
|
|
57
|
+
amountPrecision: number;
|
|
58
|
+
}
|
|
59
|
+
export interface BinanceMarketIndex {
|
|
60
|
+
byUnifiedSymbol: Map<string, BinanceMarketRecord>;
|
|
61
|
+
byNativeSymbol: Map<string, BinanceMarketRecord>;
|
|
62
|
+
markets: BinanceMarketRecord[];
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|