@imbingox/acex 0.3.0 → 0.4.0-beta.1
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 +7 -7
- package/docs/api.md +66 -66
- package/package.json +1 -1
- package/src/adapters/binance/adapter.ts +131 -12
- package/src/adapters/binance/market-catalog.ts +10 -10
- package/src/adapters/binance/stream-protocol.ts +202 -0
- package/src/client/runtime.ts +1 -1
- package/src/internal/decimal.ts +19 -0
- package/src/internal/managed-websocket.ts +8 -0
- package/src/internal/subscription-multiplexer.ts +747 -0
- package/src/managers/account-manager.ts +40 -32
- package/src/managers/market-manager.ts +100 -51
- package/src/managers/order-manager.ts +7 -8
- package/src/types/account.ts +27 -28
- package/src/types/market.ts +12 -12
- package/src/types/order.ts +6 -7
- package/src/adapters/binance/book-ticker.ts +0 -123
- package/src/adapters/binance/mark-price.ts +0 -126
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
PrivateSubscriptionState,
|
|
16
16
|
} from "../client/context.ts";
|
|
17
17
|
import { AsyncEventBus } from "../internal/async-event-bus.ts";
|
|
18
|
+
import { toCanonical } from "../internal/decimal.ts";
|
|
18
19
|
import { matchesAccountFilter } from "../internal/filters.ts";
|
|
19
20
|
import type {
|
|
20
21
|
AccountDataStatus,
|
|
@@ -56,6 +57,10 @@ function getBigNumber(
|
|
|
56
57
|
return value === undefined ? fallback : new BigNumber(value);
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
function isZeroDecimal(value: string): boolean {
|
|
61
|
+
return new BigNumber(value).isZero();
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
export class AccountManagerImpl
|
|
60
65
|
implements
|
|
61
66
|
AccountManager,
|
|
@@ -322,7 +327,7 @@ export class AccountManagerImpl
|
|
|
322
327
|
positions.get(key),
|
|
323
328
|
);
|
|
324
329
|
|
|
325
|
-
if (nextPosition.size
|
|
330
|
+
if (isZeroDecimal(nextPosition.size)) {
|
|
326
331
|
positions.delete(key);
|
|
327
332
|
} else {
|
|
328
333
|
positions.set(key, nextPosition);
|
|
@@ -461,7 +466,7 @@ export class AccountManagerImpl
|
|
|
461
466
|
);
|
|
462
467
|
const positions = bootstrap.positions
|
|
463
468
|
.map((position) => this.createPosition(accountId, venue, position))
|
|
464
|
-
.filter((position) => !position.size
|
|
469
|
+
.filter((position) => !isZeroDecimal(position.size));
|
|
465
470
|
const risk = bootstrap.risk
|
|
466
471
|
? this.createRisk(accountId, venue, bootstrap.risk)
|
|
467
472
|
: undefined;
|
|
@@ -499,9 +504,12 @@ export class AccountManagerImpl
|
|
|
499
504
|
input: RawBalanceUpdate,
|
|
500
505
|
previous?: BalanceSnapshot,
|
|
501
506
|
): BalanceSnapshot {
|
|
502
|
-
const previousFree = previous?.free ??
|
|
503
|
-
const previousUsed = previous?.used ??
|
|
504
|
-
const previousTotal =
|
|
507
|
+
const previousFree = new BigNumber(previous?.free ?? 0);
|
|
508
|
+
const previousUsed = new BigNumber(previous?.used ?? 0);
|
|
509
|
+
const previousTotal =
|
|
510
|
+
previous?.total === undefined
|
|
511
|
+
? previousFree.plus(previousUsed)
|
|
512
|
+
: new BigNumber(previous.total);
|
|
505
513
|
const free = getBigNumber(input.free, previousFree);
|
|
506
514
|
const total = getBigNumber(input.total, previousTotal);
|
|
507
515
|
const used =
|
|
@@ -515,27 +523,27 @@ export class AccountManagerImpl
|
|
|
515
523
|
accountId,
|
|
516
524
|
venue,
|
|
517
525
|
asset: input.asset,
|
|
518
|
-
free,
|
|
519
|
-
used,
|
|
520
|
-
total,
|
|
526
|
+
free: toCanonical(free),
|
|
527
|
+
used: toCanonical(used),
|
|
528
|
+
total: toCanonical(total),
|
|
521
529
|
exchangeTs: input.exchangeTs,
|
|
522
530
|
receivedAt: input.receivedAt,
|
|
523
531
|
updatedAt: input.receivedAt,
|
|
524
532
|
seq: (previous?.seq ?? 0) + 1,
|
|
525
533
|
lending: input.lending
|
|
526
534
|
? {
|
|
527
|
-
supplied:
|
|
528
|
-
borrowed:
|
|
529
|
-
interest:
|
|
530
|
-
netAsset:
|
|
535
|
+
supplied: toCanonical(input.lending.supplied),
|
|
536
|
+
borrowed: toCanonical(input.lending.borrowed),
|
|
537
|
+
interest: toCanonical(input.lending.interest),
|
|
538
|
+
netAsset: toCanonical(input.lending.netAsset),
|
|
531
539
|
supplyAPY:
|
|
532
540
|
input.lending.supplyAPY === undefined
|
|
533
541
|
? undefined
|
|
534
|
-
:
|
|
542
|
+
: toCanonical(input.lending.supplyAPY),
|
|
535
543
|
borrowAPY:
|
|
536
544
|
input.lending.borrowAPY === undefined
|
|
537
545
|
? undefined
|
|
538
|
-
:
|
|
546
|
+
: toCanonical(input.lending.borrowAPY),
|
|
539
547
|
}
|
|
540
548
|
: previous?.lending,
|
|
541
549
|
};
|
|
@@ -552,27 +560,27 @@ export class AccountManagerImpl
|
|
|
552
560
|
venue,
|
|
553
561
|
symbol: input.symbol,
|
|
554
562
|
side: input.side,
|
|
555
|
-
size:
|
|
563
|
+
size: toCanonical(input.size),
|
|
556
564
|
entryPrice:
|
|
557
565
|
input.entryPrice === undefined
|
|
558
566
|
? previous?.entryPrice
|
|
559
|
-
:
|
|
567
|
+
: toCanonical(input.entryPrice),
|
|
560
568
|
markPrice:
|
|
561
569
|
input.markPrice === undefined
|
|
562
570
|
? previous?.markPrice
|
|
563
|
-
:
|
|
571
|
+
: toCanonical(input.markPrice),
|
|
564
572
|
unrealizedPnl:
|
|
565
573
|
input.unrealizedPnl === undefined
|
|
566
574
|
? previous?.unrealizedPnl
|
|
567
|
-
:
|
|
575
|
+
: toCanonical(input.unrealizedPnl),
|
|
568
576
|
leverage:
|
|
569
577
|
input.leverage === undefined
|
|
570
578
|
? previous?.leverage
|
|
571
|
-
:
|
|
579
|
+
: toCanonical(input.leverage),
|
|
572
580
|
liquidationPrice:
|
|
573
581
|
input.liquidationPrice === undefined
|
|
574
582
|
? previous?.liquidationPrice
|
|
575
|
-
:
|
|
583
|
+
: toCanonical(input.liquidationPrice),
|
|
576
584
|
exchangeTs: input.exchangeTs,
|
|
577
585
|
receivedAt: input.receivedAt,
|
|
578
586
|
updatedAt: input.receivedAt,
|
|
@@ -592,27 +600,27 @@ export class AccountManagerImpl
|
|
|
592
600
|
netEquity:
|
|
593
601
|
input.netEquity === undefined
|
|
594
602
|
? previous?.netEquity
|
|
595
|
-
:
|
|
603
|
+
: toCanonical(input.netEquity),
|
|
596
604
|
riskEquity:
|
|
597
605
|
input.riskEquity === undefined
|
|
598
606
|
? previous?.riskEquity
|
|
599
|
-
:
|
|
607
|
+
: toCanonical(input.riskEquity),
|
|
600
608
|
riskRatio:
|
|
601
609
|
input.riskRatio === undefined
|
|
602
610
|
? previous?.riskRatio
|
|
603
|
-
:
|
|
611
|
+
: toCanonical(input.riskRatio),
|
|
604
612
|
riskLeverage:
|
|
605
613
|
input.riskLeverage === undefined
|
|
606
614
|
? previous?.riskLeverage
|
|
607
|
-
:
|
|
615
|
+
: toCanonical(input.riskLeverage),
|
|
608
616
|
initialMargin:
|
|
609
617
|
input.initialMargin === undefined
|
|
610
618
|
? previous?.initialMargin
|
|
611
|
-
:
|
|
619
|
+
: toCanonical(input.initialMargin),
|
|
612
620
|
maintenanceMargin:
|
|
613
621
|
input.maintenanceMargin === undefined
|
|
614
622
|
? previous?.maintenanceMargin
|
|
615
|
-
:
|
|
623
|
+
: toCanonical(input.maintenanceMargin),
|
|
616
624
|
exchangeTs: input.exchangeTs,
|
|
617
625
|
receivedAt: input.receivedAt,
|
|
618
626
|
updatedAt: input.receivedAt,
|
|
@@ -622,27 +630,27 @@ export class AccountManagerImpl
|
|
|
622
630
|
marginLevel:
|
|
623
631
|
input.lending.marginLevel === undefined
|
|
624
632
|
? undefined
|
|
625
|
-
:
|
|
633
|
+
: toCanonical(input.lending.marginLevel),
|
|
626
634
|
healthFactor:
|
|
627
635
|
input.lending.healthFactor === undefined
|
|
628
636
|
? undefined
|
|
629
|
-
:
|
|
637
|
+
: toCanonical(input.lending.healthFactor),
|
|
630
638
|
ltv:
|
|
631
639
|
input.lending.ltv === undefined
|
|
632
640
|
? undefined
|
|
633
|
-
:
|
|
641
|
+
: toCanonical(input.lending.ltv),
|
|
634
642
|
liquidationThreshold:
|
|
635
643
|
input.lending.liquidationThreshold === undefined
|
|
636
644
|
? undefined
|
|
637
|
-
:
|
|
645
|
+
: toCanonical(input.lending.liquidationThreshold),
|
|
638
646
|
totalCollateralUSD:
|
|
639
647
|
input.lending.totalCollateralUSD === undefined
|
|
640
648
|
? undefined
|
|
641
|
-
:
|
|
649
|
+
: toCanonical(input.lending.totalCollateralUSD),
|
|
642
650
|
totalDebtUSD:
|
|
643
651
|
input.lending.totalDebtUSD === undefined
|
|
644
652
|
? undefined
|
|
645
|
-
:
|
|
653
|
+
: toCanonical(input.lending.totalDebtUSD),
|
|
646
654
|
}
|
|
647
655
|
: previous?.lending,
|
|
648
656
|
};
|
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
} from "../client/context.ts";
|
|
17
17
|
import { AcexError } from "../errors.ts";
|
|
18
18
|
import { AsyncEventBus } from "../internal/async-event-bus.ts";
|
|
19
|
+
import { toCanonical } from "../internal/decimal.ts";
|
|
19
20
|
import { matchesMarketFilter } from "../internal/filters.ts";
|
|
20
21
|
import type {
|
|
21
22
|
FundingRateSnapshot,
|
|
@@ -100,35 +101,33 @@ function floorToStep(value: BigNumber, step: BigNumber): BigNumber {
|
|
|
100
101
|
return value.dividedToIntegerBy(step).multipliedBy(step);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
function normalizeDecimalInput(value: BigNumber): string {
|
|
104
|
-
return value.isFinite() ? value.toFixed() : value.toString();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
104
|
export class MarketManagerImpl
|
|
108
105
|
implements MarketManager, ManagerLifecycle, HealthReporter<MarketDataStatus>
|
|
109
106
|
{
|
|
110
107
|
readonly events: MarketEventStreams;
|
|
111
108
|
|
|
112
109
|
private readonly context: ClientContext;
|
|
113
|
-
private readonly
|
|
110
|
+
private readonly adapters: Map<Venue, MarketAdapter>;
|
|
114
111
|
private readonly marketBus = new AsyncEventBus<MarketEvent>();
|
|
115
112
|
private readonly marketStatusBus =
|
|
116
113
|
new AsyncEventBus<MarketStatusChangedEvent>();
|
|
117
114
|
private readonly definitions = new Map<string, MarketDefinition>();
|
|
118
115
|
private readonly records = new Map<string, MarketRecord>();
|
|
119
|
-
private
|
|
116
|
+
private readonly loadedCatalogVenues = new Set<Venue>();
|
|
117
|
+
private readonly catalogPromises = new Map<Venue, Promise<void>>();
|
|
120
118
|
private readonly initialL1TimeoutMs: number;
|
|
121
119
|
private readonly l1StaleAfterMs: number;
|
|
122
120
|
private readonly l1ReconnectDelayMs: number;
|
|
123
121
|
private readonly l1ReconnectMaxDelayMs: number;
|
|
122
|
+
private readonly streamNow = (): number => this.context.now();
|
|
124
123
|
|
|
125
124
|
constructor(
|
|
126
125
|
context: ClientContext,
|
|
127
|
-
|
|
126
|
+
adapters: Map<Venue, MarketAdapter>,
|
|
128
127
|
options: MarketManagerOptions = {},
|
|
129
128
|
) {
|
|
130
129
|
this.context = context;
|
|
131
|
-
this.
|
|
130
|
+
this.adapters = new Map(adapters);
|
|
132
131
|
this.initialL1TimeoutMs =
|
|
133
132
|
options.initialL1TimeoutMs ?? DEFAULT_INITIAL_L1_TIMEOUT_MS;
|
|
134
133
|
this.l1StaleAfterMs = options.l1StaleAfterMs ?? DEFAULT_L1_STALE_AFTER_MS;
|
|
@@ -162,7 +161,9 @@ export class MarketManagerImpl
|
|
|
162
161
|
// --- MarketManager public API ---
|
|
163
162
|
|
|
164
163
|
async loadMarkets(): Promise<void> {
|
|
165
|
-
await
|
|
164
|
+
await Promise.all(
|
|
165
|
+
[...this.adapters.keys()].map((venue) => this.loadMarketCatalog(venue)),
|
|
166
|
+
);
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
async subscribeL1Book(input: SubscribeL1BookInput): Promise<void> {
|
|
@@ -258,20 +259,36 @@ export class MarketManagerImpl
|
|
|
258
259
|
const market = this.resolveLoadedMarket(input);
|
|
259
260
|
const rawPrice = new BigNumber(input.price);
|
|
260
261
|
const rawAmount = new BigNumber(input.amount);
|
|
261
|
-
const
|
|
262
|
-
const
|
|
262
|
+
const priceStep = new BigNumber(market.priceStep);
|
|
263
|
+
const amountStep = new BigNumber(market.amountStep);
|
|
264
|
+
const minAmount =
|
|
265
|
+
market.minAmount === undefined
|
|
266
|
+
? undefined
|
|
267
|
+
: new BigNumber(market.minAmount);
|
|
268
|
+
const minNotional =
|
|
269
|
+
market.minNotional === undefined
|
|
270
|
+
? undefined
|
|
271
|
+
: new BigNumber(market.minNotional);
|
|
272
|
+
const price = floorToStep(rawPrice, priceStep);
|
|
273
|
+
const amount = floorToStep(rawAmount, amountStep);
|
|
274
|
+
|
|
275
|
+
// normalizeOrderInput rejects non-finite input gracefully (see the
|
|
276
|
+
// isFinite checks below), so its echoed numeric fields fall back to the
|
|
277
|
+
// raw string instead of throwing the way toCanonical now does.
|
|
278
|
+
const echoDecimal = (value: BigNumber): string =>
|
|
279
|
+
value.isFinite() ? toCanonical(value) : value.toString();
|
|
263
280
|
|
|
264
281
|
const normalized: NormalizedOrderInput = {
|
|
265
|
-
price:
|
|
266
|
-
amount:
|
|
267
|
-
rawPrice:
|
|
268
|
-
rawAmount:
|
|
282
|
+
price: echoDecimal(price),
|
|
283
|
+
amount: echoDecimal(amount),
|
|
284
|
+
rawPrice: echoDecimal(rawPrice),
|
|
285
|
+
rawAmount: echoDecimal(rawAmount),
|
|
269
286
|
adjusted: !price.isEqualTo(rawPrice) || !amount.isEqualTo(rawAmount),
|
|
270
287
|
accepted: true,
|
|
271
|
-
priceStep: market.priceStep
|
|
272
|
-
amountStep: market.amountStep
|
|
273
|
-
minAmount: market.minAmount
|
|
274
|
-
minNotional: market.minNotional
|
|
288
|
+
priceStep: market.priceStep,
|
|
289
|
+
amountStep: market.amountStep,
|
|
290
|
+
minAmount: market.minAmount,
|
|
291
|
+
minNotional: market.minNotional,
|
|
275
292
|
};
|
|
276
293
|
|
|
277
294
|
if (!price.isFinite() || price.isLessThanOrEqualTo(0)) {
|
|
@@ -290,7 +307,7 @@ export class MarketManagerImpl
|
|
|
290
307
|
};
|
|
291
308
|
}
|
|
292
309
|
|
|
293
|
-
if (
|
|
310
|
+
if (minAmount && amount.isLessThan(minAmount)) {
|
|
294
311
|
return {
|
|
295
312
|
...normalized,
|
|
296
313
|
accepted: false,
|
|
@@ -298,9 +315,9 @@ export class MarketManagerImpl
|
|
|
298
315
|
};
|
|
299
316
|
}
|
|
300
317
|
|
|
301
|
-
if (
|
|
318
|
+
if (minNotional) {
|
|
302
319
|
const notional = amount.multipliedBy(price);
|
|
303
|
-
if (notional.isLessThan(
|
|
320
|
+
if (notional.isLessThan(minNotional)) {
|
|
304
321
|
return {
|
|
305
322
|
...normalized,
|
|
306
323
|
accepted: false,
|
|
@@ -414,43 +431,55 @@ export class MarketManagerImpl
|
|
|
414
431
|
|
|
415
432
|
// --- Internal helpers ---
|
|
416
433
|
|
|
417
|
-
private async loadMarketCatalog(): Promise<void> {
|
|
418
|
-
|
|
434
|
+
private async loadMarketCatalog(venue: Venue): Promise<void> {
|
|
435
|
+
this.assertSupportedVenue(venue);
|
|
436
|
+
|
|
437
|
+
if (this.loadedCatalogVenues.has(venue)) {
|
|
419
438
|
return;
|
|
420
439
|
}
|
|
421
440
|
|
|
422
|
-
|
|
423
|
-
|
|
441
|
+
let catalogPromise = this.catalogPromises.get(venue);
|
|
442
|
+
if (!catalogPromise) {
|
|
443
|
+
catalogPromise = this.fetchAndStoreMarketCatalog(venue);
|
|
444
|
+
this.catalogPromises.set(venue, catalogPromise);
|
|
424
445
|
}
|
|
425
446
|
|
|
426
447
|
try {
|
|
427
|
-
await
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
448
|
+
await catalogPromise;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
this.catalogPromises.delete(venue);
|
|
451
|
+
throw error;
|
|
432
452
|
}
|
|
433
453
|
}
|
|
434
454
|
|
|
435
|
-
private async fetchAndStoreMarketCatalog(): Promise<void> {
|
|
455
|
+
private async fetchAndStoreMarketCatalog(venue: Venue): Promise<void> {
|
|
456
|
+
const adapter = this.getMarketAdapter(venue);
|
|
457
|
+
|
|
436
458
|
try {
|
|
437
|
-
const markets = await
|
|
438
|
-
|
|
459
|
+
const markets = await adapter.loadMarkets();
|
|
460
|
+
|
|
461
|
+
for (const [key, market] of this.definitions) {
|
|
462
|
+
if (market.venue === venue) {
|
|
463
|
+
this.definitions.delete(key);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
439
466
|
|
|
440
467
|
for (const market of markets) {
|
|
441
468
|
this.definitions.set(marketKey(market), market);
|
|
442
469
|
}
|
|
470
|
+
|
|
471
|
+
this.loadedCatalogVenues.add(venue);
|
|
443
472
|
} catch (error) {
|
|
444
473
|
const wrapped = new AcexError(
|
|
445
474
|
"MARKET_CATALOG_LOAD_FAILED",
|
|
446
|
-
|
|
475
|
+
`Failed to load market catalog from ${venue}`,
|
|
447
476
|
);
|
|
448
477
|
this.context.publishRuntimeError(
|
|
449
478
|
"adapter",
|
|
450
479
|
error instanceof Error
|
|
451
480
|
? error
|
|
452
481
|
: new Error("Unknown catalog load failure"),
|
|
453
|
-
{ venue
|
|
482
|
+
{ venue },
|
|
454
483
|
);
|
|
455
484
|
throw wrapped;
|
|
456
485
|
}
|
|
@@ -461,7 +490,7 @@ export class MarketManagerImpl
|
|
|
461
490
|
symbol: string;
|
|
462
491
|
}): Promise<MarketDefinition> {
|
|
463
492
|
this.assertSupportedVenue(input.venue);
|
|
464
|
-
await this.loadMarketCatalog();
|
|
493
|
+
await this.loadMarketCatalog(input.venue);
|
|
465
494
|
|
|
466
495
|
const market = this.definitions.get(marketKey(input));
|
|
467
496
|
if (!market) {
|
|
@@ -500,7 +529,7 @@ export class MarketManagerImpl
|
|
|
500
529
|
}
|
|
501
530
|
|
|
502
531
|
private assertSupportedVenue(venue: Venue): void {
|
|
503
|
-
if (
|
|
532
|
+
if (this.adapters.has(venue)) {
|
|
504
533
|
return;
|
|
505
534
|
}
|
|
506
535
|
|
|
@@ -512,6 +541,20 @@ export class MarketManagerImpl
|
|
|
512
541
|
);
|
|
513
542
|
}
|
|
514
543
|
|
|
544
|
+
private getMarketAdapter(venue: Venue): MarketAdapter {
|
|
545
|
+
const adapter = this.adapters.get(venue);
|
|
546
|
+
if (!adapter) {
|
|
547
|
+
throw this.createError(
|
|
548
|
+
"VENUE_NOT_SUPPORTED",
|
|
549
|
+
`Venue is not supported yet: ${venue}`,
|
|
550
|
+
{ venue },
|
|
551
|
+
"client",
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return adapter;
|
|
556
|
+
}
|
|
557
|
+
|
|
515
558
|
private assertFundingRateSupported(market: MarketDefinition): void {
|
|
516
559
|
if (market.contract && market.type === "swap") {
|
|
517
560
|
return;
|
|
@@ -664,10 +707,14 @@ export class MarketManagerImpl
|
|
|
664
707
|
staleAfterMs: this.l1StaleAfterMs,
|
|
665
708
|
reconnectDelayMs: this.l1ReconnectDelayMs,
|
|
666
709
|
reconnectMaxDelayMs: this.l1ReconnectMaxDelayMs,
|
|
667
|
-
now:
|
|
710
|
+
now: this.streamNow,
|
|
668
711
|
};
|
|
669
712
|
|
|
670
|
-
return this.
|
|
713
|
+
return this.getMarketAdapter(market.venue).createL1BookStream(
|
|
714
|
+
market,
|
|
715
|
+
callbacks,
|
|
716
|
+
options,
|
|
717
|
+
);
|
|
671
718
|
}
|
|
672
719
|
|
|
673
720
|
private createFundingRateStream(
|
|
@@ -721,10 +768,14 @@ export class MarketManagerImpl
|
|
|
721
768
|
staleAfterMs: this.l1StaleAfterMs,
|
|
722
769
|
reconnectDelayMs: this.l1ReconnectDelayMs,
|
|
723
770
|
reconnectMaxDelayMs: this.l1ReconnectMaxDelayMs,
|
|
724
|
-
now:
|
|
771
|
+
now: this.streamNow,
|
|
725
772
|
};
|
|
726
773
|
|
|
727
|
-
return this.
|
|
774
|
+
return this.getMarketAdapter(market.venue).createFundingRateStream(
|
|
775
|
+
market,
|
|
776
|
+
callbacks,
|
|
777
|
+
options,
|
|
778
|
+
);
|
|
728
779
|
}
|
|
729
780
|
|
|
730
781
|
private createL1Book(
|
|
@@ -736,10 +787,10 @@ export class MarketManagerImpl
|
|
|
736
787
|
return {
|
|
737
788
|
venue,
|
|
738
789
|
symbol,
|
|
739
|
-
bidPrice:
|
|
740
|
-
bidSize:
|
|
741
|
-
askPrice:
|
|
742
|
-
askSize:
|
|
790
|
+
bidPrice: toCanonical(input.bidPrice),
|
|
791
|
+
bidSize: toCanonical(input.bidSize),
|
|
792
|
+
askPrice: toCanonical(input.askPrice),
|
|
793
|
+
askSize: toCanonical(input.askSize),
|
|
743
794
|
exchangeTs: input.exchangeTs,
|
|
744
795
|
receivedAt: input.receivedAt,
|
|
745
796
|
updatedAt: input.receivedAt,
|
|
@@ -763,12 +814,10 @@ export class MarketManagerImpl
|
|
|
763
814
|
return {
|
|
764
815
|
venue,
|
|
765
816
|
symbol,
|
|
766
|
-
fundingRate:
|
|
817
|
+
fundingRate: toCanonical(input.fundingRate),
|
|
767
818
|
nextFundingTime: input.nextFundingTime,
|
|
768
|
-
markPrice: input.markPrice ?
|
|
769
|
-
indexPrice: input.indexPrice
|
|
770
|
-
? new BigNumber(input.indexPrice)
|
|
771
|
-
: undefined,
|
|
819
|
+
markPrice: input.markPrice ? toCanonical(input.markPrice) : undefined,
|
|
820
|
+
indexPrice: input.indexPrice ? toCanonical(input.indexPrice) : undefined,
|
|
772
821
|
exchangeTs: input.exchangeTs,
|
|
773
822
|
receivedAt: input.receivedAt,
|
|
774
823
|
updatedAt: input.receivedAt,
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
} from "../client/context.ts";
|
|
11
11
|
import { AcexError } from "../errors.ts";
|
|
12
12
|
import { AsyncEventBus } from "../internal/async-event-bus.ts";
|
|
13
|
+
import { toCanonical } from "../internal/decimal.ts";
|
|
13
14
|
import { matchesOrderFilter } from "../internal/filters.ts";
|
|
14
15
|
import type {
|
|
15
16
|
CancelAllOrdersInput,
|
|
@@ -546,22 +547,20 @@ export class OrderManagerImpl
|
|
|
546
547
|
type: input.type,
|
|
547
548
|
status: input.status,
|
|
548
549
|
price:
|
|
549
|
-
input.price === undefined
|
|
550
|
-
? previous?.price
|
|
551
|
-
: new BigNumber(input.price),
|
|
550
|
+
input.price === undefined ? previous?.price : toCanonical(input.price),
|
|
552
551
|
triggerPrice:
|
|
553
552
|
input.triggerPrice === undefined
|
|
554
553
|
? previous?.triggerPrice
|
|
555
|
-
:
|
|
556
|
-
amount,
|
|
557
|
-
filled,
|
|
558
|
-
remaining,
|
|
554
|
+
: toCanonical(input.triggerPrice),
|
|
555
|
+
amount: toCanonical(amount),
|
|
556
|
+
filled: toCanonical(filled),
|
|
557
|
+
remaining: toCanonical(remaining),
|
|
559
558
|
reduceOnly: input.reduceOnly ?? previous?.reduceOnly,
|
|
560
559
|
positionSide: input.positionSide ?? previous?.positionSide,
|
|
561
560
|
avgFillPrice:
|
|
562
561
|
input.avgFillPrice === undefined
|
|
563
562
|
? previous?.avgFillPrice
|
|
564
|
-
:
|
|
563
|
+
: toCanonical(input.avgFillPrice),
|
|
565
564
|
exchangeTs: input.exchangeTs,
|
|
566
565
|
receivedAt: input.receivedAt,
|
|
567
566
|
updatedAt: input.receivedAt,
|
package/src/types/account.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type BigNumber from "bignumber.js";
|
|
2
1
|
import type {
|
|
3
2
|
PrivateRuntimeReason,
|
|
4
3
|
PrivateRuntimeStatus,
|
|
@@ -52,9 +51,9 @@ export interface BalanceSnapshot {
|
|
|
52
51
|
accountId: string;
|
|
53
52
|
venue: Venue;
|
|
54
53
|
asset: string;
|
|
55
|
-
free:
|
|
56
|
-
used:
|
|
57
|
-
total:
|
|
54
|
+
free: string;
|
|
55
|
+
used: string;
|
|
56
|
+
total: string;
|
|
58
57
|
exchangeTs?: number;
|
|
59
58
|
receivedAt: number;
|
|
60
59
|
updatedAt: number;
|
|
@@ -63,12 +62,12 @@ export interface BalanceSnapshot {
|
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
export interface LendingBalanceFacet {
|
|
66
|
-
supplied:
|
|
67
|
-
borrowed:
|
|
68
|
-
interest:
|
|
69
|
-
netAsset:
|
|
70
|
-
supplyAPY?:
|
|
71
|
-
borrowAPY?:
|
|
65
|
+
supplied: string;
|
|
66
|
+
borrowed: string;
|
|
67
|
+
interest: string;
|
|
68
|
+
netAsset: string;
|
|
69
|
+
supplyAPY?: string;
|
|
70
|
+
borrowAPY?: string;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
export interface PositionSnapshot {
|
|
@@ -76,12 +75,12 @@ export interface PositionSnapshot {
|
|
|
76
75
|
venue: Venue;
|
|
77
76
|
symbol: string;
|
|
78
77
|
side: PositionSide;
|
|
79
|
-
size:
|
|
80
|
-
entryPrice?:
|
|
81
|
-
markPrice?:
|
|
82
|
-
unrealizedPnl?:
|
|
83
|
-
leverage?:
|
|
84
|
-
liquidationPrice?:
|
|
78
|
+
size: string;
|
|
79
|
+
entryPrice?: string;
|
|
80
|
+
markPrice?: string;
|
|
81
|
+
unrealizedPnl?: string;
|
|
82
|
+
leverage?: string;
|
|
83
|
+
liquidationPrice?: string;
|
|
85
84
|
exchangeTs?: number;
|
|
86
85
|
receivedAt: number;
|
|
87
86
|
updatedAt: number;
|
|
@@ -91,12 +90,12 @@ export interface PositionSnapshot {
|
|
|
91
90
|
export interface RiskSnapshot {
|
|
92
91
|
accountId: string;
|
|
93
92
|
venue: Venue;
|
|
94
|
-
netEquity?:
|
|
95
|
-
riskEquity?:
|
|
96
|
-
riskRatio?:
|
|
97
|
-
riskLeverage?:
|
|
98
|
-
initialMargin?:
|
|
99
|
-
maintenanceMargin?:
|
|
93
|
+
netEquity?: string;
|
|
94
|
+
riskEquity?: string;
|
|
95
|
+
riskRatio?: string;
|
|
96
|
+
riskLeverage?: string;
|
|
97
|
+
initialMargin?: string;
|
|
98
|
+
maintenanceMargin?: string;
|
|
100
99
|
exchangeTs?: number;
|
|
101
100
|
receivedAt: number;
|
|
102
101
|
updatedAt: number;
|
|
@@ -105,12 +104,12 @@ export interface RiskSnapshot {
|
|
|
105
104
|
}
|
|
106
105
|
|
|
107
106
|
export interface LendingRiskFacet {
|
|
108
|
-
marginLevel?:
|
|
109
|
-
healthFactor?:
|
|
110
|
-
ltv?:
|
|
111
|
-
liquidationThreshold?:
|
|
112
|
-
totalCollateralUSD?:
|
|
113
|
-
totalDebtUSD?:
|
|
107
|
+
marginLevel?: string;
|
|
108
|
+
healthFactor?: string;
|
|
109
|
+
ltv?: string;
|
|
110
|
+
liquidationThreshold?: string;
|
|
111
|
+
totalCollateralUSD?: string;
|
|
112
|
+
totalDebtUSD?: string;
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
export interface AccountSnapshot {
|
package/src/types/market.ts
CHANGED
|
@@ -15,13 +15,13 @@ export interface MarketDefinition {
|
|
|
15
15
|
contract: boolean;
|
|
16
16
|
linear?: boolean;
|
|
17
17
|
inverse?: boolean;
|
|
18
|
-
contractSize?:
|
|
18
|
+
contractSize?: string;
|
|
19
19
|
pricePrecision: number;
|
|
20
20
|
amountPrecision: number;
|
|
21
|
-
priceStep:
|
|
22
|
-
amountStep:
|
|
23
|
-
minAmount?:
|
|
24
|
-
minNotional?:
|
|
21
|
+
priceStep: string;
|
|
22
|
+
amountStep: string;
|
|
23
|
+
minAmount?: string;
|
|
24
|
+
minNotional?: string;
|
|
25
25
|
expiry?: number;
|
|
26
26
|
raw: Record<string, unknown>;
|
|
27
27
|
}
|
|
@@ -92,10 +92,10 @@ export interface MarketEventFilter {
|
|
|
92
92
|
export interface L1Book {
|
|
93
93
|
venue: Venue;
|
|
94
94
|
symbol: string;
|
|
95
|
-
bidPrice:
|
|
96
|
-
bidSize:
|
|
97
|
-
askPrice:
|
|
98
|
-
askSize:
|
|
95
|
+
bidPrice: string;
|
|
96
|
+
bidSize: string;
|
|
97
|
+
askPrice: string;
|
|
98
|
+
askSize: string;
|
|
99
99
|
exchangeTs?: number;
|
|
100
100
|
receivedAt: number;
|
|
101
101
|
updatedAt: number;
|
|
@@ -106,10 +106,10 @@ export interface L1Book {
|
|
|
106
106
|
export interface FundingRateSnapshot {
|
|
107
107
|
venue: Venue;
|
|
108
108
|
symbol: string;
|
|
109
|
-
fundingRate:
|
|
109
|
+
fundingRate: string;
|
|
110
110
|
nextFundingTime?: number;
|
|
111
|
-
markPrice?:
|
|
112
|
-
indexPrice?:
|
|
111
|
+
markPrice?: string;
|
|
112
|
+
indexPrice?: string;
|
|
113
113
|
exchangeTs?: number;
|
|
114
114
|
receivedAt: number;
|
|
115
115
|
updatedAt: number;
|