@imbingox/acex 0.3.0-beta.1 → 0.3.0-beta.3
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 +71 -24
- package/docs/api.md +1457 -0
- package/package.json +5 -2
- package/src/adapters/binance/adapter.ts +11 -2
- package/src/adapters/binance/market-catalog.ts +2 -2
- package/src/adapters/binance/private-adapter.ts +44 -4
- package/src/adapters/juplend/private-adapter.ts +517 -0
- package/src/adapters/types.ts +34 -4
- package/src/client/context.ts +16 -11
- package/src/client/private-subscription-coordinator.ts +101 -47
- package/src/client/runtime.ts +64 -20
- package/src/client/venue-capabilities.ts +109 -0
- package/src/errors.ts +1 -1
- package/src/internal/filters.ts +9 -9
- package/src/managers/account-manager.ts +95 -58
- package/src/managers/market-manager.ts +45 -45
- package/src/managers/order-manager.ts +49 -56
- package/src/types/account.ts +30 -10
- package/src/types/client.ts +73 -2
- package/src/types/market.ts +12 -16
- package/src/types/order.ts +7 -7
- package/src/types/shared.ts +43 -7
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`acex` 是一个面向交易场景的 **状态型** 多交易所 SDK。调用方持有一个 `AcexClient`,通过统一的 `market` / `account` / `order` manager 读取最新快照、消费增量事件、执行下单撤单命令;SDK 内部负责本地缓存、ready barrier、websocket 生命周期和自动重连,调用方不需要自己处理。
|
|
4
4
|
|
|
5
|
-
当前 MVP
|
|
5
|
+
当前 MVP 落地 Binance(Spot + USDⓈ-M + COIN-M 行情,PAPI UM 私有链路)以及 Juplend(Jupiter Lend 只读借贷账户视图)。
|
|
6
6
|
|
|
7
7
|
## 安装
|
|
8
8
|
|
|
@@ -21,12 +21,12 @@ const client = createClient();
|
|
|
21
21
|
await client.start();
|
|
22
22
|
|
|
23
23
|
await client.market.subscribeL1Book({
|
|
24
|
-
|
|
24
|
+
venue: "binance",
|
|
25
25
|
symbol: "BTC/USDT:USDT",
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
const book = client.market.getL1Book({
|
|
29
|
-
|
|
29
|
+
venue: "binance",
|
|
30
30
|
symbol: "BTC/USDT:USDT",
|
|
31
31
|
});
|
|
32
32
|
const books = client.market.getL1Books("BTC/USDT:USDT");
|
|
@@ -35,12 +35,12 @@ console.log(`venues=${books.length}`);
|
|
|
35
35
|
console.log(`book freshness=${book?.status.freshness}`);
|
|
36
36
|
|
|
37
37
|
await client.market.subscribeFundingRate({
|
|
38
|
-
|
|
38
|
+
venue: "binance",
|
|
39
39
|
symbol: "BTC/USDT:USDT",
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
const funding = client.market.getFundingRate({
|
|
43
|
-
|
|
43
|
+
venue: "binance",
|
|
44
44
|
symbol: "BTC/USDT:USDT",
|
|
45
45
|
});
|
|
46
46
|
const fundingRates = client.market.getFundingRates("BTC/USDT:USDT");
|
|
@@ -48,7 +48,7 @@ console.log(`funding=${funding?.fundingRate.toFixed()}`);
|
|
|
48
48
|
console.log(`funding venues=${fundingRates.length}`);
|
|
49
49
|
|
|
50
50
|
for await (const event of client.market.events.l1BookUpdates({
|
|
51
|
-
|
|
51
|
+
venue: "binance",
|
|
52
52
|
symbol: "BTC/USDT:USDT",
|
|
53
53
|
})) {
|
|
54
54
|
console.log(event.snapshot.bidPrice.toFixed());
|
|
@@ -58,48 +58,85 @@ for await (const event of client.market.events.l1BookUpdates({
|
|
|
58
58
|
await client.stop();
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
###
|
|
61
|
+
### 同一个 client 同时使用 Binance + Juplend
|
|
62
|
+
|
|
63
|
+
`createClient({ account: { juplend: { pollIntervalMs } } })` 只是配置 Juplend 账户的 polling 间隔,不代表这个 client 只能注册 Juplend。一个 `AcexClient` 可以同时注册 Binance 交易账户和 Juplend 借贷只读账户,用同一个 `AccountManager` 对比风险值。
|
|
62
64
|
|
|
63
65
|
```ts
|
|
64
|
-
const client = createClient(
|
|
66
|
+
const client = createClient({
|
|
67
|
+
account: {
|
|
68
|
+
juplend: {
|
|
69
|
+
pollIntervalMs: 30_000,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
65
73
|
await client.start();
|
|
66
74
|
|
|
67
75
|
await client.registerAccount({
|
|
68
76
|
accountId: "main-binance",
|
|
69
|
-
|
|
77
|
+
venue: "binance",
|
|
70
78
|
credentials: {
|
|
71
79
|
apiKey: process.env.BINANCE_PAPI_API_KEY,
|
|
72
80
|
secret: process.env.BINANCE_PAPI_SECRET,
|
|
73
81
|
},
|
|
74
82
|
});
|
|
75
83
|
|
|
84
|
+
await client.registerAccount({
|
|
85
|
+
accountId: "jup-loop-a",
|
|
86
|
+
venue: "juplend",
|
|
87
|
+
credentials: {
|
|
88
|
+
apiKey: process.env.JUPITER_API_KEY!,
|
|
89
|
+
},
|
|
90
|
+
options: {
|
|
91
|
+
walletAddress: "<solana-wallet-address>",
|
|
92
|
+
positionId: "<optional-nft-position-id>",
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
await client.account.subscribeAccount({ accountId: "jup-loop-a" });
|
|
76
97
|
await client.account.subscribeAccount({ accountId: "main-binance" });
|
|
77
98
|
await client.order.subscribeOrders({ accountId: "main-binance" });
|
|
78
99
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
side: "buy",
|
|
83
|
-
type: "limit",
|
|
84
|
-
price: "71830.6",
|
|
85
|
-
amount: "0.001",
|
|
86
|
-
});
|
|
100
|
+
const binanceRisk = client.account.getRiskSnapshot("main-binance");
|
|
101
|
+
const juplendRisk = client.account.getRiskSnapshot("jup-loop-a");
|
|
102
|
+
const juplendBalances = client.account.getBalances("jup-loop-a");
|
|
87
103
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
for (const balance of juplendBalances) {
|
|
105
|
+
console.log(balance.asset, balance.lending?.netAsset.toFixed());
|
|
106
|
+
}
|
|
107
|
+
console.log({
|
|
108
|
+
binanceRiskRatio: binanceRisk?.riskRatio?.toFixed(),
|
|
109
|
+
juplendRiskRatio: juplendRisk?.riskRatio?.toFixed(),
|
|
92
110
|
});
|
|
93
111
|
|
|
94
112
|
await client.stop();
|
|
95
113
|
```
|
|
96
114
|
|
|
115
|
+
Juplend 使用 Jupiter Portfolio API 读取 Solana 钱包的借贷仓位,不需要私钥,也不支持 supply / borrow / repay / withdraw 等写操作。`accountId` 是你自定义的 SDK 账户名;Solana 钱包地址放在 `options.walletAddress`。如果只想观察某个 Juplend NFT position,可传 `options.positionId`。
|
|
116
|
+
|
|
117
|
+
### 查询 venue 能力
|
|
118
|
+
|
|
119
|
+
`getVenueCapabilities()` 查询的是当前 SDK runtime 已实现能力,不是交易所官网完整能力,也不会检查 API key 是否有交易权限:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
const binance = client.getVenueCapabilities("binance");
|
|
123
|
+
console.log(binance.order.supported); // true
|
|
124
|
+
console.log(binance.market.fundingRate); // "market_dependent"
|
|
125
|
+
|
|
126
|
+
const juplend = client.getVenueCapabilities("juplend");
|
|
127
|
+
console.log(juplend.readOnly); // true
|
|
128
|
+
console.log(juplend.order.reason); // "read_only"
|
|
129
|
+
|
|
130
|
+
const capabilities = client.listVenueCapabilities();
|
|
131
|
+
```
|
|
132
|
+
|
|
97
133
|
价格、数量等输出字段统一是 `BigNumber`;`createOrder()` 的 `price` / `amount` 输入仍接受 decimal string。详见手册 [§3 核心概念](./docs/api.md#3-核心概念)。
|
|
98
134
|
|
|
99
135
|
## 核心能力
|
|
100
136
|
|
|
101
137
|
| 能力 | 概述 | 详细文档 |
|
|
102
138
|
|---|---|---|
|
|
139
|
+
| **Capabilities** | `getVenueCapabilities` / `listVenueCapabilities` 查询 SDK 当前 runtime 支持能力 | [docs/api.md §4](./docs/api.md#43-venue-capabilities) |
|
|
103
140
|
| **Market** | Market catalog、L1 Book / Funding Rate 订阅、增量事件、订阅状态与自动重连 | [docs/api.md §5](./docs/api.md#5-marketmanager) |
|
|
104
141
|
| **Account** | 账户快照、余额、持仓、风险投影与事件流 | [docs/api.md §6](./docs/api.md#6-accountmanager) |
|
|
105
142
|
| **Order** | open orders 投影、订单事件流,`createOrder` / `cancelOrder` / `cancelAllOrders` 第一版命令 | [docs/api.md §7](./docs/api.md#7-ordermanager) |
|
|
@@ -109,8 +146,9 @@ await client.stop();
|
|
|
109
146
|
|
|
110
147
|
## 当前限制
|
|
111
148
|
|
|
112
|
-
-
|
|
113
|
-
-
|
|
149
|
+
- 运行时 market/order 能力只支持 `binance`;`okx` / `bybit` / `gate` 仅类型定义
|
|
150
|
+
- 账户视图支持 Binance PAPI UM 与 Juplend 只读借贷账户
|
|
151
|
+
- Juplend 只读,不支持订单和链上写操作;token 数量来自 USD / oracle price 反算
|
|
114
152
|
- Funding Rate 仅支持 Binance 永续合约,来自 mark price websocket;不支持现货和交割合约
|
|
115
153
|
- `createOrder()` 只支持 `limit` / `market`;条件单、改单、账户级全撤不支持
|
|
116
154
|
- 双向持仓账户下单时必须显式传 `positionSide`
|
|
@@ -141,7 +179,7 @@ bun run test
|
|
|
141
179
|
|
|
142
180
|
- `tests/support/test-utils.ts`:通用 fake WebSocket、事件等待、Response helper 和全局清理。
|
|
143
181
|
- `tests/support/exchanges/binance.ts`:Binance 专用 REST/WS fixtures 与 installer。
|
|
144
|
-
- 新增交易所时,优先新增 `tests/support/exchanges/<
|
|
182
|
+
- 新增交易所时,优先新增 `tests/support/exchanges/<venue>.ts`,复用通用 helper,避免把交易所 payload 写进通用测试工具。
|
|
145
183
|
|
|
146
184
|
GitHub Actions 的 `CI` workflow 会在 PR 和 `main` push 时运行 lint、type-check、unit、integration;release workflow 继续复用 `bun run test`,不会执行 soak/live。
|
|
147
185
|
|
|
@@ -154,6 +192,7 @@ bun run test:live:market:smoke
|
|
|
154
192
|
bun run test:live:market:soak
|
|
155
193
|
bun run test:live:account:smoke
|
|
156
194
|
bun run test:live:account:soak
|
|
195
|
+
bun run test:live:juplend:smoke
|
|
157
196
|
bun run test:live:order:smoke
|
|
158
197
|
bun run test:live:order:soak
|
|
159
198
|
```
|
|
@@ -167,8 +206,16 @@ bun run test:live:order:soak
|
|
|
167
206
|
|
|
168
207
|
- `market`:`loadMarkets()`、`subscribeL1Book()`、`subscribeFundingRate()`、`getL1Book()` / `getL1Books()`、`getFundingRate()` / `getFundingRates()`、对应事件流和可选断线重连(`--disconnect-target funding` 可单独验证资金费率重连)
|
|
169
208
|
- `account`:Binance PAPI UM 账户 bootstrap、余额/仓位/风险投影、private stream 更新和可选重连
|
|
209
|
+
- `juplend`:Jupiter Portfolio API / vault 元数据连通性、lending balance facet、账户级 `riskRatio`、可选 `--position-id` 过滤单个 NFT position
|
|
170
210
|
- `order`:open orders bootstrap、`subscribeOrders()`、订单事件投影和可选重连
|
|
171
211
|
|
|
212
|
+
Juplend live smoke 示例:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
JUPITER_API_KEY=... JUPLEND_WALLET_ADDRESS=<wallet> bun run test:live:juplend -- --show-amounts
|
|
216
|
+
JUPITER_API_KEY=... bun run test:live:juplend -- --account-id jup-loop-a --wallet-address <wallet> --position-id <nftId> --show-amounts
|
|
217
|
+
```
|
|
218
|
+
|
|
172
219
|
### 发布流程
|
|
173
220
|
|
|
174
221
|
仓库使用 **Changesets + GitHub Actions + npm Trusted Publishing**:
|