@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/dist/core/client.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type BinanceUsdmExchangeLike, type CreateBinanceUsdmExchangeInput } from "../adapters/ccxt/binance-usdm-exchange.js";
|
|
1
2
|
import type { ExchangeAdapter } from "../adapters/types.js";
|
|
2
3
|
import { type AccountManager } from "../managers/account-manager.js";
|
|
3
4
|
import { type MarketManager } from "../managers/market-manager.js";
|
|
@@ -5,6 +6,9 @@ import { type OrderManager } from "../managers/order-manager.js";
|
|
|
5
6
|
import { createHealthStore } from "../store/health-store.js";
|
|
6
7
|
import type { ClientStatus, Exchange } from "../types/public.js";
|
|
7
8
|
import { createRuntime } from "./runtime.js";
|
|
9
|
+
export interface CreateClientOptions {
|
|
10
|
+
sandbox?: boolean;
|
|
11
|
+
}
|
|
8
12
|
export interface RegisterAccountInput {
|
|
9
13
|
accountId: string;
|
|
10
14
|
exchange: Exchange;
|
|
@@ -14,24 +18,33 @@ export interface RegisterAccountInput {
|
|
|
14
18
|
password?: string;
|
|
15
19
|
};
|
|
16
20
|
}
|
|
21
|
+
export interface RegisterAccountResult {
|
|
22
|
+
accountId: string;
|
|
23
|
+
exchange: Exchange;
|
|
24
|
+
}
|
|
17
25
|
interface InternalCreateClientOptions {
|
|
18
26
|
adapter?: ExchangeAdapter;
|
|
19
27
|
}
|
|
28
|
+
interface CreatePublicClientDependencies {
|
|
29
|
+
createExchange?: (input: CreateBinanceUsdmExchangeInput) => BinanceUsdmExchangeLike;
|
|
30
|
+
createAdapter?: (input: {
|
|
31
|
+
accountId: string;
|
|
32
|
+
exchange: BinanceUsdmExchangeLike;
|
|
33
|
+
}) => ExchangeAdapter;
|
|
34
|
+
}
|
|
20
35
|
export interface AcexClient {
|
|
21
36
|
readonly market: MarketManager;
|
|
22
37
|
readonly account: AccountManager;
|
|
23
38
|
readonly order: OrderManager;
|
|
24
39
|
getStatus(): ClientStatus;
|
|
25
40
|
getHealth(): ReturnType<ReturnType<typeof createHealthStore>["snapshot"]>;
|
|
26
|
-
registerAccount(input: RegisterAccountInput): Promise<
|
|
27
|
-
accountId: string;
|
|
28
|
-
exchange: Exchange;
|
|
29
|
-
}>;
|
|
41
|
+
registerAccount(input: RegisterAccountInput): Promise<RegisterAccountResult>;
|
|
30
42
|
start(): Promise<void>;
|
|
31
43
|
stop(): Promise<void>;
|
|
32
44
|
watchErrors(): ReturnType<ReturnType<typeof createRuntime>["watchErrors"]>;
|
|
33
45
|
watchHealth(): ReturnType<ReturnType<typeof createRuntime>["watchHealth"]>;
|
|
34
46
|
}
|
|
35
47
|
export declare function createInternalClient(options?: InternalCreateClientOptions): AcexClient;
|
|
36
|
-
export declare function
|
|
48
|
+
export declare function createPublicClient(options?: CreateClientOptions, dependencies?: CreatePublicClientDependencies): AcexClient;
|
|
49
|
+
export declare function createClient(options?: CreateClientOptions): AcexClient;
|
|
37
50
|
export {};
|
package/dist/core/client.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
import { BinanceCompositeAdapter } from "../adapters/binance/composite-adapter.js";
|
|
2
|
+
import { BinanceNativeMarketAdapter } from "../adapters/binance/native-market-adapter.js";
|
|
3
|
+
import { CcxtBinanceUsdMAdapter } from "../adapters/ccxt/binance-usdm-ccxt-adapter.js";
|
|
4
|
+
import { createBinanceUsdmExchange, } from "../adapters/ccxt/binance-usdm-exchange.js";
|
|
5
|
+
import { createAcexError, isAcexError } from "../errors/acex-error.js";
|
|
1
6
|
import { createIdleAccountManager } from "../managers/account-manager.js";
|
|
2
7
|
import { createIdleMarketManager } from "../managers/market-manager.js";
|
|
3
8
|
import { createIdleOrderManager } from "../managers/order-manager.js";
|
|
9
|
+
import { createAsyncQueue } from "../runtime/async-queue.js";
|
|
4
10
|
import { createHealthStore } from "../store/health-store.js";
|
|
11
|
+
import { IMPLEMENTED_EXCHANGES } from "../types/public.js";
|
|
5
12
|
import { createRuntime } from "./runtime.js";
|
|
13
|
+
const PUBLIC_EXCHANGE = IMPLEMENTED_EXCHANGES[0];
|
|
6
14
|
async function* emptyAsyncIterable() { }
|
|
7
15
|
export function createInternalClient(options = {}) {
|
|
8
16
|
let status = "idle";
|
|
@@ -40,6 +48,356 @@ export function createInternalClient(options = {}) {
|
|
|
40
48
|
},
|
|
41
49
|
};
|
|
42
50
|
}
|
|
43
|
-
export function
|
|
44
|
-
|
|
51
|
+
export function createPublicClient(options = {}, dependencies = {}) {
|
|
52
|
+
const idleMarket = createIdleMarketManager();
|
|
53
|
+
const idleAccount = createIdleAccountManager();
|
|
54
|
+
const idleOrder = createIdleOrderManager();
|
|
55
|
+
const accountEvents = createAsyncQueue({ maxBufferSize: 100 });
|
|
56
|
+
const errors = createAsyncQueue({ maxBufferSize: 100 });
|
|
57
|
+
const healthStore = createHealthStore();
|
|
58
|
+
const healthEvents = createAsyncQueue({ maxBufferSize: 100 });
|
|
59
|
+
const accounts = new Map();
|
|
60
|
+
let status = "idle";
|
|
61
|
+
let activeClient;
|
|
62
|
+
let activeAdapter;
|
|
63
|
+
const market = {
|
|
64
|
+
async subscribeL1Book(input) {
|
|
65
|
+
assertSupportedExchange(input.exchange);
|
|
66
|
+
const client = await requireStartedClient();
|
|
67
|
+
await client.market.subscribeL1Book(input);
|
|
68
|
+
syncHealth();
|
|
69
|
+
},
|
|
70
|
+
async subscribeFundingRate(input) {
|
|
71
|
+
assertSupportedExchange(input.exchange);
|
|
72
|
+
const client = await requireStartedClient();
|
|
73
|
+
await client.market.subscribeFundingRate(input);
|
|
74
|
+
syncHealth();
|
|
75
|
+
},
|
|
76
|
+
getL1Book(key) {
|
|
77
|
+
return getCurrentClient().market.getL1Book(key);
|
|
78
|
+
},
|
|
79
|
+
getFundingRate(key) {
|
|
80
|
+
return getCurrentClient().market.getFundingRate(key);
|
|
81
|
+
},
|
|
82
|
+
getMarketSnapshot(key) {
|
|
83
|
+
return getCurrentClient().market.getMarketSnapshot(key);
|
|
84
|
+
},
|
|
85
|
+
getMarketStatus(key) {
|
|
86
|
+
return getCurrentClient().market.getMarketStatus(key);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
const account = {
|
|
90
|
+
async subscribeAccount(input) {
|
|
91
|
+
getRegisteredAccount(input.accountId);
|
|
92
|
+
const client = await requireStartedClient();
|
|
93
|
+
await client.account.subscribeAccount(input);
|
|
94
|
+
syncHealth();
|
|
95
|
+
},
|
|
96
|
+
getBalance(accountId, asset) {
|
|
97
|
+
return getCurrentClient().account.getBalance(accountId, asset);
|
|
98
|
+
},
|
|
99
|
+
getBalances(accountId) {
|
|
100
|
+
return getCurrentClient().account.getBalances(accountId);
|
|
101
|
+
},
|
|
102
|
+
getPosition(input) {
|
|
103
|
+
return getCurrentClient().account.getPosition(input);
|
|
104
|
+
},
|
|
105
|
+
getPositions(accountId) {
|
|
106
|
+
return getCurrentClient().account.getPositions(accountId);
|
|
107
|
+
},
|
|
108
|
+
getAccountSnapshot(accountId) {
|
|
109
|
+
return getCurrentClient().account.getAccountSnapshot(accountId);
|
|
110
|
+
},
|
|
111
|
+
getAccountStatus(accountId) {
|
|
112
|
+
return getCurrentClient().account.getAccountStatus(accountId);
|
|
113
|
+
},
|
|
114
|
+
getRiskSnapshot(accountId) {
|
|
115
|
+
return getCurrentClient().account.getRiskSnapshot(accountId);
|
|
116
|
+
},
|
|
117
|
+
watchAccountEvents() {
|
|
118
|
+
return accountEvents;
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
const order = {
|
|
122
|
+
async subscribeOrders(input) {
|
|
123
|
+
getRegisteredAccount(input.accountId);
|
|
124
|
+
const client = await requireStartedClient();
|
|
125
|
+
await client.order.subscribeOrders(input);
|
|
126
|
+
syncHealth();
|
|
127
|
+
},
|
|
128
|
+
async placeOrder(input) {
|
|
129
|
+
getRegisteredAccount(input.accountId);
|
|
130
|
+
assertSupportedExchange(input.exchange);
|
|
131
|
+
const client = await requireStartedClient();
|
|
132
|
+
const ack = await client.order.placeOrder(input);
|
|
133
|
+
syncHealth();
|
|
134
|
+
return ack;
|
|
135
|
+
},
|
|
136
|
+
async amendOrder(input) {
|
|
137
|
+
getRegisteredAccount(input.accountId);
|
|
138
|
+
assertSupportedExchange(input.exchange);
|
|
139
|
+
const client = await requireStartedClient();
|
|
140
|
+
const ack = await client.order.amendOrder(input);
|
|
141
|
+
syncHealth();
|
|
142
|
+
return ack;
|
|
143
|
+
},
|
|
144
|
+
async cancelOrder(input) {
|
|
145
|
+
getRegisteredAccount(input.accountId);
|
|
146
|
+
assertSupportedExchange(input.exchange);
|
|
147
|
+
const client = await requireStartedClient();
|
|
148
|
+
const ack = await client.order.cancelOrder(input);
|
|
149
|
+
syncHealth();
|
|
150
|
+
return ack;
|
|
151
|
+
},
|
|
152
|
+
async cancelAllOrders(input) {
|
|
153
|
+
getRegisteredAccount(input.accountId);
|
|
154
|
+
assertSupportedExchange(input.exchange);
|
|
155
|
+
const result = await requireStartedClient().then((client) => client.order.cancelAllOrders(input));
|
|
156
|
+
syncHealth();
|
|
157
|
+
return result;
|
|
158
|
+
},
|
|
159
|
+
getOrder(input) {
|
|
160
|
+
return getCurrentClient().order.getOrder(input);
|
|
161
|
+
},
|
|
162
|
+
getOpenOrders(accountId) {
|
|
163
|
+
return getCurrentClient().order.getOpenOrders(accountId);
|
|
164
|
+
},
|
|
165
|
+
getOrderStatus(accountId) {
|
|
166
|
+
return getCurrentClient().order.getOrderStatus(accountId);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
function getCurrentClient() {
|
|
170
|
+
return (activeClient ?? {
|
|
171
|
+
market: idleMarket,
|
|
172
|
+
account: idleAccount,
|
|
173
|
+
order: idleOrder,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function bridgeEvents(source, push) {
|
|
177
|
+
void (async () => {
|
|
178
|
+
try {
|
|
179
|
+
for await (const value of source) {
|
|
180
|
+
push(value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch { }
|
|
184
|
+
})();
|
|
185
|
+
}
|
|
186
|
+
function attachClientBridges(client) {
|
|
187
|
+
bridgeEvents(client.account.watchAccountEvents(), (event) => {
|
|
188
|
+
accountEvents.push(event);
|
|
189
|
+
});
|
|
190
|
+
bridgeEvents(client.watchErrors(), (event) => {
|
|
191
|
+
errors.push(event);
|
|
192
|
+
});
|
|
193
|
+
bridgeEvents(client.watchHealth(), (event) => {
|
|
194
|
+
healthEvents.push(event);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function getRegisteredAccount(accountId) {
|
|
198
|
+
const account = accounts.get(accountId);
|
|
199
|
+
if (account === undefined) {
|
|
200
|
+
throw createAcexError({
|
|
201
|
+
code: "ACCOUNT_NOT_FOUND",
|
|
202
|
+
message: `account not found: ${accountId}`,
|
|
203
|
+
retryable: false,
|
|
204
|
+
accountId,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return account;
|
|
208
|
+
}
|
|
209
|
+
function getOnlyRegisteredAccount() {
|
|
210
|
+
const registered = [...accounts.values()][0];
|
|
211
|
+
if (registered === undefined) {
|
|
212
|
+
throw createAcexError({
|
|
213
|
+
code: "VALIDATION_ERROR",
|
|
214
|
+
message: "registerAccount() must be called before start()",
|
|
215
|
+
retryable: false,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return registered;
|
|
219
|
+
}
|
|
220
|
+
function assertNonEmpty(value, field) {
|
|
221
|
+
if (value.trim().length === 0) {
|
|
222
|
+
throw createAcexError({
|
|
223
|
+
code: "VALIDATION_ERROR",
|
|
224
|
+
message: `missing required field: ${field}`,
|
|
225
|
+
retryable: false,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function assertSupportedExchange(exchange) {
|
|
230
|
+
if (exchange !== PUBLIC_EXCHANGE) {
|
|
231
|
+
throw createAcexError({
|
|
232
|
+
code: "EXCHANGE_NOT_SUPPORTED",
|
|
233
|
+
message: `unsupported exchange: ${exchange}`,
|
|
234
|
+
retryable: false,
|
|
235
|
+
exchange,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function syncHealth() {
|
|
240
|
+
healthStore.setClientStatus(status);
|
|
241
|
+
if (activeAdapter !== undefined) {
|
|
242
|
+
healthStore.setExchangeHealth(activeAdapter.exchange, activeAdapter.getHealth());
|
|
243
|
+
}
|
|
244
|
+
if (activeClient === undefined) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
for (const accountId of accounts.keys()) {
|
|
248
|
+
const accountStatus = activeClient.account.getAccountStatus(accountId);
|
|
249
|
+
if (accountStatus !== undefined) {
|
|
250
|
+
healthStore.setAccountStatus(accountId, accountStatus);
|
|
251
|
+
}
|
|
252
|
+
const orderStatus = activeClient.order.getOrderStatus(accountId);
|
|
253
|
+
if (orderStatus !== undefined) {
|
|
254
|
+
healthStore.setOrderStatus(accountId, orderStatus);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async function ensureActiveClient() {
|
|
259
|
+
if (activeClient !== undefined) {
|
|
260
|
+
return activeClient;
|
|
261
|
+
}
|
|
262
|
+
const registered = getOnlyRegisteredAccount();
|
|
263
|
+
try {
|
|
264
|
+
const exchangeInput = {
|
|
265
|
+
apiKey: registered.credentials.apiKey,
|
|
266
|
+
secret: registered.credentials.secret,
|
|
267
|
+
...(options.sandbox === undefined ? {} : { sandbox: options.sandbox }),
|
|
268
|
+
};
|
|
269
|
+
const exchange = dependencies.createExchange?.(exchangeInput) ?? createBinanceUsdmExchange(exchangeInput);
|
|
270
|
+
activeAdapter =
|
|
271
|
+
dependencies.createAdapter?.({
|
|
272
|
+
accountId: registered.accountId,
|
|
273
|
+
exchange,
|
|
274
|
+
}) ??
|
|
275
|
+
new BinanceCompositeAdapter({
|
|
276
|
+
marketAdapter: new BinanceNativeMarketAdapter(),
|
|
277
|
+
privateAdapter: new CcxtBinanceUsdMAdapter({
|
|
278
|
+
accountId: registered.accountId,
|
|
279
|
+
exchange: exchange,
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
activeClient = createInternalClient({ adapter: activeAdapter });
|
|
283
|
+
attachClientBridges(activeClient);
|
|
284
|
+
return activeClient;
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
throw toClientError(error, {
|
|
288
|
+
exchange: registered.exchange,
|
|
289
|
+
accountId: registered.accountId,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async function requireStartedClient() {
|
|
294
|
+
if (status !== "running") {
|
|
295
|
+
throw createAcexError({
|
|
296
|
+
code: "VALIDATION_ERROR",
|
|
297
|
+
message: "client.start() must be called before using runtime APIs",
|
|
298
|
+
retryable: false,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
return ensureActiveClient();
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
market,
|
|
305
|
+
account,
|
|
306
|
+
order,
|
|
307
|
+
getStatus: () => status,
|
|
308
|
+
getHealth() {
|
|
309
|
+
syncHealth();
|
|
310
|
+
return healthStore.snapshot();
|
|
311
|
+
},
|
|
312
|
+
watchErrors() {
|
|
313
|
+
return errors;
|
|
314
|
+
},
|
|
315
|
+
watchHealth() {
|
|
316
|
+
return healthEvents;
|
|
317
|
+
},
|
|
318
|
+
async registerAccount(input) {
|
|
319
|
+
assertNonEmpty(input.accountId, "accountId");
|
|
320
|
+
assertNonEmpty(input.credentials.apiKey, "credentials.apiKey");
|
|
321
|
+
assertNonEmpty(input.credentials.secret, "credentials.secret");
|
|
322
|
+
assertSupportedExchange(input.exchange);
|
|
323
|
+
if (accounts.has(input.accountId)) {
|
|
324
|
+
throw createAcexError({
|
|
325
|
+
code: "VALIDATION_ERROR",
|
|
326
|
+
message: `duplicate accountId: ${input.accountId}`,
|
|
327
|
+
retryable: false,
|
|
328
|
+
accountId: input.accountId,
|
|
329
|
+
exchange: input.exchange,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
if (accounts.size > 0) {
|
|
333
|
+
throw createAcexError({
|
|
334
|
+
code: "CAPABILITY_NOT_SUPPORTED",
|
|
335
|
+
message: "public createClient() currently supports one registered account",
|
|
336
|
+
retryable: false,
|
|
337
|
+
exchange: input.exchange,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
accounts.set(input.accountId, input);
|
|
341
|
+
if (status === "running" && activeClient === undefined) {
|
|
342
|
+
const client = await ensureActiveClient();
|
|
343
|
+
await client.start();
|
|
344
|
+
}
|
|
345
|
+
syncHealth();
|
|
346
|
+
return {
|
|
347
|
+
accountId: input.accountId,
|
|
348
|
+
exchange: input.exchange,
|
|
349
|
+
};
|
|
350
|
+
},
|
|
351
|
+
async start() {
|
|
352
|
+
if (status === "running") {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const registered = getOnlyRegisteredAccount();
|
|
356
|
+
status = "starting";
|
|
357
|
+
syncHealth();
|
|
358
|
+
try {
|
|
359
|
+
const client = await ensureActiveClient();
|
|
360
|
+
await client.start();
|
|
361
|
+
status = "running";
|
|
362
|
+
syncHealth();
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
status = "idle";
|
|
366
|
+
syncHealth();
|
|
367
|
+
throw toClientError(error, {
|
|
368
|
+
exchange: registered.exchange,
|
|
369
|
+
accountId: registered.accountId,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
async stop() {
|
|
374
|
+
if (status === "stopped") {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
status = "stopping";
|
|
378
|
+
syncHealth();
|
|
379
|
+
await activeClient?.stop();
|
|
380
|
+
status = "stopped";
|
|
381
|
+
syncHealth();
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
export function createClient(options = {}) {
|
|
386
|
+
return createPublicClient(options);
|
|
387
|
+
}
|
|
388
|
+
function toClientError(error, context) {
|
|
389
|
+
if (isAcexError(error)) {
|
|
390
|
+
return error;
|
|
391
|
+
}
|
|
392
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
393
|
+
return createAcexError({
|
|
394
|
+
code: message.includes("ccxt.pro.binanceusdm is not available")
|
|
395
|
+
? "CAPABILITY_NOT_SUPPORTED"
|
|
396
|
+
: "INTERNAL_ERROR",
|
|
397
|
+
message,
|
|
398
|
+
retryable: false,
|
|
399
|
+
...(context.exchange === undefined ? {} : { exchange: context.exchange }),
|
|
400
|
+
...(context.accountId === undefined ? {} : { accountId: context.accountId }),
|
|
401
|
+
cause: error,
|
|
402
|
+
});
|
|
45
403
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createClient } from "./core/client.js";
|
|
2
2
|
export { createAcexError, isAcexError } from "./errors/acex-error.js";
|
|
3
3
|
export { IMPLEMENTED_EXCHANGES } from "./types/public.js";
|
|
4
|
-
export type {
|
|
4
|
+
export type { AcexClient, CreateClientOptions, RegisterAccountInput, RegisterAccountResult, } from "./core/client.js";
|
|
5
|
+
export type { AcexErrorCode, ClientStatus, Exchange, ImplementedExchange, } from "./types/public.js";
|
|
5
6
|
export type { AcexError, CreateAcexErrorInput } from "./errors/acex-error.js";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type WsConnectionState = "idle" | "connecting" | "open" | "reconnecting" | "closed";
|
|
2
|
+
export interface WsSocketLike {
|
|
3
|
+
readyState: number;
|
|
4
|
+
send(data: string | ArrayBufferLike | Uint8Array): void;
|
|
5
|
+
close(code?: number, reason?: string): void;
|
|
6
|
+
ping?(data?: string | ArrayBufferLike | Uint8Array): void;
|
|
7
|
+
pong?(data?: string | ArrayBufferLike | Uint8Array): void;
|
|
8
|
+
terminate?(): void;
|
|
9
|
+
onopen: ((event: unknown) => void) | null;
|
|
10
|
+
onmessage: ((event: {
|
|
11
|
+
data: string | Buffer | ArrayBuffer | ArrayBufferView;
|
|
12
|
+
}) => void) | null;
|
|
13
|
+
onping?: ((event: {
|
|
14
|
+
data?: string | Buffer | ArrayBuffer | ArrayBufferView;
|
|
15
|
+
}) => void) | null;
|
|
16
|
+
onpong?: ((event: {
|
|
17
|
+
data?: string | Buffer | ArrayBuffer | ArrayBufferView;
|
|
18
|
+
}) => void) | null;
|
|
19
|
+
onclose: ((event: unknown) => void) | null;
|
|
20
|
+
onerror: ((event: unknown) => void) | null;
|
|
21
|
+
}
|
|
22
|
+
type CustomHeartbeatCleanup = (() => void | Promise<void>) | undefined;
|
|
23
|
+
type CustomHeartbeatContext = {
|
|
24
|
+
socket: WsSocketLike;
|
|
25
|
+
markActivity: () => void;
|
|
26
|
+
send: (data: string | ArrayBufferLike | Uint8Array) => void;
|
|
27
|
+
sleep: (ms: number) => Promise<void>;
|
|
28
|
+
now: () => number;
|
|
29
|
+
reportError: (error: unknown) => void;
|
|
30
|
+
};
|
|
31
|
+
type HeartbeatConfig = {
|
|
32
|
+
kind: "passive_read_timeout";
|
|
33
|
+
idleTimeoutMs: number;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "native_ping_pong";
|
|
36
|
+
heartbeatIntervalMs: number;
|
|
37
|
+
idleTimeoutMs: number;
|
|
38
|
+
} | {
|
|
39
|
+
kind: "app_ping_message";
|
|
40
|
+
heartbeatIntervalMs: number;
|
|
41
|
+
idleTimeoutMs: number;
|
|
42
|
+
buildPingMessage: () => string | ArrayBufferLike | Uint8Array;
|
|
43
|
+
} | {
|
|
44
|
+
kind: "custom";
|
|
45
|
+
idleTimeoutMs: number;
|
|
46
|
+
heartbeatIntervalMs?: number;
|
|
47
|
+
start: (context: CustomHeartbeatContext) => CustomHeartbeatCleanup | Promise<CustomHeartbeatCleanup>;
|
|
48
|
+
};
|
|
49
|
+
interface CreateWsConnectionSupervisorInput {
|
|
50
|
+
createSocket: () => WsSocketLike;
|
|
51
|
+
heartbeat: HeartbeatConfig;
|
|
52
|
+
backoff: {
|
|
53
|
+
baseDelayMs: number;
|
|
54
|
+
maxDelayMs: number;
|
|
55
|
+
jitter: boolean;
|
|
56
|
+
};
|
|
57
|
+
now?: () => number;
|
|
58
|
+
sleep?: (ms: number) => Promise<void>;
|
|
59
|
+
onOpen?: () => void;
|
|
60
|
+
onMessage?: (event: {
|
|
61
|
+
data: string | Buffer | ArrayBuffer | ArrayBufferView;
|
|
62
|
+
}) => void;
|
|
63
|
+
onClose?: () => void;
|
|
64
|
+
onDisconnect?: () => void;
|
|
65
|
+
onReconnect?: () => void | Promise<void>;
|
|
66
|
+
onError?: (error: Error) => void;
|
|
67
|
+
}
|
|
68
|
+
export interface WsConnectionSupervisor {
|
|
69
|
+
connect(): Promise<void>;
|
|
70
|
+
close(): Promise<void>;
|
|
71
|
+
send(data: string | ArrayBufferLike | Uint8Array): void;
|
|
72
|
+
getState(): WsConnectionState;
|
|
73
|
+
getLastActivityAt(): number | undefined;
|
|
74
|
+
}
|
|
75
|
+
export declare function createWsConnectionSupervisor(input: CreateWsConnectionSupervisorInput): WsConnectionSupervisor;
|
|
76
|
+
export {};
|