@imbingox/acex 0.3.0-beta.1 → 0.3.0-beta.2
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 +54 -24
- package/package.json +3 -1
- package/src/adapters/binance/adapter.ts +1 -1
- package/src/adapters/binance/market-catalog.ts +2 -2
- package/src/adapters/binance/private-adapter.ts +8 -3
- package/src/adapters/juplend/private-adapter.ts +483 -0
- package/src/adapters/types.ts +26 -4
- package/src/client/context.ts +16 -11
- package/src/client/private-subscription-coordinator.ts +101 -47
- package/src/client/runtime.ts +42 -20
- 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 +2 -2
- package/src/types/market.ts +12 -16
- package/src/types/order.ts +7 -7
- package/src/types/shared.ts +43 -7
|
@@ -25,17 +25,17 @@ import type {
|
|
|
25
25
|
AccountSnapshotReplacedEvent,
|
|
26
26
|
AccountStatusChangedEvent,
|
|
27
27
|
BalanceSnapshot,
|
|
28
|
-
Exchange,
|
|
29
28
|
PositionKeyInput,
|
|
30
29
|
PositionSnapshot,
|
|
31
30
|
RiskSnapshot,
|
|
32
31
|
SubscribeAccountInput,
|
|
33
32
|
UnsubscribeAccountInput,
|
|
33
|
+
Venue,
|
|
34
34
|
} from "../types/index.ts";
|
|
35
35
|
|
|
36
36
|
interface AccountRecord {
|
|
37
37
|
accountId: string;
|
|
38
|
-
|
|
38
|
+
venue: Venue;
|
|
39
39
|
subscribed: boolean;
|
|
40
40
|
snapshot?: AccountSnapshot;
|
|
41
41
|
status: AccountDataStatus;
|
|
@@ -79,7 +79,7 @@ export class AccountManagerImpl
|
|
|
79
79
|
status: (filter) =>
|
|
80
80
|
this.accountStatusBus.stream((event) =>
|
|
81
81
|
matchesAccountFilter(
|
|
82
|
-
{ accountId: event.accountId,
|
|
82
|
+
{ accountId: event.accountId, venue: event.venue },
|
|
83
83
|
filter,
|
|
84
84
|
),
|
|
85
85
|
),
|
|
@@ -88,7 +88,7 @@ export class AccountManagerImpl
|
|
|
88
88
|
matchesAccountFilter(
|
|
89
89
|
{
|
|
90
90
|
accountId: event.accountId,
|
|
91
|
-
|
|
91
|
+
venue: event.venue,
|
|
92
92
|
symbol: "symbol" in event ? event.symbol : undefined,
|
|
93
93
|
},
|
|
94
94
|
filter,
|
|
@@ -104,7 +104,7 @@ export class AccountManagerImpl
|
|
|
104
104
|
const account = this.context.getRegisteredAccount(input.accountId);
|
|
105
105
|
this.context.ensurePrivateCredentials(input.accountId);
|
|
106
106
|
|
|
107
|
-
const record = this.getOrCreateRecord(input.accountId, account.
|
|
107
|
+
const record = this.getOrCreateRecord(input.accountId, account.venue);
|
|
108
108
|
record.subscribed = true;
|
|
109
109
|
|
|
110
110
|
try {
|
|
@@ -210,25 +210,25 @@ export class AccountManagerImpl
|
|
|
210
210
|
this.records.delete(accountId);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
onCredentialsUpdated(accountId: string,
|
|
213
|
+
onCredentialsUpdated(accountId: string, venue: Venue): void {
|
|
214
214
|
const record = this.records.get(accountId);
|
|
215
215
|
if (!record?.subscribed) {
|
|
216
216
|
return;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
this.onPrivateAccountPending(accountId,
|
|
219
|
+
this.onPrivateAccountPending(accountId, venue);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
// --- PrivateAccountDataConsumer ---
|
|
223
223
|
|
|
224
|
-
onPrivateAccountPending(accountId: string,
|
|
225
|
-
const record = this.getOrCreateRecord(accountId,
|
|
224
|
+
onPrivateAccountPending(accountId: string, venue: Venue): void {
|
|
225
|
+
const record = this.getOrCreateRecord(accountId, venue);
|
|
226
226
|
if (!record.subscribed) {
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
record.status = {
|
|
231
|
-
...this.createStatus(accountId,
|
|
231
|
+
...this.createStatus(accountId, venue, "active"),
|
|
232
232
|
ready: Boolean(record.snapshot),
|
|
233
233
|
runtimeStatus: "bootstrap_pending",
|
|
234
234
|
reason: undefined,
|
|
@@ -241,19 +241,15 @@ export class AccountManagerImpl
|
|
|
241
241
|
|
|
242
242
|
onPrivateAccountBootstrap(
|
|
243
243
|
accountId: string,
|
|
244
|
-
|
|
244
|
+
venue: Venue,
|
|
245
245
|
bootstrap: RawAccountBootstrap,
|
|
246
246
|
): void {
|
|
247
|
-
const record = this.getOrCreateRecord(accountId,
|
|
247
|
+
const record = this.getOrCreateRecord(accountId, venue);
|
|
248
248
|
if (!record.subscribed) {
|
|
249
249
|
return;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
record.snapshot = this.createBootstrapSnapshot(
|
|
253
|
-
accountId,
|
|
254
|
-
exchange,
|
|
255
|
-
bootstrap,
|
|
256
|
-
);
|
|
252
|
+
record.snapshot = this.createBootstrapSnapshot(accountId, venue, bootstrap);
|
|
257
253
|
record.status = {
|
|
258
254
|
...record.status,
|
|
259
255
|
activity: "active",
|
|
@@ -268,7 +264,7 @@ export class AccountManagerImpl
|
|
|
268
264
|
const event: AccountSnapshotReplacedEvent = {
|
|
269
265
|
type: "account.snapshot_replaced",
|
|
270
266
|
accountId,
|
|
271
|
-
|
|
267
|
+
venue,
|
|
272
268
|
snapshot: record.snapshot,
|
|
273
269
|
ts: this.context.now(),
|
|
274
270
|
};
|
|
@@ -279,16 +275,16 @@ export class AccountManagerImpl
|
|
|
279
275
|
|
|
280
276
|
onPrivateAccountUpdate(
|
|
281
277
|
accountId: string,
|
|
282
|
-
|
|
278
|
+
venue: Venue,
|
|
283
279
|
update: RawAccountUpdate,
|
|
284
280
|
): void {
|
|
285
|
-
const record = this.getOrCreateRecord(accountId,
|
|
281
|
+
const record = this.getOrCreateRecord(accountId, venue);
|
|
286
282
|
if (!record.subscribed) {
|
|
287
283
|
return;
|
|
288
284
|
}
|
|
289
285
|
|
|
290
286
|
const previous =
|
|
291
|
-
record.snapshot ?? this.createEmptySnapshot(accountId,
|
|
287
|
+
record.snapshot ?? this.createEmptySnapshot(accountId, venue);
|
|
292
288
|
const balances = { ...previous.balances };
|
|
293
289
|
const positions = new Map(
|
|
294
290
|
previous.positions.map((position) => [
|
|
@@ -301,7 +297,7 @@ export class AccountManagerImpl
|
|
|
301
297
|
for (const balance of update.balances ?? []) {
|
|
302
298
|
const nextBalance = this.createBalance(
|
|
303
299
|
accountId,
|
|
304
|
-
|
|
300
|
+
venue,
|
|
305
301
|
balance,
|
|
306
302
|
balances[balance.asset],
|
|
307
303
|
);
|
|
@@ -309,7 +305,7 @@ export class AccountManagerImpl
|
|
|
309
305
|
this.accountBus.publish({
|
|
310
306
|
type: "balance.updated",
|
|
311
307
|
accountId,
|
|
312
|
-
|
|
308
|
+
venue,
|
|
313
309
|
asset: balance.asset,
|
|
314
310
|
snapshot: nextBalance,
|
|
315
311
|
ts: this.context.now(),
|
|
@@ -320,7 +316,7 @@ export class AccountManagerImpl
|
|
|
320
316
|
const key = positionKey(position.symbol, position.side);
|
|
321
317
|
const nextPosition = this.createPosition(
|
|
322
318
|
accountId,
|
|
323
|
-
|
|
319
|
+
venue,
|
|
324
320
|
position,
|
|
325
321
|
positions.get(key),
|
|
326
322
|
);
|
|
@@ -334,7 +330,7 @@ export class AccountManagerImpl
|
|
|
334
330
|
this.accountBus.publish({
|
|
335
331
|
type: "position.updated",
|
|
336
332
|
accountId,
|
|
337
|
-
|
|
333
|
+
venue,
|
|
338
334
|
symbol: position.symbol,
|
|
339
335
|
snapshot: nextPosition,
|
|
340
336
|
ts: this.context.now(),
|
|
@@ -342,11 +338,11 @@ export class AccountManagerImpl
|
|
|
342
338
|
}
|
|
343
339
|
|
|
344
340
|
if (update.risk) {
|
|
345
|
-
risk = this.createRisk(accountId,
|
|
341
|
+
risk = this.createRisk(accountId, venue, update.risk, previous.risk);
|
|
346
342
|
this.accountBus.publish({
|
|
347
343
|
type: "risk.updated",
|
|
348
344
|
accountId,
|
|
349
|
-
|
|
345
|
+
venue,
|
|
350
346
|
snapshot: risk,
|
|
351
347
|
ts: this.context.now(),
|
|
352
348
|
});
|
|
@@ -354,7 +350,7 @@ export class AccountManagerImpl
|
|
|
354
350
|
|
|
355
351
|
record.snapshot = {
|
|
356
352
|
accountId,
|
|
357
|
-
|
|
353
|
+
venue,
|
|
358
354
|
balances,
|
|
359
355
|
positions: [...positions.values()],
|
|
360
356
|
risk,
|
|
@@ -377,10 +373,10 @@ export class AccountManagerImpl
|
|
|
377
373
|
|
|
378
374
|
onPrivateAccountStreamState(
|
|
379
375
|
accountId: string,
|
|
380
|
-
|
|
376
|
+
venue: Venue,
|
|
381
377
|
state: PrivateSubscriptionState,
|
|
382
378
|
): void {
|
|
383
|
-
const record = this.getOrCreateRecord(accountId,
|
|
379
|
+
const record = this.getOrCreateRecord(accountId, venue);
|
|
384
380
|
if (!record.subscribed) {
|
|
385
381
|
return;
|
|
386
382
|
}
|
|
@@ -404,18 +400,15 @@ export class AccountManagerImpl
|
|
|
404
400
|
return [...this.records.values()]
|
|
405
401
|
.map((record) => cloneAccountStatus(record.status))
|
|
406
402
|
.sort((left, right) =>
|
|
407
|
-
`${left.
|
|
408
|
-
`${right.
|
|
403
|
+
`${left.venue}:${left.accountId}`.localeCompare(
|
|
404
|
+
`${right.venue}:${right.accountId}`,
|
|
409
405
|
),
|
|
410
406
|
);
|
|
411
407
|
}
|
|
412
408
|
|
|
413
409
|
// --- Internal helpers ---
|
|
414
410
|
|
|
415
|
-
private getOrCreateRecord(
|
|
416
|
-
accountId: string,
|
|
417
|
-
exchange: Exchange,
|
|
418
|
-
): AccountRecord {
|
|
411
|
+
private getOrCreateRecord(accountId: string, venue: Venue): AccountRecord {
|
|
419
412
|
const existing = this.records.get(accountId);
|
|
420
413
|
if (existing) {
|
|
421
414
|
return existing;
|
|
@@ -423,9 +416,9 @@ export class AccountManagerImpl
|
|
|
423
416
|
|
|
424
417
|
const record: AccountRecord = {
|
|
425
418
|
accountId,
|
|
426
|
-
|
|
419
|
+
venue,
|
|
427
420
|
subscribed: false,
|
|
428
|
-
status: this.createStatus(accountId,
|
|
421
|
+
status: this.createStatus(accountId, venue, "inactive"),
|
|
429
422
|
};
|
|
430
423
|
|
|
431
424
|
this.records.set(accountId, record);
|
|
@@ -434,12 +427,12 @@ export class AccountManagerImpl
|
|
|
434
427
|
|
|
435
428
|
private createStatus(
|
|
436
429
|
accountId: string,
|
|
437
|
-
|
|
430
|
+
venue: Venue,
|
|
438
431
|
activity: "active" | "inactive",
|
|
439
432
|
): AccountDataStatus {
|
|
440
433
|
return {
|
|
441
434
|
accountId,
|
|
442
|
-
|
|
435
|
+
venue,
|
|
443
436
|
activity,
|
|
444
437
|
ready: false,
|
|
445
438
|
runtimeStatus: activity === "active" ? "bootstrap_pending" : "stopped",
|
|
@@ -448,25 +441,25 @@ export class AccountManagerImpl
|
|
|
448
441
|
|
|
449
442
|
private createBootstrapSnapshot(
|
|
450
443
|
accountId: string,
|
|
451
|
-
|
|
444
|
+
venue: Venue,
|
|
452
445
|
bootstrap: RawAccountBootstrap,
|
|
453
446
|
): AccountSnapshot {
|
|
454
447
|
const balances = Object.fromEntries(
|
|
455
448
|
bootstrap.balances.map((balance) => [
|
|
456
449
|
balance.asset,
|
|
457
|
-
this.createBalance(accountId,
|
|
450
|
+
this.createBalance(accountId, venue, balance),
|
|
458
451
|
]),
|
|
459
452
|
);
|
|
460
453
|
const positions = bootstrap.positions
|
|
461
|
-
.map((position) => this.createPosition(accountId,
|
|
454
|
+
.map((position) => this.createPosition(accountId, venue, position))
|
|
462
455
|
.filter((position) => !position.size.isZero());
|
|
463
456
|
const risk = bootstrap.risk
|
|
464
|
-
? this.createRisk(accountId,
|
|
457
|
+
? this.createRisk(accountId, venue, bootstrap.risk)
|
|
465
458
|
: undefined;
|
|
466
459
|
|
|
467
460
|
return {
|
|
468
461
|
accountId,
|
|
469
|
-
|
|
462
|
+
venue,
|
|
470
463
|
balances,
|
|
471
464
|
positions,
|
|
472
465
|
risk,
|
|
@@ -478,12 +471,12 @@ export class AccountManagerImpl
|
|
|
478
471
|
|
|
479
472
|
private createEmptySnapshot(
|
|
480
473
|
accountId: string,
|
|
481
|
-
|
|
474
|
+
venue: Venue,
|
|
482
475
|
): AccountSnapshot {
|
|
483
476
|
const now = this.context.now();
|
|
484
477
|
return {
|
|
485
478
|
accountId,
|
|
486
|
-
|
|
479
|
+
venue,
|
|
487
480
|
balances: {},
|
|
488
481
|
positions: [],
|
|
489
482
|
receivedAt: now,
|
|
@@ -493,7 +486,7 @@ export class AccountManagerImpl
|
|
|
493
486
|
|
|
494
487
|
private createBalance(
|
|
495
488
|
accountId: string,
|
|
496
|
-
|
|
489
|
+
venue: Venue,
|
|
497
490
|
input: RawBalanceUpdate,
|
|
498
491
|
previous?: BalanceSnapshot,
|
|
499
492
|
): BalanceSnapshot {
|
|
@@ -511,7 +504,7 @@ export class AccountManagerImpl
|
|
|
511
504
|
|
|
512
505
|
return {
|
|
513
506
|
accountId,
|
|
514
|
-
|
|
507
|
+
venue,
|
|
515
508
|
asset: input.asset,
|
|
516
509
|
free,
|
|
517
510
|
used,
|
|
@@ -520,18 +513,34 @@ export class AccountManagerImpl
|
|
|
520
513
|
receivedAt: input.receivedAt,
|
|
521
514
|
updatedAt: input.receivedAt,
|
|
522
515
|
seq: (previous?.seq ?? 0) + 1,
|
|
516
|
+
lending: input.lending
|
|
517
|
+
? {
|
|
518
|
+
supplied: new BigNumber(input.lending.supplied),
|
|
519
|
+
borrowed: new BigNumber(input.lending.borrowed),
|
|
520
|
+
interest: new BigNumber(input.lending.interest),
|
|
521
|
+
netAsset: new BigNumber(input.lending.netAsset),
|
|
522
|
+
supplyAPY:
|
|
523
|
+
input.lending.supplyAPY === undefined
|
|
524
|
+
? undefined
|
|
525
|
+
: new BigNumber(input.lending.supplyAPY),
|
|
526
|
+
borrowAPY:
|
|
527
|
+
input.lending.borrowAPY === undefined
|
|
528
|
+
? undefined
|
|
529
|
+
: new BigNumber(input.lending.borrowAPY),
|
|
530
|
+
}
|
|
531
|
+
: previous?.lending,
|
|
523
532
|
};
|
|
524
533
|
}
|
|
525
534
|
|
|
526
535
|
private createPosition(
|
|
527
536
|
accountId: string,
|
|
528
|
-
|
|
537
|
+
venue: Venue,
|
|
529
538
|
input: RawPositionUpdate,
|
|
530
539
|
previous?: PositionSnapshot,
|
|
531
540
|
): PositionSnapshot {
|
|
532
541
|
return {
|
|
533
542
|
accountId,
|
|
534
|
-
|
|
543
|
+
venue,
|
|
535
544
|
symbol: input.symbol,
|
|
536
545
|
side: input.side,
|
|
537
546
|
size: new BigNumber(input.size),
|
|
@@ -564,21 +573,21 @@ export class AccountManagerImpl
|
|
|
564
573
|
|
|
565
574
|
private createRisk(
|
|
566
575
|
accountId: string,
|
|
567
|
-
|
|
576
|
+
venue: Venue,
|
|
568
577
|
input: RawRiskUpdate,
|
|
569
578
|
previous?: RiskSnapshot,
|
|
570
579
|
): RiskSnapshot {
|
|
571
580
|
return {
|
|
572
581
|
accountId,
|
|
573
|
-
|
|
582
|
+
venue,
|
|
574
583
|
equity:
|
|
575
584
|
input.equity === undefined
|
|
576
585
|
? previous?.equity
|
|
577
586
|
: new BigNumber(input.equity),
|
|
578
|
-
|
|
579
|
-
input.
|
|
580
|
-
? previous?.
|
|
581
|
-
: new BigNumber(input.
|
|
587
|
+
riskRatio:
|
|
588
|
+
input.riskRatio === undefined
|
|
589
|
+
? previous?.riskRatio
|
|
590
|
+
: new BigNumber(input.riskRatio),
|
|
582
591
|
initialMargin:
|
|
583
592
|
input.initialMargin === undefined
|
|
584
593
|
? previous?.initialMargin
|
|
@@ -591,6 +600,34 @@ export class AccountManagerImpl
|
|
|
591
600
|
receivedAt: input.receivedAt,
|
|
592
601
|
updatedAt: input.receivedAt,
|
|
593
602
|
seq: (previous?.seq ?? 0) + 1,
|
|
603
|
+
lending: input.lending
|
|
604
|
+
? {
|
|
605
|
+
marginLevel:
|
|
606
|
+
input.lending.marginLevel === undefined
|
|
607
|
+
? undefined
|
|
608
|
+
: new BigNumber(input.lending.marginLevel),
|
|
609
|
+
healthFactor:
|
|
610
|
+
input.lending.healthFactor === undefined
|
|
611
|
+
? undefined
|
|
612
|
+
: new BigNumber(input.lending.healthFactor),
|
|
613
|
+
ltv:
|
|
614
|
+
input.lending.ltv === undefined
|
|
615
|
+
? undefined
|
|
616
|
+
: new BigNumber(input.lending.ltv),
|
|
617
|
+
liquidationThreshold:
|
|
618
|
+
input.lending.liquidationThreshold === undefined
|
|
619
|
+
? undefined
|
|
620
|
+
: new BigNumber(input.lending.liquidationThreshold),
|
|
621
|
+
totalCollateralUSD:
|
|
622
|
+
input.lending.totalCollateralUSD === undefined
|
|
623
|
+
? undefined
|
|
624
|
+
: new BigNumber(input.lending.totalCollateralUSD),
|
|
625
|
+
totalDebtUSD:
|
|
626
|
+
input.lending.totalDebtUSD === undefined
|
|
627
|
+
? undefined
|
|
628
|
+
: new BigNumber(input.lending.totalDebtUSD),
|
|
629
|
+
}
|
|
630
|
+
: previous?.lending,
|
|
594
631
|
};
|
|
595
632
|
}
|
|
596
633
|
|
|
@@ -598,7 +635,7 @@ export class AccountManagerImpl
|
|
|
598
635
|
const event: AccountStatusChangedEvent = {
|
|
599
636
|
type: "account.status_changed",
|
|
600
637
|
accountId: record.accountId,
|
|
601
|
-
|
|
638
|
+
venue: record.venue,
|
|
602
639
|
status: cloneAccountStatus(record.status),
|
|
603
640
|
ts: this.context.now(),
|
|
604
641
|
};
|