@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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `acex` 是一个面向交易场景的 **状态型** 多交易所 SDK。调用方持有一个 `AcexClient`,通过统一的 `market` / `account` / `order` manager 读取最新快照、消费增量事件、执行下单撤单命令;SDK 内部负责本地缓存、ready barrier、websocket 生命周期和自动重连,调用方不需要自己处理。
4
4
 
5
- 当前 MVP 只落地 Binance(Spot + USDⓈ-M + COIN-M 行情,PAPI UM 私有链路)。
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
- exchange: "binance",
24
+ venue: "binance",
25
25
  symbol: "BTC/USDT:USDT",
26
26
  });
27
27
 
28
28
  const book = client.market.getL1Book({
29
- exchange: "binance",
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
- exchange: "binance",
38
+ venue: "binance",
39
39
  symbol: "BTC/USDT:USDT",
40
40
  });
41
41
 
42
42
  const funding = client.market.getFundingRate({
43
- exchange: "binance",
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
- exchange: "binance",
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
- exchange: "binance",
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 created = await client.order.createOrder({
80
- accountId: "main-binance",
81
- symbol: "BTC/USDT:USDT",
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
- await client.order.cancelOrder({
89
- accountId: "main-binance",
90
- symbol: "BTC/USDT:USDT",
91
- orderId: created.orderId,
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
- - 运行时只支持 `binance`;`okx` / `bybit` / `gate` 仅类型定义
113
- - 私有链路仅 Binance PAPI UM(统一账户 / Portfolio Margin)
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/<exchange>.ts`,复用通用 helper,避免把交易所 payload 写进通用测试工具。
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**: