@imbingox/acex 0.1.0 → 0.3.0-beta.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 (85) hide show
  1. package/README.md +96 -285
  2. package/index.ts +1 -0
  3. package/package.json +40 -23
  4. package/src/adapters/binance/adapter.ts +80 -0
  5. package/src/adapters/binance/book-ticker.ts +123 -0
  6. package/src/adapters/binance/mark-price.ts +126 -0
  7. package/src/adapters/binance/market-catalog.ts +258 -0
  8. package/src/adapters/binance/private-adapter.ts +833 -0
  9. package/src/adapters/types.ts +219 -0
  10. package/src/client/context.ts +123 -0
  11. package/src/client/create-client.ts +6 -0
  12. package/src/client/private-subscription-coordinator.ts +512 -0
  13. package/src/client/runtime.ts +410 -0
  14. package/src/errors.ts +27 -0
  15. package/src/index.ts +5 -0
  16. package/src/internal/async-event-bus.ts +100 -0
  17. package/src/internal/filters.ts +117 -0
  18. package/src/internal/managed-websocket.ts +280 -0
  19. package/src/managers/account-manager.ts +609 -0
  20. package/src/managers/market-manager.ts +912 -0
  21. package/src/managers/order-manager.ts +685 -0
  22. package/src/types/account.ts +157 -0
  23. package/src/types/client.ts +79 -0
  24. package/src/types/index.ts +5 -0
  25. package/src/types/market.ts +152 -0
  26. package/src/types/order.ts +177 -0
  27. package/src/types/shared.ts +93 -0
  28. package/dist/adapters/binance/composite-adapter.d.ts +0 -116
  29. package/dist/adapters/binance/composite-adapter.js +0 -121
  30. package/dist/adapters/binance/market-types.d.ts +0 -63
  31. package/dist/adapters/binance/market-types.js +0 -1
  32. package/dist/adapters/binance/native-market-adapter.d.ts +0 -102
  33. package/dist/adapters/binance/native-market-adapter.js +0 -455
  34. package/dist/adapters/binance/normalizers.d.ts +0 -8
  35. package/dist/adapters/binance/normalizers.js +0 -123
  36. package/dist/adapters/binance/rest-client.d.ts +0 -17
  37. package/dist/adapters/binance/rest-client.js +0 -66
  38. package/dist/adapters/binance/symbol-router.d.ts +0 -9
  39. package/dist/adapters/binance/symbol-router.js +0 -174
  40. package/dist/adapters/binance/ws-client.d.ts +0 -24
  41. package/dist/adapters/binance/ws-client.js +0 -261
  42. package/dist/adapters/ccxt/aster-ccxt-adapter.d.ts +0 -157
  43. package/dist/adapters/ccxt/aster-ccxt-adapter.js +0 -272
  44. package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.d.ts +0 -180
  45. package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.js +0 -539
  46. package/dist/adapters/ccxt/binance-usdm-exchange.d.ts +0 -22
  47. package/dist/adapters/ccxt/binance-usdm-exchange.js +0 -23
  48. package/dist/adapters/fake/fake-aster-adapter.d.ts +0 -130
  49. package/dist/adapters/fake/fake-aster-adapter.js +0 -283
  50. package/dist/adapters/types.d.ts +0 -210
  51. package/dist/adapters/types.js +0 -1
  52. package/dist/core/client.d.ts +0 -50
  53. package/dist/core/client.js +0 -403
  54. package/dist/core/recovery.d.ts +0 -22
  55. package/dist/core/recovery.js +0 -18
  56. package/dist/core/runtime.d.ts +0 -26
  57. package/dist/core/runtime.js +0 -150
  58. package/dist/errors/acex-error.d.ts +0 -25
  59. package/dist/errors/acex-error.js +0 -54
  60. package/dist/index.d.ts +0 -6
  61. package/dist/index.js +0 -3
  62. package/dist/managers/account-manager.d.ts +0 -41
  63. package/dist/managers/account-manager.js +0 -80
  64. package/dist/managers/market-manager.d.ts +0 -16
  65. package/dist/managers/market-manager.js +0 -28
  66. package/dist/managers/order-manager.d.ts +0 -87
  67. package/dist/managers/order-manager.js +0 -122
  68. package/dist/runtime/async-queue.d.ts +0 -8
  69. package/dist/runtime/async-queue.js +0 -88
  70. package/dist/runtime/request-id.d.ts +0 -1
  71. package/dist/runtime/request-id.js +0 -5
  72. package/dist/runtime/ws-connection-supervisor.d.ts +0 -76
  73. package/dist/runtime/ws-connection-supervisor.js +0 -522
  74. package/dist/store/account-store.d.ts +0 -52
  75. package/dist/store/account-store.js +0 -18
  76. package/dist/store/health-store.d.ts +0 -16
  77. package/dist/store/health-store.js +0 -29
  78. package/dist/store/market-store.d.ts +0 -42
  79. package/dist/store/market-store.js +0 -51
  80. package/dist/store/order-store.d.ts +0 -38
  81. package/dist/store/order-store.js +0 -49
  82. package/dist/testing/create-fake-runtime.d.ts +0 -5
  83. package/dist/testing/create-fake-runtime.js +0 -7
  84. package/dist/types/public.d.ts +0 -5
  85. package/dist/types/public.js +0 -1
package/README.md CHANGED
@@ -1,25 +1,8 @@
1
- # acex
1
+ # @imbingox/acex
2
2
 
3
- `acex` 是一个面向 Bun 的交易 SDK
3
+ `acex` 是一个面向交易场景的 **状态型** 多交易所 SDK。调用方持有一个 `AcexClient`,通过统一的 `market` / `account` / `order` manager 读取最新快照、消费增量事件、执行下单撤单命令;SDK 内部负责本地缓存、ready barrier、websocket 生命周期和自动重连,调用方不需要自己处理。
4
4
 
5
- 当前 public `createClient()` 的可用范围是:
6
-
7
- - 只支持 `binance`
8
- - 只支持单账户
9
- - 默认走 `sandbox: true`
10
- - 当前官方验证环境是 Binance USD-M demo/testnet
11
-
12
- 当前 Binance 路径分为两层:
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 路径
17
-
18
- 包名:
19
-
20
- ```bash
21
- @imbingox/acex
22
- ```
5
+ 当前 MVP 只落地 Binance(Spot + USDⓈ-M + COIN-M 行情,PAPI UM 私有链路)。
23
6
 
24
7
  ## 安装
25
8
 
@@ -27,333 +10,161 @@
27
10
  bun add @imbingox/acex
28
11
  ```
29
12
 
30
- ## 你会怎么用它
31
-
32
- 典型流程只有 5 步:
13
+ ## 快速上手
33
14
 
34
- 1. `createClient()` 创建客户端
35
- 2. `registerAccount()` 注册账户
36
- 3. `start()` 启动运行时
37
- 4. `subscribe...()` 建立你关心的数据订阅
38
- 5. 用 `get...()` 读取当前最新快照,或用下单 API 发命令
39
-
40
- ## 最小示例
41
-
42
- 下面这段就是当前推荐的接入方式:
15
+ ### 行情(无需凭证)
43
16
 
44
17
  ```ts
45
18
  import { createClient } from "@imbingox/acex";
46
19
 
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
20
+ const client = createClient();
150
21
  await client.start();
151
- ```
152
-
153
- `start()` 之后,SDK 才会真正建立底层 runtime。
154
22
 
155
- 如果你在 `start()` 之前调用:
156
-
157
- - `subscribeL1Book()`
158
- - `subscribeAccount()`
159
- - `subscribeOrders()`
160
- - 下单相关 API
161
-
162
- 会直接抛错。
163
-
164
- ### 4. 订阅你要的数据
165
-
166
- 行情:
167
-
168
- ```ts
169
23
  await client.market.subscribeL1Book({
170
24
  exchange: "binance",
171
- symbol: "BTC/USDT",
25
+ symbol: "BTC/USDT:USDT",
172
26
  });
173
27
 
174
- await client.market.subscribeL1Book({
28
+ const book = client.market.getL1Book({
175
29
  exchange: "binance",
176
30
  symbol: "BTC/USDT:USDT",
177
31
  });
32
+ const books = client.market.getL1Books("BTC/USDT:USDT");
33
+ console.log(`bid=${book?.bidPrice.toFixed()} ask=${book?.askPrice.toFixed()}`);
34
+ console.log(`venues=${books.length}`);
35
+ console.log(`book freshness=${book?.status.freshness}`);
178
36
 
179
37
  await client.market.subscribeFundingRate({
180
38
  exchange: "binance",
181
39
  symbol: "BTC/USDT:USDT",
182
40
  });
183
- ```
184
-
185
- 账户基线:
186
-
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
41
 
206
- ### 5. 读取最新快照
207
-
208
- 行情快照:
209
-
210
- ```ts
211
- const book = client.market.getL1Book({
42
+ const funding = client.market.getFundingRate({
212
43
  exchange: "binance",
213
44
  symbol: "BTC/USDT:USDT",
214
45
  });
215
- ```
46
+ const fundingRates = client.market.getFundingRates("BTC/USDT:USDT");
47
+ console.log(`funding=${funding?.fundingRate.toFixed()}`);
48
+ console.log(`funding venues=${fundingRates.length}`);
216
49
 
217
- 账户快照:
50
+ for await (const event of client.market.events.l1BookUpdates({
51
+ exchange: "binance",
52
+ symbol: "BTC/USDT:USDT",
53
+ })) {
54
+ console.log(event.snapshot.bidPrice.toFixed());
55
+ break;
56
+ }
218
57
 
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");
58
+ await client.stop();
224
59
  ```
225
60
 
226
- 订单投影:
61
+ ### 账户与订单
227
62
 
228
63
  ```ts
229
- const openOrders = client.order.getOpenOrders("main-binance");
230
- const orderStatus = client.order.getOrderStatus("main-binance");
231
- ```
64
+ const client = createClient();
65
+ await client.start();
232
66
 
233
- ## 下单相关 API
67
+ await client.registerAccount({
68
+ accountId: "main-binance",
69
+ exchange: "binance",
70
+ credentials: {
71
+ apiKey: process.env.BINANCE_PAPI_API_KEY,
72
+ secret: process.env.BINANCE_PAPI_SECRET,
73
+ },
74
+ });
234
75
 
235
- 当前 public API 已暴露这些命令:
76
+ await client.account.subscribeAccount({ accountId: "main-binance" });
77
+ await client.order.subscribeOrders({ accountId: "main-binance" });
236
78
 
237
- ```ts
238
- await client.order.placeOrder({
79
+ const created = await client.order.createOrder({
239
80
  accountId: "main-binance",
240
- exchange: "binance",
241
81
  symbol: "BTC/USDT:USDT",
242
82
  side: "buy",
83
+ type: "limit",
84
+ price: "71830.6",
243
85
  amount: "0.001",
244
- clientOrderId: "demo-open-1",
245
- type: "market",
246
86
  });
247
- ```
248
87
 
249
- ```ts
250
88
  await client.order.cancelOrder({
251
89
  accountId: "main-binance",
252
- exchange: "binance",
253
- clientOrderId: "demo-open-1",
90
+ symbol: "BTC/USDT:USDT",
91
+ orderId: created.orderId,
254
92
  });
255
- ```
256
93
 
257
- ```ts
258
- await client.order.amendOrder({
259
- accountId: "main-binance",
260
- exchange: "binance",
261
- clientOrderId: "demo-open-1",
262
- newPrice: "65000",
263
- });
94
+ await client.stop();
264
95
  ```
265
96
 
266
- ```ts
267
- await client.order.cancelAllOrders({
268
- accountId: "main-binance",
269
- exchange: "binance",
270
- });
271
- ```
272
-
273
- 读取单个订单:
274
-
275
- ```ts
276
- const order = client.order.getOrder({
277
- accountId: "main-binance",
278
- exchange: "binance",
279
- clientOrderId: "demo-open-1",
280
- });
281
- ```
97
+ 价格、数量等输出字段统一是 `BigNumber`;`createOrder()` 的 `price` / `amount` 输入仍接受 decimal string。详见手册 [§3 核心概念](./docs/api.md#3-核心概念)。
282
98
 
283
- ## 健康状态和错误流
99
+ ## 核心能力
284
100
 
285
- 客户端状态:
101
+ | 能力 | 概述 | 详细文档 |
102
+ |---|---|---|
103
+ | **Market** | Market catalog、L1 Book / Funding Rate 订阅、增量事件、订阅状态与自动重连 | [docs/api.md §5](./docs/api.md#5-marketmanager) |
104
+ | **Account** | 账户快照、余额、持仓、风险投影与事件流 | [docs/api.md §6](./docs/api.md#6-accountmanager) |
105
+ | **Order** | open orders 投影、订单事件流,`createOrder` / `cancelOrder` / `cancelAllOrders` 第一版命令 | [docs/api.md §7](./docs/api.md#7-ordermanager) |
106
+ | **健康与错误** | `getHealth()`、`events.health()`、`events.errors()` | [docs/api.md §8](./docs/api.md#8-健康与错误事件) |
286
107
 
287
- ```ts
288
- const status = client.getStatus();
289
- const health = client.getHealth();
290
- ```
108
+ 完整手册(接口签名、数据类型、错误码):[docs/api.md](./docs/api.md)。
291
109
 
292
- 监听 health:
110
+ ## 当前限制
293
111
 
294
- ```ts
295
- for await (const event of client.watchHealth()) {
296
- console.log("health", event);
297
- }
298
- ```
112
+ - 运行时只支持 `binance`;`okx` / `bybit` / `gate` 仅类型定义
113
+ - 私有链路仅 Binance PAPI UM(统一账户 / Portfolio Margin)
114
+ - Funding Rate 仅支持 Binance 永续合约,来自 mark price websocket;不支持现货和交割合约
115
+ - `createOrder()` 只支持 `limit` / `market`;条件单、改单、账户级全撤不支持
116
+ - 双向持仓账户下单时必须显式传 `positionSide`
117
+ - `CreateClientOptions` 中 `sandbox` / `logger` / `logLevel` 是预留位
299
118
 
300
- 监听内部错误:
119
+ ## 仓库内开发
301
120
 
302
- ```ts
303
- for await (const event of client.watchErrors()) {
304
- console.error("internal error", event);
305
- }
121
+ ```bash
122
+ bun install
123
+ bun run lint
124
+ bun run type-check
125
+ bun run test
306
126
  ```
307
127
 
308
- ## 当前最值得记住的限制
128
+ ### 真实环境 smoke / soak 脚本
309
129
 
310
- - 这是 `Bun-only` SDK
311
- - 当前 public 入口只接通了 `binance`
312
- - 当前 public 入口只支持单账户
313
- - 默认就是 `sandbox: true`
314
- - symbol 使用 CCXT unified symbol,例如 `BTC/USDT:USDT`
315
- - `createClient()` 适合直接接入;仓库里的 verification script 主要用于内部验收
130
+ 不进默认 `bun run test`,单独执行:
316
131
 
317
- ## 当前已验证的路径
132
+ ```bash
133
+ bun run test:live:market:smoke
134
+ bun run test:live:market:soak
135
+ bun run test:live:account:smoke
136
+ bun run test:live:account:soak
137
+ bun run test:live:order:smoke
138
+ bun run test:live:order:soak
139
+ ```
318
140
 
319
- 截至 `2026-03-31`,Binance USD-M demo/testnet 已验证:
141
+ 约定:
320
142
 
321
- - `subscribeL1Book`
322
- - `fetchAccountBaseline`
323
- - `fetchOpenOrdersBaseline`
324
- - market `placeOrder`
325
- - reduce-only market `placeOrder`
326
- - public WS
327
- - private WS
328
- - REST baseline
143
+ - `smoke` 默认跑 10 秒,做连通性检查,不主动断线
144
+ - `soak` 默认跑 60 秒,并做一次主动断线重连验证
329
145
 
330
- 这意味着:
146
+ 覆盖内容:
331
147
 
332
- - README 里的最小接入流程是当前实现重点保障的使用方式
333
- - `amendOrder` `cancelAllOrders` 已有 API,但不属于首轮官方实盘验收重点
148
+ - `market`:`loadMarkets()`、`subscribeL1Book()`、`subscribeFundingRate()`、`getL1Book()` / `getL1Books()`、`getFundingRate()` / `getFundingRates()`、对应事件流和可选断线重连(`--disconnect-target funding` 可单独验证资金费率重连)
149
+ - `account`:Binance PAPI UM 账户 bootstrap、余额/仓位/风险投影、private stream 更新和可选重连
150
+ - `order`:open orders bootstrap、`subscribeOrders()`、订单事件投影和可选重连
334
151
 
335
- ## 本地开发
152
+ ### 发布流程
336
153
 
337
- 安装依赖:
154
+ 仓库使用 **Changesets + GitHub Actions + npm Trusted Publishing**:
338
155
 
339
- ```bash
340
- bun install
341
- ```
156
+ 1. 开发 PR 时,如果改动影响用户,执行 `bun run changeset`
157
+ 2. 按提示选择 `patch` / `minor` / `major`,写一段对外 release note
158
+ 3. PR merge 到 `main` 后,[release.yml](./.github/workflows/release.yml) 会:
159
+ - 安装依赖
160
+ - 跑 `bun run lint` / `bun run type-check` / `bun run test`
161
+ - 若有未消费的 changeset,创建或更新 release PR
162
+ 4. merge release PR 后,同一 workflow 自动发布到 npm
342
163
 
343
- 常用命令:
164
+ 当前仓库处于 Changesets 的 `beta` prerelease 模式,自动发布默认走 npm `beta` dist-tag。
344
165
 
345
- ```bash
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
357
- ```
166
+ npm 侧配置 Trusted Publisher 要求:
358
167
 
359
- 这个脚本更偏“仓库验收”,不是普通业务接入时必须使用的入口。
168
+ - workflow 文件名是 `release.yml`
169
+ - `package.json.repository.url` 直接写仓库地址,例如 `https://github.com/imbingox/acex`
170
+ - npm 包 settings 绑定 GitHub Actions trusted publisher,不使用长期 `NPM_TOKEN`
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index.ts";
package/package.json CHANGED
@@ -1,34 +1,51 @@
1
1
  {
2
2
  "name": "@imbingox/acex",
3
- "version": "0.1.0",
4
- "private": false,
3
+ "version": "0.3.0-beta.0",
4
+ "description": "Multi-exchange trading SDK for market data, account, and order management",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/imbingox/acex.git"
8
+ },
9
+ "module": "index.ts",
5
10
  "type": "module",
6
- "packageManager": "bun@1.2.8",
11
+ "exports": {
12
+ ".": "./index.ts"
13
+ },
7
14
  "publishConfig": {
8
15
  "access": "public"
9
16
  },
10
- "files": ["dist"],
11
- "main": "./dist/index.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js"
17
- }
18
- },
17
+ "files": [
18
+ "index.ts",
19
+ "src/"
20
+ ],
19
21
  "scripts": {
20
- "build": "tsc -p tsconfig.json",
21
- "typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
22
- "test": "bun test",
23
- "lint": "biome check package.json tsconfig.json src tests",
24
- "format": "biome format --write ."
25
- },
26
- "dependencies": {
27
- "ccxt": "^4.5.45"
22
+ "changeset": "changeset",
23
+ "changeset:pre:enter:beta": "changeset pre enter beta && if [ -f .changeset/pre.json ]; then biome check --write .changeset/pre.json; fi",
24
+ "changeset:pre:exit": "changeset pre exit && if [ -f .changeset/pre.json ]; then biome check --write .changeset/pre.json; fi",
25
+ "lint": "biome check .",
26
+ "lint:fix": "biome check --write .",
27
+ "release": "changeset publish",
28
+ "type-check": "tsc --noEmit",
29
+ "test": "bun test --max-concurrency=1",
30
+ "test:live:account": "bun run scripts/live-account-smoke.ts",
31
+ "test:live:account:smoke": "bun run scripts/live-account-smoke.ts --duration 10",
32
+ "test:live:account:soak": "bun run scripts/live-account-smoke.ts --duration 60 --disconnect-after 5",
33
+ "test:live:market": "bun run scripts/live-market-smoke.ts",
34
+ "test:live:market:smoke": "bun run scripts/live-market-smoke.ts --duration 10",
35
+ "test:live:market:soak": "bun run scripts/live-market-smoke.ts --duration 60 --disconnect-after 5 --disconnect-target perp",
36
+ "test:live:order": "bun run scripts/live-order-smoke.ts",
37
+ "test:live:order:smoke": "bun run scripts/live-order-smoke.ts --duration 10",
38
+ "test:live:order:soak": "bun run scripts/live-order-smoke.ts --duration 60 --disconnect-after 5",
39
+ "version-packages": "changeset version && files=\"package.json\"; if [ -f .changeset/pre.json ]; then files=\"$files .changeset/pre.json\"; fi; if [ -f CHANGELOG.md ]; then files=\"$files CHANGELOG.md\"; fi; biome check --write $files"
28
40
  },
29
41
  "devDependencies": {
30
- "@biomejs/biome": "^1.9.4",
31
- "typescript": "^5.8.2",
32
- "bun-types": "^1.3.11"
42
+ "@biomejs/biome": "^2.4.10",
43
+ "@changesets/cli": "^2.31.0",
44
+ "@types/bun": "latest",
45
+ "typescript": "^6.0.2"
46
+ },
47
+ "dependencies": {
48
+ "@mindfoldhq/trellis": "^0.4.0",
49
+ "bignumber.js": "^11.0.0"
33
50
  }
34
51
  }
@@ -0,0 +1,80 @@
1
+ import type { MarketDefinition } from "../../types/index.ts";
2
+ import type {
3
+ FundingRateStreamCallbacks,
4
+ FundingRateStreamOptions,
5
+ L1BookStreamCallbacks,
6
+ L1BookStreamOptions,
7
+ MarketAdapter,
8
+ StreamHandle,
9
+ } from "../types.ts";
10
+ import { subscribeBinanceBookTicker } from "./book-ticker.ts";
11
+ import { subscribeBinanceMarkPrice } from "./mark-price.ts";
12
+ import {
13
+ type BinanceMarketDefinition,
14
+ loadBinanceMarkets,
15
+ } from "./market-catalog.ts";
16
+
17
+ export class BinanceMarketAdapter implements MarketAdapter {
18
+ readonly exchange = "binance" as const;
19
+
20
+ private readonly definitions = new Map<string, BinanceMarketDefinition>();
21
+
22
+ async loadMarkets(): Promise<MarketDefinition[]> {
23
+ const markets = await loadBinanceMarkets();
24
+ this.definitions.clear();
25
+
26
+ for (const market of markets) {
27
+ this.definitions.set(market.symbol, market);
28
+ }
29
+
30
+ return markets;
31
+ }
32
+
33
+ createL1BookStream(
34
+ market: MarketDefinition,
35
+ callbacks: L1BookStreamCallbacks,
36
+ options: L1BookStreamOptions,
37
+ ): StreamHandle {
38
+ const binanceMarket = this.definitions.get(market.symbol);
39
+ if (!binanceMarket) {
40
+ throw new Error(`Unknown Binance market: ${market.symbol}`);
41
+ }
42
+
43
+ return subscribeBinanceBookTicker(
44
+ binanceMarket,
45
+ {
46
+ onBookTicker(update) {
47
+ callbacks.onUpdate(update);
48
+ },
49
+ onFreshnessChange: callbacks.onFreshnessChange,
50
+ onDisconnected: callbacks.onDisconnected,
51
+ onError: callbacks.onError,
52
+ },
53
+ options,
54
+ );
55
+ }
56
+
57
+ createFundingRateStream(
58
+ market: MarketDefinition,
59
+ callbacks: FundingRateStreamCallbacks,
60
+ options: FundingRateStreamOptions,
61
+ ): StreamHandle {
62
+ const binanceMarket = this.definitions.get(market.symbol);
63
+ if (!binanceMarket) {
64
+ throw new Error(`Unknown Binance market: ${market.symbol}`);
65
+ }
66
+
67
+ return subscribeBinanceMarkPrice(
68
+ binanceMarket,
69
+ {
70
+ onFundingRate(update) {
71
+ callbacks.onUpdate(update);
72
+ },
73
+ onFreshnessChange: callbacks.onFreshnessChange,
74
+ onDisconnected: callbacks.onDisconnected,
75
+ onError: callbacks.onError,
76
+ },
77
+ options,
78
+ );
79
+ }
80
+ }