@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/src/adapters/types.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AccountCredentials,
|
|
3
3
|
CreateOrderType,
|
|
4
|
-
Exchange,
|
|
5
4
|
MarketDefinition,
|
|
6
5
|
OrderSide,
|
|
7
6
|
OrderStatus,
|
|
8
7
|
PositionSide,
|
|
8
|
+
Venue,
|
|
9
|
+
VenueAccountCapabilities,
|
|
10
|
+
VenueMarketCapabilities,
|
|
11
|
+
VenueOrderCapabilities,
|
|
9
12
|
} from "../types/index.ts";
|
|
10
13
|
|
|
11
14
|
export interface StreamHandle {
|
|
@@ -68,7 +71,8 @@ export interface FundingRateStreamOptions {
|
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
export interface MarketAdapter {
|
|
71
|
-
readonly
|
|
74
|
+
readonly venue: Venue;
|
|
75
|
+
readonly marketCapabilities: VenueMarketCapabilities;
|
|
72
76
|
loadMarkets(): Promise<MarketDefinition[]>;
|
|
73
77
|
createL1BookStream(
|
|
74
78
|
market: MarketDefinition,
|
|
@@ -89,6 +93,16 @@ export interface RawBalanceUpdate {
|
|
|
89
93
|
total?: string;
|
|
90
94
|
exchangeTs?: number;
|
|
91
95
|
receivedAt: number;
|
|
96
|
+
lending?: RawLendingBalanceUpdate;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface RawLendingBalanceUpdate {
|
|
100
|
+
supplied: string;
|
|
101
|
+
borrowed: string;
|
|
102
|
+
interest: string;
|
|
103
|
+
netAsset: string;
|
|
104
|
+
supplyAPY?: string;
|
|
105
|
+
borrowAPY?: string;
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
export interface RawPositionUpdate {
|
|
@@ -106,11 +120,21 @@ export interface RawPositionUpdate {
|
|
|
106
120
|
|
|
107
121
|
export interface RawRiskUpdate {
|
|
108
122
|
equity?: string;
|
|
109
|
-
|
|
123
|
+
riskRatio?: string;
|
|
110
124
|
initialMargin?: string;
|
|
111
125
|
maintenanceMargin?: string;
|
|
112
126
|
exchangeTs?: number;
|
|
113
127
|
receivedAt: number;
|
|
128
|
+
lending?: RawLendingRiskUpdate;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface RawLendingRiskUpdate {
|
|
132
|
+
marginLevel?: string;
|
|
133
|
+
healthFactor?: string;
|
|
134
|
+
ltv?: string;
|
|
135
|
+
liquidationThreshold?: string;
|
|
136
|
+
totalCollateralUSD?: string;
|
|
137
|
+
totalDebtUSD?: string;
|
|
114
138
|
}
|
|
115
139
|
|
|
116
140
|
export interface RawAccountBootstrap {
|
|
@@ -171,6 +195,7 @@ export interface CancelAllOrdersRequest {
|
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
export interface PrivateStreamCallbacks {
|
|
198
|
+
onAccountSnapshot(snapshot: RawAccountBootstrap): void;
|
|
174
199
|
onAccountUpdate(update: RawAccountUpdate): void;
|
|
175
200
|
onOrderUpdate(update: RawOrderUpdate): void;
|
|
176
201
|
onDisconnected(): void;
|
|
@@ -183,11 +208,16 @@ export interface PrivateStreamOptions {
|
|
|
183
208
|
reconnectDelayMs: number;
|
|
184
209
|
reconnectMaxDelayMs: number;
|
|
185
210
|
listenKeyKeepAliveMs: number;
|
|
211
|
+
juplendPollIntervalMs?: number;
|
|
186
212
|
now?: () => number;
|
|
187
213
|
}
|
|
188
214
|
|
|
189
215
|
export interface PrivateUserDataAdapter {
|
|
190
|
-
readonly
|
|
216
|
+
readonly venue: Venue;
|
|
217
|
+
readonly readOnly: boolean;
|
|
218
|
+
readonly notes: string[];
|
|
219
|
+
readonly accountCapabilities: VenueAccountCapabilities;
|
|
220
|
+
readonly orderCapabilities: VenueOrderCapabilities;
|
|
191
221
|
bootstrapAccount(
|
|
192
222
|
credentials: AccountCredentials,
|
|
193
223
|
accountOptions?: Record<string, unknown>,
|
package/src/client/context.ts
CHANGED
|
@@ -9,15 +9,15 @@ import type {
|
|
|
9
9
|
CancelAllOrdersInput,
|
|
10
10
|
CancelOrderInput,
|
|
11
11
|
CreateOrderInput,
|
|
12
|
-
Exchange,
|
|
13
12
|
HealthEvent,
|
|
14
13
|
PrivateRuntimeReason,
|
|
15
14
|
PrivateRuntimeStatus,
|
|
15
|
+
Venue,
|
|
16
16
|
} from "../types/index.ts";
|
|
17
17
|
|
|
18
18
|
export interface RegisteredAccountRecord {
|
|
19
19
|
accountId: string;
|
|
20
|
-
|
|
20
|
+
venue: Venue;
|
|
21
21
|
credentials?: AccountCredentials;
|
|
22
22
|
options?: Record<string, unknown>;
|
|
23
23
|
}
|
|
@@ -49,7 +49,7 @@ export interface ManagerLifecycle {
|
|
|
49
49
|
|
|
50
50
|
export interface AccountAwareManager {
|
|
51
51
|
onAccountRemoved(accountId: string, now: number): void;
|
|
52
|
-
onCredentialsUpdated(accountId: string,
|
|
52
|
+
onCredentialsUpdated(accountId: string, venue: Venue): void;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export interface HealthReporter<T> {
|
|
@@ -65,46 +65,51 @@ export interface PrivateSubscriptionState {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export interface PrivateAccountDataConsumer {
|
|
68
|
-
onPrivateAccountPending(accountId: string,
|
|
68
|
+
onPrivateAccountPending(accountId: string, venue: Venue): void;
|
|
69
69
|
onPrivateAccountBootstrap(
|
|
70
70
|
accountId: string,
|
|
71
|
-
|
|
71
|
+
venue: Venue,
|
|
72
72
|
bootstrap: RawAccountBootstrap,
|
|
73
73
|
): void;
|
|
74
74
|
onPrivateAccountUpdate(
|
|
75
75
|
accountId: string,
|
|
76
|
-
|
|
76
|
+
venue: Venue,
|
|
77
77
|
update: RawAccountUpdate,
|
|
78
78
|
): void;
|
|
79
79
|
onPrivateAccountStreamState(
|
|
80
80
|
accountId: string,
|
|
81
|
-
|
|
81
|
+
venue: Venue,
|
|
82
82
|
state: PrivateSubscriptionState,
|
|
83
83
|
): void;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export interface PrivateOrderDataConsumer {
|
|
87
|
-
onPrivateOrderPending(accountId: string,
|
|
87
|
+
onPrivateOrderPending(accountId: string, venue: Venue): void;
|
|
88
88
|
onPrivateOrderBootstrap(
|
|
89
89
|
accountId: string,
|
|
90
|
-
|
|
90
|
+
venue: Venue,
|
|
91
91
|
snapshots: RawOrderUpdate[],
|
|
92
92
|
): void;
|
|
93
93
|
onPrivateOrderUpdate(
|
|
94
94
|
accountId: string,
|
|
95
|
-
|
|
95
|
+
venue: Venue,
|
|
96
96
|
update: RawOrderUpdate,
|
|
97
97
|
): void;
|
|
98
98
|
onPrivateOrderStreamState(
|
|
99
99
|
accountId: string,
|
|
100
|
-
|
|
100
|
+
venue: Venue,
|
|
101
101
|
state: PrivateSubscriptionState,
|
|
102
102
|
): void;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export function hasPrivateCredentials(
|
|
106
106
|
credentials?: AccountCredentials,
|
|
107
|
+
venue?: Venue,
|
|
107
108
|
): boolean {
|
|
109
|
+
if (venue === "juplend") {
|
|
110
|
+
return Boolean(credentials?.apiKey);
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
return Boolean(credentials?.apiKey && credentials.secret);
|
|
109
114
|
}
|
|
110
115
|
|
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
StreamHandle,
|
|
4
4
|
} from "../adapters/types.ts";
|
|
5
5
|
import { AcexError } from "../errors.ts";
|
|
6
|
-
import type { AccountRuntimeOptions,
|
|
6
|
+
import type { AccountRuntimeOptions, Venue } from "../types/index.ts";
|
|
7
7
|
import type {
|
|
8
8
|
ClientContext,
|
|
9
9
|
PrivateAccountDataConsumer,
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
|
|
14
14
|
interface PrivateSubscriptionRecord {
|
|
15
15
|
accountId: string;
|
|
16
|
-
|
|
16
|
+
venue: Venue;
|
|
17
17
|
accountSubscribed: boolean;
|
|
18
18
|
ordersSubscribed: boolean;
|
|
19
19
|
accountReady: boolean;
|
|
@@ -30,24 +30,27 @@ const DEFAULT_LISTEN_KEY_KEEPALIVE_MS = 30 * 60 * 1_000;
|
|
|
30
30
|
|
|
31
31
|
export class PrivateSubscriptionCoordinator {
|
|
32
32
|
private readonly context: ClientContext;
|
|
33
|
-
private readonly
|
|
33
|
+
private readonly adapters: Map<Venue, PrivateUserDataAdapter>;
|
|
34
34
|
private readonly accountConsumer: PrivateAccountDataConsumer;
|
|
35
35
|
private readonly orderConsumer: PrivateOrderDataConsumer;
|
|
36
36
|
private readonly streamOpenTimeoutMs: number;
|
|
37
37
|
private readonly streamReconnectDelayMs: number;
|
|
38
38
|
private readonly streamReconnectMaxDelayMs: number;
|
|
39
39
|
private readonly listenKeyKeepAliveMs: number;
|
|
40
|
+
private readonly juplendPollIntervalMs?: number;
|
|
40
41
|
private readonly records = new Map<string, PrivateSubscriptionRecord>();
|
|
41
42
|
|
|
42
43
|
constructor(
|
|
43
44
|
context: ClientContext,
|
|
44
|
-
|
|
45
|
+
adapters: PrivateUserDataAdapter[],
|
|
45
46
|
accountConsumer: PrivateAccountDataConsumer,
|
|
46
47
|
orderConsumer: PrivateOrderDataConsumer,
|
|
47
48
|
options: AccountRuntimeOptions = {},
|
|
48
49
|
) {
|
|
49
50
|
this.context = context;
|
|
50
|
-
this.
|
|
51
|
+
this.adapters = new Map(
|
|
52
|
+
adapters.map((adapter) => [adapter.venue, adapter]),
|
|
53
|
+
);
|
|
51
54
|
this.accountConsumer = accountConsumer;
|
|
52
55
|
this.orderConsumer = orderConsumer;
|
|
53
56
|
this.streamOpenTimeoutMs =
|
|
@@ -59,6 +62,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
59
62
|
DEFAULT_STREAM_RECONNECT_MAX_DELAY_MS;
|
|
60
63
|
this.listenKeyKeepAliveMs =
|
|
61
64
|
options.listenKeyKeepAliveMs ?? DEFAULT_LISTEN_KEY_KEEPALIVE_MS;
|
|
65
|
+
this.juplendPollIntervalMs = options.juplend?.pollIntervalMs;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
async subscribeAccountFeed(accountId: string): Promise<void> {
|
|
@@ -67,12 +71,17 @@ export class PrivateSubscriptionCoordinator {
|
|
|
67
71
|
const needsPending = !record.stream && !record.startPromise;
|
|
68
72
|
record.accountSubscribed = true;
|
|
69
73
|
if (needsPending) {
|
|
70
|
-
this.accountConsumer.onPrivateAccountPending(accountId, record.
|
|
74
|
+
this.accountConsumer.onPrivateAccountPending(accountId, record.venue);
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
if (record.venue === "juplend") {
|
|
79
|
+
await this.bootstrapAccount(record, account);
|
|
80
|
+
await this.ensureStream(record, account);
|
|
81
|
+
} else {
|
|
82
|
+
await this.ensureStream(record, account);
|
|
83
|
+
await this.bootstrapAccount(record, account);
|
|
84
|
+
}
|
|
76
85
|
} catch (error) {
|
|
77
86
|
record.accountSubscribed = false;
|
|
78
87
|
this.closeIfUnused(record);
|
|
@@ -96,7 +105,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
96
105
|
const needsPending = !record.stream && !record.startPromise;
|
|
97
106
|
record.ordersSubscribed = true;
|
|
98
107
|
if (needsPending) {
|
|
99
|
-
this.orderConsumer.onPrivateOrderPending(accountId, record.
|
|
108
|
+
this.orderConsumer.onPrivateOrderPending(accountId, record.venue);
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
try {
|
|
@@ -128,13 +137,13 @@ export class PrivateSubscriptionCoordinator {
|
|
|
128
137
|
if (record.accountSubscribed) {
|
|
129
138
|
this.accountConsumer.onPrivateAccountPending(
|
|
130
139
|
record.accountId,
|
|
131
|
-
record.
|
|
140
|
+
record.venue,
|
|
132
141
|
);
|
|
133
142
|
}
|
|
134
143
|
if (record.ordersSubscribed) {
|
|
135
144
|
this.orderConsumer.onPrivateOrderPending(
|
|
136
145
|
record.accountId,
|
|
137
|
-
record.
|
|
146
|
+
record.venue,
|
|
138
147
|
);
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -165,10 +174,10 @@ export class PrivateSubscriptionCoordinator {
|
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
if (record.accountSubscribed) {
|
|
168
|
-
this.accountConsumer.onPrivateAccountPending(accountId, record.
|
|
177
|
+
this.accountConsumer.onPrivateAccountPending(accountId, record.venue);
|
|
169
178
|
}
|
|
170
179
|
if (record.ordersSubscribed) {
|
|
171
|
-
this.orderConsumer.onPrivateOrderPending(accountId, record.
|
|
180
|
+
this.orderConsumer.onPrivateOrderPending(accountId, record.venue);
|
|
172
181
|
}
|
|
173
182
|
|
|
174
183
|
void this.resumeRecord(record);
|
|
@@ -179,9 +188,14 @@ export class PrivateSubscriptionCoordinator {
|
|
|
179
188
|
this.closeStream(record);
|
|
180
189
|
|
|
181
190
|
try {
|
|
182
|
-
|
|
183
|
-
if (record.accountSubscribed) {
|
|
191
|
+
if (record.venue === "juplend" && record.accountSubscribed) {
|
|
184
192
|
await this.bootstrapAccount(record, account);
|
|
193
|
+
await this.ensureStream(record, account);
|
|
194
|
+
} else {
|
|
195
|
+
await this.ensureStream(record, account);
|
|
196
|
+
if (record.accountSubscribed) {
|
|
197
|
+
await this.bootstrapAccount(record, account);
|
|
198
|
+
}
|
|
185
199
|
}
|
|
186
200
|
if (record.ordersSubscribed) {
|
|
187
201
|
await this.bootstrapOrders(record, account);
|
|
@@ -193,16 +207,28 @@ export class PrivateSubscriptionCoordinator {
|
|
|
193
207
|
|
|
194
208
|
private getAccount(accountId: string): RegisteredAccountRecord {
|
|
195
209
|
const account = this.context.getRegisteredAccount(accountId);
|
|
196
|
-
if (
|
|
210
|
+
if (!this.adapters.has(account.venue)) {
|
|
197
211
|
throw new AcexError(
|
|
198
|
-
"
|
|
199
|
-
`
|
|
212
|
+
"VENUE_NOT_SUPPORTED",
|
|
213
|
+
`Venue is not supported yet: ${account.venue}`,
|
|
200
214
|
);
|
|
201
215
|
}
|
|
202
216
|
|
|
203
217
|
return account;
|
|
204
218
|
}
|
|
205
219
|
|
|
220
|
+
private getAdapter(venue: Venue): PrivateUserDataAdapter {
|
|
221
|
+
const adapter = this.adapters.get(venue);
|
|
222
|
+
if (!adapter) {
|
|
223
|
+
throw new AcexError(
|
|
224
|
+
"VENUE_NOT_SUPPORTED",
|
|
225
|
+
`Venue is not supported yet: ${venue}`,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return adapter;
|
|
230
|
+
}
|
|
231
|
+
|
|
206
232
|
private getOrCreateRecord(
|
|
207
233
|
account: RegisteredAccountRecord,
|
|
208
234
|
): PrivateSubscriptionRecord {
|
|
@@ -213,7 +239,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
213
239
|
|
|
214
240
|
const record: PrivateSubscriptionRecord = {
|
|
215
241
|
accountId: account.accountId,
|
|
216
|
-
|
|
242
|
+
venue: account.venue,
|
|
217
243
|
accountSubscribed: false,
|
|
218
244
|
ordersSubscribed: false,
|
|
219
245
|
accountReady: false,
|
|
@@ -275,9 +301,22 @@ export class PrivateSubscriptionCoordinator {
|
|
|
275
301
|
);
|
|
276
302
|
}
|
|
277
303
|
|
|
278
|
-
const
|
|
304
|
+
const adapter = this.getAdapter(record.venue);
|
|
305
|
+
const stream = adapter.createPrivateStream(
|
|
279
306
|
credentials,
|
|
280
307
|
{
|
|
308
|
+
onAccountSnapshot: (snapshot) => {
|
|
309
|
+
if (!record.accountSubscribed) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
record.accountReady = true;
|
|
314
|
+
this.accountConsumer.onPrivateAccountBootstrap(
|
|
315
|
+
record.accountId,
|
|
316
|
+
record.venue,
|
|
317
|
+
snapshot,
|
|
318
|
+
);
|
|
319
|
+
},
|
|
281
320
|
onAccountUpdate: (update) => {
|
|
282
321
|
if (!record.accountSubscribed) {
|
|
283
322
|
return;
|
|
@@ -286,7 +325,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
286
325
|
record.accountReady = true;
|
|
287
326
|
this.accountConsumer.onPrivateAccountUpdate(
|
|
288
327
|
record.accountId,
|
|
289
|
-
record.
|
|
328
|
+
record.venue,
|
|
290
329
|
update,
|
|
291
330
|
);
|
|
292
331
|
},
|
|
@@ -298,7 +337,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
298
337
|
record.orderReady = true;
|
|
299
338
|
this.orderConsumer.onPrivateOrderUpdate(
|
|
300
339
|
record.accountId,
|
|
301
|
-
record.
|
|
340
|
+
record.venue,
|
|
302
341
|
update,
|
|
303
342
|
);
|
|
304
343
|
},
|
|
@@ -306,7 +345,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
306
345
|
if (record.accountSubscribed) {
|
|
307
346
|
this.accountConsumer.onPrivateAccountStreamState(
|
|
308
347
|
record.accountId,
|
|
309
|
-
record.
|
|
348
|
+
record.venue,
|
|
310
349
|
{
|
|
311
350
|
runtimeStatus: "reconnecting",
|
|
312
351
|
ready: record.accountReady,
|
|
@@ -317,7 +356,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
317
356
|
if (record.ordersSubscribed) {
|
|
318
357
|
this.orderConsumer.onPrivateOrderStreamState(
|
|
319
358
|
record.accountId,
|
|
320
|
-
record.
|
|
359
|
+
record.venue,
|
|
321
360
|
{
|
|
322
361
|
runtimeStatus: "reconnecting",
|
|
323
362
|
ready: record.orderReady,
|
|
@@ -338,8 +377,19 @@ export class PrivateSubscriptionCoordinator {
|
|
|
338
377
|
onError: (error) => {
|
|
339
378
|
this.context.publishRuntimeError("adapter", error, {
|
|
340
379
|
accountId: record.accountId,
|
|
341
|
-
|
|
380
|
+
venue: record.venue,
|
|
342
381
|
});
|
|
382
|
+
if (record.accountSubscribed) {
|
|
383
|
+
this.accountConsumer.onPrivateAccountStreamState(
|
|
384
|
+
record.accountId,
|
|
385
|
+
record.venue,
|
|
386
|
+
{
|
|
387
|
+
runtimeStatus: "degraded",
|
|
388
|
+
ready: record.accountReady,
|
|
389
|
+
reason: "http_failed",
|
|
390
|
+
},
|
|
391
|
+
);
|
|
392
|
+
}
|
|
343
393
|
},
|
|
344
394
|
},
|
|
345
395
|
{
|
|
@@ -347,6 +397,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
347
397
|
reconnectDelayMs: this.streamReconnectDelayMs,
|
|
348
398
|
reconnectMaxDelayMs: this.streamReconnectMaxDelayMs,
|
|
349
399
|
listenKeyKeepAliveMs: this.listenKeyKeepAliveMs,
|
|
400
|
+
juplendPollIntervalMs: this.juplendPollIntervalMs,
|
|
350
401
|
now: () => this.context.now(),
|
|
351
402
|
},
|
|
352
403
|
account.options,
|
|
@@ -361,16 +412,16 @@ export class PrivateSubscriptionCoordinator {
|
|
|
361
412
|
const runtimeError =
|
|
362
413
|
error instanceof Error
|
|
363
414
|
? error
|
|
364
|
-
: new Error(
|
|
415
|
+
: new Error(`Failed to open ${record.venue} private stream`);
|
|
365
416
|
this.context.publishRuntimeError("adapter", runtimeError, {
|
|
366
417
|
accountId: record.accountId,
|
|
367
|
-
|
|
418
|
+
venue: record.venue,
|
|
368
419
|
});
|
|
369
420
|
|
|
370
421
|
if (record.accountSubscribed) {
|
|
371
422
|
this.accountConsumer.onPrivateAccountStreamState(
|
|
372
423
|
record.accountId,
|
|
373
|
-
record.
|
|
424
|
+
record.venue,
|
|
374
425
|
{
|
|
375
426
|
runtimeStatus: "degraded",
|
|
376
427
|
ready: record.accountReady,
|
|
@@ -381,7 +432,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
381
432
|
if (record.ordersSubscribed) {
|
|
382
433
|
this.orderConsumer.onPrivateOrderStreamState(
|
|
383
434
|
record.accountId,
|
|
384
|
-
record.
|
|
435
|
+
record.venue,
|
|
385
436
|
{
|
|
386
437
|
runtimeStatus: "degraded",
|
|
387
438
|
ready: record.orderReady,
|
|
@@ -402,16 +453,13 @@ export class PrivateSubscriptionCoordinator {
|
|
|
402
453
|
if (record.accountSubscribed) {
|
|
403
454
|
this.accountConsumer.onPrivateAccountPending(
|
|
404
455
|
record.accountId,
|
|
405
|
-
record.
|
|
456
|
+
record.venue,
|
|
406
457
|
);
|
|
407
458
|
await this.bootstrapAccount(record, account);
|
|
408
459
|
}
|
|
409
460
|
|
|
410
461
|
if (record.ordersSubscribed) {
|
|
411
|
-
this.orderConsumer.onPrivateOrderPending(
|
|
412
|
-
record.accountId,
|
|
413
|
-
record.exchange,
|
|
414
|
-
);
|
|
462
|
+
this.orderConsumer.onPrivateOrderPending(record.accountId, record.venue);
|
|
415
463
|
await this.bootstrapOrders(record, account);
|
|
416
464
|
}
|
|
417
465
|
}
|
|
@@ -421,9 +469,9 @@ export class PrivateSubscriptionCoordinator {
|
|
|
421
469
|
account: RegisteredAccountRecord,
|
|
422
470
|
): Promise<void> {
|
|
423
471
|
try {
|
|
424
|
-
const bootstrap = await this.
|
|
472
|
+
const bootstrap = await this.getAdapter(record.venue).bootstrapAccount(
|
|
425
473
|
account.credentials ?? {},
|
|
426
|
-
account.options,
|
|
474
|
+
{ ...account.options, accountId: account.accountId },
|
|
427
475
|
);
|
|
428
476
|
if (!record.accountSubscribed) {
|
|
429
477
|
return;
|
|
@@ -432,7 +480,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
432
480
|
record.accountReady = true;
|
|
433
481
|
this.accountConsumer.onPrivateAccountBootstrap(
|
|
434
482
|
record.accountId,
|
|
435
|
-
record.
|
|
483
|
+
record.venue,
|
|
436
484
|
bootstrap,
|
|
437
485
|
);
|
|
438
486
|
} catch (error) {
|
|
@@ -441,24 +489,28 @@ export class PrivateSubscriptionCoordinator {
|
|
|
441
489
|
"adapter",
|
|
442
490
|
error instanceof Error
|
|
443
491
|
? error
|
|
444
|
-
: new Error(
|
|
492
|
+
: new Error(
|
|
493
|
+
`Failed to bootstrap ${record.venue} private account state`,
|
|
494
|
+
),
|
|
445
495
|
{
|
|
446
496
|
accountId: record.accountId,
|
|
447
|
-
|
|
497
|
+
venue: record.venue,
|
|
448
498
|
},
|
|
449
499
|
);
|
|
450
500
|
this.accountConsumer.onPrivateAccountStreamState(
|
|
451
501
|
record.accountId,
|
|
452
|
-
record.
|
|
502
|
+
record.venue,
|
|
453
503
|
{
|
|
454
504
|
runtimeStatus: "degraded",
|
|
455
505
|
ready: false,
|
|
456
|
-
reason: "auth_failed",
|
|
506
|
+
reason: record.venue === "juplend" ? "http_failed" : "auth_failed",
|
|
457
507
|
},
|
|
458
508
|
);
|
|
509
|
+
const reason =
|
|
510
|
+
error instanceof Error && error.message ? ` (${error.message})` : "";
|
|
459
511
|
throw new AcexError(
|
|
460
512
|
"ACCOUNT_BOOTSTRAP_FAILED",
|
|
461
|
-
`Failed to bootstrap account data: ${record.accountId}`,
|
|
513
|
+
`Failed to bootstrap account data: ${record.accountId}${reason}`,
|
|
462
514
|
);
|
|
463
515
|
}
|
|
464
516
|
}
|
|
@@ -468,7 +520,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
468
520
|
account: RegisteredAccountRecord,
|
|
469
521
|
): Promise<void> {
|
|
470
522
|
try {
|
|
471
|
-
const snapshots = await this.
|
|
523
|
+
const snapshots = await this.getAdapter(record.venue).bootstrapOpenOrders(
|
|
472
524
|
account.credentials ?? {},
|
|
473
525
|
account.options,
|
|
474
526
|
);
|
|
@@ -479,7 +531,7 @@ export class PrivateSubscriptionCoordinator {
|
|
|
479
531
|
record.orderReady = true;
|
|
480
532
|
this.orderConsumer.onPrivateOrderBootstrap(
|
|
481
533
|
record.accountId,
|
|
482
|
-
record.
|
|
534
|
+
record.venue,
|
|
483
535
|
snapshots,
|
|
484
536
|
);
|
|
485
537
|
} catch (error) {
|
|
@@ -488,15 +540,17 @@ export class PrivateSubscriptionCoordinator {
|
|
|
488
540
|
"adapter",
|
|
489
541
|
error instanceof Error
|
|
490
542
|
? error
|
|
491
|
-
: new Error(
|
|
543
|
+
: new Error(
|
|
544
|
+
`Failed to bootstrap ${record.venue} private order state`,
|
|
545
|
+
),
|
|
492
546
|
{
|
|
493
547
|
accountId: record.accountId,
|
|
494
|
-
|
|
548
|
+
venue: record.venue,
|
|
495
549
|
},
|
|
496
550
|
);
|
|
497
551
|
this.orderConsumer.onPrivateOrderStreamState(
|
|
498
552
|
record.accountId,
|
|
499
|
-
record.
|
|
553
|
+
record.venue,
|
|
500
554
|
{
|
|
501
555
|
runtimeStatus: "degraded",
|
|
502
556
|
ready: false,
|