@imbingox/acex 0.1.0 → 0.2.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 +92 -285
- package/index.ts +1 -0
- package/package.json +40 -23
- package/src/adapters/binance/adapter.ts +80 -0
- package/src/adapters/binance/book-ticker.ts +123 -0
- package/src/adapters/binance/mark-price.ts +126 -0
- package/src/adapters/binance/market-catalog.ts +258 -0
- package/src/adapters/binance/private-adapter.ts +833 -0
- package/src/adapters/types.ts +219 -0
- package/src/client/context.ts +123 -0
- package/src/client/create-client.ts +6 -0
- package/src/client/private-subscription-coordinator.ts +512 -0
- package/src/client/runtime.ts +410 -0
- package/src/errors.ts +27 -0
- package/src/index.ts +5 -0
- package/src/internal/async-event-bus.ts +100 -0
- package/src/internal/filters.ts +117 -0
- package/src/internal/managed-websocket.ts +280 -0
- package/src/managers/account-manager.ts +609 -0
- package/src/managers/market-manager.ts +889 -0
- package/src/managers/order-manager.ts +685 -0
- package/src/types/account.ts +157 -0
- package/src/types/client.ts +79 -0
- package/src/types/index.ts +5 -0
- package/src/types/market.ts +150 -0
- package/src/types/order.ts +177 -0
- package/src/types/shared.ts +93 -0
- package/dist/adapters/binance/composite-adapter.d.ts +0 -116
- package/dist/adapters/binance/composite-adapter.js +0 -121
- package/dist/adapters/binance/market-types.d.ts +0 -63
- package/dist/adapters/binance/market-types.js +0 -1
- package/dist/adapters/binance/native-market-adapter.d.ts +0 -102
- package/dist/adapters/binance/native-market-adapter.js +0 -455
- package/dist/adapters/binance/normalizers.d.ts +0 -8
- package/dist/adapters/binance/normalizers.js +0 -123
- package/dist/adapters/binance/rest-client.d.ts +0 -17
- package/dist/adapters/binance/rest-client.js +0 -66
- package/dist/adapters/binance/symbol-router.d.ts +0 -9
- package/dist/adapters/binance/symbol-router.js +0 -174
- package/dist/adapters/binance/ws-client.d.ts +0 -24
- package/dist/adapters/binance/ws-client.js +0 -261
- package/dist/adapters/ccxt/aster-ccxt-adapter.d.ts +0 -157
- package/dist/adapters/ccxt/aster-ccxt-adapter.js +0 -272
- package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.d.ts +0 -180
- package/dist/adapters/ccxt/binance-usdm-ccxt-adapter.js +0 -539
- package/dist/adapters/ccxt/binance-usdm-exchange.d.ts +0 -22
- package/dist/adapters/ccxt/binance-usdm-exchange.js +0 -23
- package/dist/adapters/fake/fake-aster-adapter.d.ts +0 -130
- package/dist/adapters/fake/fake-aster-adapter.js +0 -283
- package/dist/adapters/types.d.ts +0 -210
- package/dist/adapters/types.js +0 -1
- package/dist/core/client.d.ts +0 -50
- package/dist/core/client.js +0 -403
- package/dist/core/recovery.d.ts +0 -22
- package/dist/core/recovery.js +0 -18
- package/dist/core/runtime.d.ts +0 -26
- package/dist/core/runtime.js +0 -150
- package/dist/errors/acex-error.d.ts +0 -25
- package/dist/errors/acex-error.js +0 -54
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -3
- package/dist/managers/account-manager.d.ts +0 -41
- package/dist/managers/account-manager.js +0 -80
- package/dist/managers/market-manager.d.ts +0 -16
- package/dist/managers/market-manager.js +0 -28
- package/dist/managers/order-manager.d.ts +0 -87
- package/dist/managers/order-manager.js +0 -122
- package/dist/runtime/async-queue.d.ts +0 -8
- package/dist/runtime/async-queue.js +0 -88
- package/dist/runtime/request-id.d.ts +0 -1
- package/dist/runtime/request-id.js +0 -5
- package/dist/runtime/ws-connection-supervisor.d.ts +0 -76
- package/dist/runtime/ws-connection-supervisor.js +0 -522
- package/dist/store/account-store.d.ts +0 -52
- package/dist/store/account-store.js +0 -18
- package/dist/store/health-store.d.ts +0 -16
- package/dist/store/health-store.js +0 -29
- package/dist/store/market-store.d.ts +0 -42
- package/dist/store/market-store.js +0 -51
- package/dist/store/order-store.d.ts +0 -38
- package/dist/store/order-store.js +0 -49
- package/dist/testing/create-fake-runtime.d.ts +0 -5
- package/dist/testing/create-fake-runtime.js +0 -7
- package/dist/types/public.d.ts +0 -5
- package/dist/types/public.js +0 -1
|
@@ -1,539 +0,0 @@
|
|
|
1
|
-
import { createAsyncQueue } from "../../runtime/async-queue.js";
|
|
2
|
-
export class CcxtBinanceUsdMAdapter {
|
|
3
|
-
exchange = "binance";
|
|
4
|
-
capabilities = {
|
|
5
|
-
publicWs: true,
|
|
6
|
-
privateWs: true,
|
|
7
|
-
l1BookStream: true,
|
|
8
|
-
fundingRateStream: true,
|
|
9
|
-
accountStream: true,
|
|
10
|
-
orderStream: true,
|
|
11
|
-
fetchMarketInfo: true,
|
|
12
|
-
fetchBalances: true,
|
|
13
|
-
fetchPositions: true,
|
|
14
|
-
fetchRisk: true,
|
|
15
|
-
fetchOpenOrders: true,
|
|
16
|
-
fetchMyTrades: true,
|
|
17
|
-
fetchOrderById: true,
|
|
18
|
-
};
|
|
19
|
-
#exchange;
|
|
20
|
-
#accountId;
|
|
21
|
-
#started = false;
|
|
22
|
-
#privateWatchTasks = new Set();
|
|
23
|
-
#orderSymbolsByClientOrderId = new Map();
|
|
24
|
-
#orderSymbolsByOrderId = new Map();
|
|
25
|
-
#marketQueue = createAsyncQueue({ maxBufferSize: 100 });
|
|
26
|
-
#marketEventSink;
|
|
27
|
-
#internalErrorQueue = createAsyncQueue({ maxBufferSize: 20 });
|
|
28
|
-
#orderQueue = createAsyncQueue({ maxBufferSize: 100 });
|
|
29
|
-
#orderEventSink;
|
|
30
|
-
#accountQueue = createAsyncQueue({ maxBufferSize: 100 });
|
|
31
|
-
#accountEventSink;
|
|
32
|
-
constructor(input) {
|
|
33
|
-
this.#exchange = input.exchange;
|
|
34
|
-
this.#accountId = input.accountId ?? "main";
|
|
35
|
-
}
|
|
36
|
-
async start() {
|
|
37
|
-
this.#started = true;
|
|
38
|
-
const privateStreams = this.#exchange;
|
|
39
|
-
if (privateStreams.watchOrders !== undefined) {
|
|
40
|
-
this.#trackPrivateWatchTask(this.#runWatchOrders(privateStreams));
|
|
41
|
-
}
|
|
42
|
-
if (privateStreams.watchBalance !== undefined) {
|
|
43
|
-
this.#trackPrivateWatchTask(this.#runWatchBalance(privateStreams));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async stop() {
|
|
47
|
-
this.#started = false;
|
|
48
|
-
await this.#exchange.close?.();
|
|
49
|
-
await Promise.allSettled([...this.#privateWatchTasks]);
|
|
50
|
-
this.#marketQueue.close();
|
|
51
|
-
this.#internalErrorQueue.close();
|
|
52
|
-
this.#orderQueue.close();
|
|
53
|
-
this.#accountQueue.close();
|
|
54
|
-
}
|
|
55
|
-
async subscribeL1Book(input) {
|
|
56
|
-
try {
|
|
57
|
-
const snapshot = await this.mapTickerToL1(input.symbol);
|
|
58
|
-
this.#emitMarketEvent({
|
|
59
|
-
type: "l1_book.updated",
|
|
60
|
-
exchange: snapshot.exchange,
|
|
61
|
-
symbol: snapshot.symbol,
|
|
62
|
-
bidPrice: snapshot.bidPrice,
|
|
63
|
-
bidSize: snapshot.bidSize,
|
|
64
|
-
askPrice: snapshot.askPrice,
|
|
65
|
-
askSize: snapshot.askSize,
|
|
66
|
-
...(snapshot.exchangeTs === undefined ? {} : { exchangeTs: snapshot.exchangeTs }),
|
|
67
|
-
receivedAt: snapshot.receivedAt,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
this.#emitInternalError(asError(error));
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
async subscribeFundingRate(_input) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
watchMarketEvents() {
|
|
79
|
-
return this.#marketQueue;
|
|
80
|
-
}
|
|
81
|
-
setMarketEventSink(sink) {
|
|
82
|
-
this.#marketEventSink = sink;
|
|
83
|
-
}
|
|
84
|
-
watchInternalErrors() {
|
|
85
|
-
return this.#internalErrorQueue;
|
|
86
|
-
}
|
|
87
|
-
async subscribeOrders(_input) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
watchOrderEvents() {
|
|
91
|
-
return this.#orderQueue;
|
|
92
|
-
}
|
|
93
|
-
setOrderEventSink(sink) {
|
|
94
|
-
this.#orderEventSink = sink;
|
|
95
|
-
}
|
|
96
|
-
watchAccountEvents() {
|
|
97
|
-
return this.#accountQueue;
|
|
98
|
-
}
|
|
99
|
-
setAccountEventSink(sink) {
|
|
100
|
-
this.#accountEventSink = sink;
|
|
101
|
-
}
|
|
102
|
-
async mapTickerToL1(symbol) {
|
|
103
|
-
const bidsAsks = await this.#exchange.watchBidsAsks([symbol]);
|
|
104
|
-
const ticker = bidsAsks[symbol];
|
|
105
|
-
if (ticker === undefined) {
|
|
106
|
-
throw new Error("missing required ticker fields");
|
|
107
|
-
}
|
|
108
|
-
if (ticker.bid === undefined ||
|
|
109
|
-
ticker.bidVolume === undefined ||
|
|
110
|
-
ticker.ask === undefined ||
|
|
111
|
-
ticker.askVolume === undefined) {
|
|
112
|
-
throw new Error("missing required ticker fields");
|
|
113
|
-
}
|
|
114
|
-
return {
|
|
115
|
-
exchange: this.exchange,
|
|
116
|
-
symbol: ticker.symbol,
|
|
117
|
-
bidPrice: String(ticker.bid),
|
|
118
|
-
bidSize: String(ticker.bidVolume),
|
|
119
|
-
askPrice: String(ticker.ask),
|
|
120
|
-
askSize: String(ticker.askVolume),
|
|
121
|
-
...(ticker.timestamp === undefined ? {} : { exchangeTs: ticker.timestamp }),
|
|
122
|
-
receivedAt: Date.now(),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
async fetchMarketInfo() {
|
|
126
|
-
const markets = await this.#exchange.fetchMarkets();
|
|
127
|
-
return markets.map((market) => {
|
|
128
|
-
return {
|
|
129
|
-
exchange: this.exchange,
|
|
130
|
-
symbol: market.symbol,
|
|
131
|
-
baseAsset: market.base,
|
|
132
|
-
quoteAsset: market.quote,
|
|
133
|
-
marketType: market.type,
|
|
134
|
-
pricePrecision: market.precision.price,
|
|
135
|
-
amountPrecision: market.precision.amount,
|
|
136
|
-
active: market.active,
|
|
137
|
-
};
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
async fetchOpenOrdersBaseline(accountId) {
|
|
141
|
-
const now = Date.now();
|
|
142
|
-
const orders = await this.#exchange.fetchOpenOrders(undefined, undefined, undefined, {
|
|
143
|
-
type: "future",
|
|
144
|
-
});
|
|
145
|
-
return orders.map((order) => {
|
|
146
|
-
const symbol = requiredString(order.symbol, "symbol");
|
|
147
|
-
const side = requiredOrderSide(order.side);
|
|
148
|
-
const type = requiredString(order.type, "type");
|
|
149
|
-
const status = requiredString(order.status, "status");
|
|
150
|
-
const amount = valueToRequiredString(order.amount, "amount");
|
|
151
|
-
const filled = valueToRequiredString(order.filled, "filled");
|
|
152
|
-
const updatedAt = order.timestamp ?? now;
|
|
153
|
-
this.#rememberOrderSymbol(withOptionalOrderLocators({
|
|
154
|
-
symbol,
|
|
155
|
-
orderId: order.id,
|
|
156
|
-
clientOrderId: order.clientOrderId,
|
|
157
|
-
}));
|
|
158
|
-
return {
|
|
159
|
-
accountId,
|
|
160
|
-
exchange: this.exchange,
|
|
161
|
-
symbol,
|
|
162
|
-
side,
|
|
163
|
-
type,
|
|
164
|
-
status,
|
|
165
|
-
amount,
|
|
166
|
-
filled,
|
|
167
|
-
...(order.price === undefined ? {} : { price: String(order.price) }),
|
|
168
|
-
seq: 0,
|
|
169
|
-
receivedAt: now,
|
|
170
|
-
updatedAt,
|
|
171
|
-
...(order.id === undefined ? {} : { orderId: order.id }),
|
|
172
|
-
...(order.clientOrderId === undefined ? {} : { clientOrderId: order.clientOrderId }),
|
|
173
|
-
};
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
async fetchAccountBaseline(accountId) {
|
|
177
|
-
const now = Date.now();
|
|
178
|
-
const [balance, positions] = await Promise.all([
|
|
179
|
-
this.#exchange.fetchBalance({ type: "future" }),
|
|
180
|
-
this.#exchange.fetchPositions([], { type: "future" }),
|
|
181
|
-
]);
|
|
182
|
-
const assets = new Set([
|
|
183
|
-
...Object.keys(balance.free ?? {}),
|
|
184
|
-
...Object.keys(balance.used ?? {}),
|
|
185
|
-
...Object.keys(balance.total ?? {}),
|
|
186
|
-
]);
|
|
187
|
-
const balances = Object.fromEntries([...assets].map((asset) => [
|
|
188
|
-
asset,
|
|
189
|
-
{
|
|
190
|
-
accountId,
|
|
191
|
-
exchange: this.exchange,
|
|
192
|
-
asset,
|
|
193
|
-
free: valueToString(balance.free?.[asset]),
|
|
194
|
-
used: valueToString(balance.used?.[asset]),
|
|
195
|
-
total: valueToString(balance.total?.[asset]),
|
|
196
|
-
seq: 0,
|
|
197
|
-
receivedAt: now,
|
|
198
|
-
updatedAt: now,
|
|
199
|
-
},
|
|
200
|
-
]));
|
|
201
|
-
const positionsSnapshots = positions.map((position) => {
|
|
202
|
-
const symbol = requiredString(position.symbol, "symbol", "position fields");
|
|
203
|
-
const side = requiredString(position.side, "side", "position fields");
|
|
204
|
-
const size = valueToRequiredString(position.contracts ?? position.amount ?? position.positionAmt, "size", "position fields");
|
|
205
|
-
const updatedAt = position.timestamp ?? now;
|
|
206
|
-
return {
|
|
207
|
-
accountId,
|
|
208
|
-
exchange: this.exchange,
|
|
209
|
-
symbol,
|
|
210
|
-
side,
|
|
211
|
-
size,
|
|
212
|
-
seq: 0,
|
|
213
|
-
receivedAt: now,
|
|
214
|
-
updatedAt,
|
|
215
|
-
};
|
|
216
|
-
});
|
|
217
|
-
const totalWalletBalance = balance.info?.totalWalletBalance;
|
|
218
|
-
const risk = totalWalletBalance === undefined
|
|
219
|
-
? undefined
|
|
220
|
-
: {
|
|
221
|
-
accountId,
|
|
222
|
-
exchange: this.exchange,
|
|
223
|
-
seq: 0,
|
|
224
|
-
receivedAt: now,
|
|
225
|
-
updatedAt: now,
|
|
226
|
-
equity: valueToString(totalWalletBalance),
|
|
227
|
-
};
|
|
228
|
-
return {
|
|
229
|
-
balances,
|
|
230
|
-
positions: positionsSnapshots,
|
|
231
|
-
...(risk === undefined ? {} : { risk }),
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
async placeOrder(input) {
|
|
235
|
-
const amount = parseFiniteNumber(input.amount, "amount");
|
|
236
|
-
if (amount <= 0) {
|
|
237
|
-
throw new Error("invalid order amount");
|
|
238
|
-
}
|
|
239
|
-
const price = input.price === undefined ? undefined : parseFiniteNumber(input.price, "price");
|
|
240
|
-
if (price !== undefined && price <= 0) {
|
|
241
|
-
throw new Error("invalid order price");
|
|
242
|
-
}
|
|
243
|
-
const orderParams = {
|
|
244
|
-
type: "future",
|
|
245
|
-
clientOrderId: input.clientOrderId,
|
|
246
|
-
};
|
|
247
|
-
if (input.reduceOnly === true) {
|
|
248
|
-
orderParams.reduceOnly = true;
|
|
249
|
-
}
|
|
250
|
-
const order = await this.#exchange.createOrder(input.symbol, input.type, input.side, amount, price, orderParams);
|
|
251
|
-
this.#rememberOrderSymbol(withOptionalOrderLocators({
|
|
252
|
-
symbol: input.symbol,
|
|
253
|
-
orderId: order.id,
|
|
254
|
-
clientOrderId: order.clientOrderId ?? input.clientOrderId,
|
|
255
|
-
}));
|
|
256
|
-
return {
|
|
257
|
-
...(order.clientOrderId === undefined
|
|
258
|
-
? { clientOrderId: input.clientOrderId }
|
|
259
|
-
: { clientOrderId: String(order.clientOrderId) }),
|
|
260
|
-
...(order.id === undefined ? {} : { orderId: String(order.id) }),
|
|
261
|
-
receivedAt: Date.now(),
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
async amendOrder(input) {
|
|
265
|
-
return {
|
|
266
|
-
...(input.clientOrderId === undefined ? {} : { clientOrderId: input.clientOrderId }),
|
|
267
|
-
...(input.orderId === undefined ? {} : { orderId: input.orderId }),
|
|
268
|
-
receivedAt: Date.now(),
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
async cancelOrder(input) {
|
|
272
|
-
if (input.orderId === undefined && input.clientOrderId === undefined) {
|
|
273
|
-
return {
|
|
274
|
-
receivedAt: Date.now(),
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
const privateStreams = this.#exchange;
|
|
278
|
-
if (privateStreams.cancelOrder !== undefined) {
|
|
279
|
-
const symbol = this.#resolveOrderSymbol(withOptionalOrderLocators({
|
|
280
|
-
symbol: undefined,
|
|
281
|
-
orderId: input.orderId,
|
|
282
|
-
clientOrderId: input.clientOrderId,
|
|
283
|
-
}));
|
|
284
|
-
const params = { type: "future" };
|
|
285
|
-
if (input.clientOrderId !== undefined) {
|
|
286
|
-
params.clientOrderId = input.clientOrderId;
|
|
287
|
-
}
|
|
288
|
-
const result = await privateStreams.cancelOrder(input.orderId, symbol, params);
|
|
289
|
-
this.#rememberOrderSymbol(withOptionalOrderLocators({
|
|
290
|
-
symbol: result.symbol ?? symbol,
|
|
291
|
-
orderId: result.id ?? input.orderId,
|
|
292
|
-
clientOrderId: result.clientOrderId ?? input.clientOrderId,
|
|
293
|
-
}));
|
|
294
|
-
return {
|
|
295
|
-
...(result.clientOrderId === undefined
|
|
296
|
-
? input.clientOrderId === undefined
|
|
297
|
-
? {}
|
|
298
|
-
: { clientOrderId: input.clientOrderId }
|
|
299
|
-
: { clientOrderId: String(result.clientOrderId) }),
|
|
300
|
-
...(result.id === undefined
|
|
301
|
-
? input.orderId === undefined
|
|
302
|
-
? {}
|
|
303
|
-
: { orderId: input.orderId }
|
|
304
|
-
: { orderId: String(result.id) }),
|
|
305
|
-
receivedAt: Date.now(),
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
return {
|
|
309
|
-
...(input.clientOrderId === undefined ? {} : { clientOrderId: input.clientOrderId }),
|
|
310
|
-
...(input.orderId === undefined ? {} : { orderId: input.orderId }),
|
|
311
|
-
receivedAt: Date.now(),
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
async cancelAllOrders(_input) {
|
|
315
|
-
return {
|
|
316
|
-
accountId: _input.accountId,
|
|
317
|
-
exchange: this.exchange,
|
|
318
|
-
canceledCount: 0,
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
#emitMarketEvent(event) {
|
|
322
|
-
if (this.#marketEventSink !== undefined) {
|
|
323
|
-
this.#marketEventSink(event);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
this.#marketQueue.push(event);
|
|
327
|
-
}
|
|
328
|
-
#emitOrderEvent(event) {
|
|
329
|
-
if (this.#orderEventSink !== undefined) {
|
|
330
|
-
this.#orderEventSink(event);
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
this.#orderQueue.push(event);
|
|
334
|
-
}
|
|
335
|
-
#emitAccountEvent(event) {
|
|
336
|
-
if (this.#accountEventSink !== undefined) {
|
|
337
|
-
this.#accountEventSink(event);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
this.#accountQueue.push(event);
|
|
341
|
-
}
|
|
342
|
-
#emitInternalError(error) {
|
|
343
|
-
this.#internalErrorQueue.push(error);
|
|
344
|
-
}
|
|
345
|
-
#trackPrivateWatchTask(task) {
|
|
346
|
-
this.#privateWatchTasks.add(task);
|
|
347
|
-
void task.finally(() => {
|
|
348
|
-
this.#privateWatchTasks.delete(task);
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
#rememberOrderSymbol(input) {
|
|
352
|
-
if (input.symbol === undefined) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
if (input.orderId !== undefined) {
|
|
356
|
-
this.#orderSymbolsByOrderId.set(String(input.orderId), input.symbol);
|
|
357
|
-
}
|
|
358
|
-
if (input.clientOrderId !== undefined) {
|
|
359
|
-
this.#orderSymbolsByClientOrderId.set(String(input.clientOrderId), input.symbol);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
#resolveOrderSymbol(input) {
|
|
363
|
-
if (input.orderId !== undefined) {
|
|
364
|
-
const symbol = this.#orderSymbolsByOrderId.get(input.orderId);
|
|
365
|
-
if (symbol !== undefined) {
|
|
366
|
-
return symbol;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (input.clientOrderId !== undefined) {
|
|
370
|
-
return this.#orderSymbolsByClientOrderId.get(input.clientOrderId);
|
|
371
|
-
}
|
|
372
|
-
return undefined;
|
|
373
|
-
}
|
|
374
|
-
async #runWatchOrders(privateStreams) {
|
|
375
|
-
while (this.#started) {
|
|
376
|
-
try {
|
|
377
|
-
const orders = await privateStreams.watchOrders?.();
|
|
378
|
-
if (!this.#started) {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
this.#emitOrdersFromWatch(orders ?? []);
|
|
382
|
-
}
|
|
383
|
-
catch (error) {
|
|
384
|
-
if (!this.#started) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
this.#started = false;
|
|
388
|
-
this.#emitInternalError(asError(error));
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
async #runWatchBalance(privateStreams) {
|
|
394
|
-
while (this.#started) {
|
|
395
|
-
try {
|
|
396
|
-
const balance = await privateStreams.watchBalance?.();
|
|
397
|
-
if (!this.#started) {
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
this.#emitBalanceFromWatch(balance);
|
|
401
|
-
}
|
|
402
|
-
catch (error) {
|
|
403
|
-
if (!this.#started) {
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
this.#started = false;
|
|
407
|
-
this.#emitInternalError(asError(error));
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
#emitOrdersFromWatch(orders) {
|
|
413
|
-
for (const order of orders) {
|
|
414
|
-
try {
|
|
415
|
-
const now = Date.now();
|
|
416
|
-
const symbol = requiredString(order.symbol, "symbol", "watchOrders");
|
|
417
|
-
const side = requiredOrderSide(order.side, "watchOrders");
|
|
418
|
-
const type = requiredString(order.type, "type", "watchOrders");
|
|
419
|
-
const status = requiredString(order.status, "status", "watchOrders");
|
|
420
|
-
const amount = valueToRequiredString(order.amount, "amount", "watchOrders");
|
|
421
|
-
const filled = valueToString(order.filled);
|
|
422
|
-
const normalizedStatus = status.toLowerCase();
|
|
423
|
-
this.#rememberOrderSymbol(withOptionalOrderLocators({
|
|
424
|
-
symbol,
|
|
425
|
-
orderId: order.id,
|
|
426
|
-
clientOrderId: order.clientOrderId,
|
|
427
|
-
}));
|
|
428
|
-
const eventType = normalizedStatus === "canceled" || normalizedStatus === "cancelled"
|
|
429
|
-
? "order.canceled"
|
|
430
|
-
: "order.updated";
|
|
431
|
-
this.#emitOrderEvent({
|
|
432
|
-
type: eventType,
|
|
433
|
-
accountId: this.#accountId,
|
|
434
|
-
exchange: this.exchange,
|
|
435
|
-
receivedAt: now,
|
|
436
|
-
snapshot: {
|
|
437
|
-
accountId: this.#accountId,
|
|
438
|
-
exchange: this.exchange,
|
|
439
|
-
symbol,
|
|
440
|
-
side,
|
|
441
|
-
type,
|
|
442
|
-
status,
|
|
443
|
-
amount,
|
|
444
|
-
filled,
|
|
445
|
-
...(order.price === undefined ? {} : { price: String(order.price) }),
|
|
446
|
-
seq: 0,
|
|
447
|
-
receivedAt: now,
|
|
448
|
-
updatedAt: Number(order.timestamp ?? now),
|
|
449
|
-
...(order.id === undefined ? {} : { orderId: String(order.id) }),
|
|
450
|
-
...(order.clientOrderId === undefined
|
|
451
|
-
? {}
|
|
452
|
-
: { clientOrderId: String(order.clientOrderId) }),
|
|
453
|
-
},
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
catch (error) {
|
|
457
|
-
this.#emitInternalError(asError(error));
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
#emitBalanceFromWatch(balance) {
|
|
462
|
-
if (balance === undefined) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
const now = Date.now();
|
|
466
|
-
const assets = new Set([
|
|
467
|
-
...Object.keys(balance.free ?? {}),
|
|
468
|
-
...Object.keys(balance.used ?? {}),
|
|
469
|
-
...Object.keys(balance.total ?? {}),
|
|
470
|
-
]);
|
|
471
|
-
for (const asset of assets) {
|
|
472
|
-
this.#emitAccountEvent({
|
|
473
|
-
type: "balance.updated",
|
|
474
|
-
accountId: this.#accountId,
|
|
475
|
-
exchange: this.exchange,
|
|
476
|
-
asset,
|
|
477
|
-
snapshot: {
|
|
478
|
-
accountId: this.#accountId,
|
|
479
|
-
exchange: this.exchange,
|
|
480
|
-
asset,
|
|
481
|
-
free: valueToString(balance.free?.[asset]),
|
|
482
|
-
used: valueToString(balance.used?.[asset]),
|
|
483
|
-
total: valueToString(balance.total?.[asset]),
|
|
484
|
-
seq: 0,
|
|
485
|
-
receivedAt: now,
|
|
486
|
-
updatedAt: now,
|
|
487
|
-
},
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
getHealth() {
|
|
492
|
-
return {
|
|
493
|
-
exchange: this.exchange,
|
|
494
|
-
status: this.#started ? "healthy" : "idle",
|
|
495
|
-
wsConnected: this.#started,
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
function withOptionalOrderLocators(input) {
|
|
500
|
-
return {
|
|
501
|
-
...(input.symbol === undefined ? {} : { symbol: input.symbol }),
|
|
502
|
-
...(input.orderId === undefined ? {} : { orderId: input.orderId }),
|
|
503
|
-
...(input.clientOrderId === undefined ? {} : { clientOrderId: input.clientOrderId }),
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
function requiredString(value, field, context = "order fields") {
|
|
507
|
-
if (value === undefined || value.trim().length === 0) {
|
|
508
|
-
throw new Error(`missing required ${context}: ${field}`);
|
|
509
|
-
}
|
|
510
|
-
return value;
|
|
511
|
-
}
|
|
512
|
-
function requiredOrderSide(value, context = "order fields") {
|
|
513
|
-
if (value !== "buy" && value !== "sell") {
|
|
514
|
-
throw new Error(`missing required ${context}: side`);
|
|
515
|
-
}
|
|
516
|
-
return value;
|
|
517
|
-
}
|
|
518
|
-
function valueToRequiredString(value, field, context = "order fields") {
|
|
519
|
-
if (value === undefined) {
|
|
520
|
-
throw new Error(`missing required ${context}: ${field}`);
|
|
521
|
-
}
|
|
522
|
-
return String(value);
|
|
523
|
-
}
|
|
524
|
-
function valueToString(value) {
|
|
525
|
-
return value === undefined ? "0" : String(value);
|
|
526
|
-
}
|
|
527
|
-
function parseFiniteNumber(value, field) {
|
|
528
|
-
if (value.trim().length === 0) {
|
|
529
|
-
throw new Error(`invalid order ${field}`);
|
|
530
|
-
}
|
|
531
|
-
const parsed = Number(value);
|
|
532
|
-
if (!Number.isFinite(parsed)) {
|
|
533
|
-
throw new Error(`invalid order ${field}`);
|
|
534
|
-
}
|
|
535
|
-
return parsed;
|
|
536
|
-
}
|
|
537
|
-
function asError(error) {
|
|
538
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
539
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface BinanceUsdmExchangeConfig {
|
|
2
|
-
apiKey: string;
|
|
3
|
-
secret: string;
|
|
4
|
-
enableRateLimit: boolean;
|
|
5
|
-
}
|
|
6
|
-
export interface BinanceUsdmExchangeLike {
|
|
7
|
-
options: {
|
|
8
|
-
defaultType?: string;
|
|
9
|
-
warnOnFetchOpenOrdersWithoutSymbol?: boolean;
|
|
10
|
-
};
|
|
11
|
-
enableDemoTrading?(value: boolean): void;
|
|
12
|
-
}
|
|
13
|
-
export type BinanceUsdmExchangeCtor = new (config: BinanceUsdmExchangeConfig) => BinanceUsdmExchangeLike;
|
|
14
|
-
export interface CreateBinanceUsdmExchangeInput {
|
|
15
|
-
apiKey: string;
|
|
16
|
-
secret: string;
|
|
17
|
-
sandbox?: boolean;
|
|
18
|
-
enableRateLimit?: boolean;
|
|
19
|
-
exchangeCtor?: BinanceUsdmExchangeCtor;
|
|
20
|
-
}
|
|
21
|
-
export declare function getCcxtProBinanceUsdmCtor(): BinanceUsdmExchangeCtor;
|
|
22
|
-
export declare function createBinanceUsdmExchange(input: CreateBinanceUsdmExchangeInput): BinanceUsdmExchangeLike;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import ccxt from "ccxt";
|
|
2
|
-
export function getCcxtProBinanceUsdmCtor() {
|
|
3
|
-
const proNamespace = ccxt
|
|
4
|
-
.pro;
|
|
5
|
-
if (proNamespace === undefined || proNamespace.binanceusdm === undefined) {
|
|
6
|
-
throw new Error("ccxt.pro.binanceusdm is not available");
|
|
7
|
-
}
|
|
8
|
-
return proNamespace.binanceusdm;
|
|
9
|
-
}
|
|
10
|
-
export function createBinanceUsdmExchange(input) {
|
|
11
|
-
const ExchangeCtor = input.exchangeCtor ?? getCcxtProBinanceUsdmCtor();
|
|
12
|
-
const exchange = new ExchangeCtor({
|
|
13
|
-
apiKey: input.apiKey,
|
|
14
|
-
secret: input.secret,
|
|
15
|
-
enableRateLimit: input.enableRateLimit ?? true,
|
|
16
|
-
});
|
|
17
|
-
exchange.options.defaultType = "future";
|
|
18
|
-
exchange.options.warnOnFetchOpenOrdersWithoutSymbol = false;
|
|
19
|
-
if (input.sandbox ?? true) {
|
|
20
|
-
exchange.enableDemoTrading?.(true);
|
|
21
|
-
}
|
|
22
|
-
return exchange;
|
|
23
|
-
}
|