@imbingox/acex 0.3.1-beta.0 → 0.4.0-beta.10
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 +11 -10
- package/docs/api.md +502 -1030
- package/package.json +1 -1
- package/src/adapters/binance/adapter.ts +19 -1
- package/src/adapters/binance/market-catalog.ts +93 -22
- package/src/adapters/binance/private-adapter.ts +302 -59
- package/src/adapters/binance/rate-limit.ts +47 -0
- package/src/adapters/binance/server-time.ts +106 -0
- package/src/adapters/juplend/private-adapter.ts +97 -68
- package/src/adapters/types.ts +25 -1
- package/src/client/context.ts +26 -9
- package/src/client/private-subscription-coordinator.ts +898 -63
- package/src/client/runtime.ts +49 -11
- package/src/client/venue-capabilities.ts +1 -0
- package/src/errors.ts +156 -2
- package/src/index.ts +8 -1
- package/src/internal/decimal.ts +19 -0
- package/src/internal/http-client.ts +608 -0
- package/src/internal/rate-limiter.ts +181 -0
- package/src/internal/watermark.ts +83 -0
- package/src/managers/account-manager.ts +267 -55
- package/src/managers/market-manager.ts +261 -60
- package/src/managers/order-manager.ts +798 -84
- package/src/types/account.ts +27 -28
- package/src/types/client.ts +1 -0
- package/src/types/market.ts +37 -12
- package/src/types/order.ts +7 -7
- package/src/types/shared.ts +66 -0
|
@@ -15,7 +15,12 @@ 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";
|
|
20
|
+
import {
|
|
21
|
+
canDeleteMissingFromSnapshot,
|
|
22
|
+
shouldApplyWatermarkedUpdate,
|
|
23
|
+
} from "../internal/watermark.ts";
|
|
19
24
|
import type {
|
|
20
25
|
AccountDataStatus,
|
|
21
26
|
AccountEvent,
|
|
@@ -56,6 +61,50 @@ function getBigNumber(
|
|
|
56
61
|
return value === undefined ? fallback : new BigNumber(value);
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
function isZeroDecimal(value: string): boolean {
|
|
65
|
+
return new BigNumber(value).isZero();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isZeroBalance(balance: BalanceSnapshot): boolean {
|
|
69
|
+
return (
|
|
70
|
+
isZeroDecimal(balance.free) &&
|
|
71
|
+
isZeroDecimal(balance.used) &&
|
|
72
|
+
isZeroDecimal(balance.total)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function successfulStatus(
|
|
77
|
+
status: AccountDataStatus,
|
|
78
|
+
options: {
|
|
79
|
+
ready?: boolean;
|
|
80
|
+
lastReceivedAt?: number;
|
|
81
|
+
lastReadyAt?: number;
|
|
82
|
+
preserveStatus?: boolean;
|
|
83
|
+
},
|
|
84
|
+
): AccountDataStatus {
|
|
85
|
+
const preservesStreamState =
|
|
86
|
+
options.preserveStatus &&
|
|
87
|
+
(status.runtimeStatus === "reconnecting" ||
|
|
88
|
+
status.reason === "ws_disconnected" ||
|
|
89
|
+
status.reason === "heartbeat_timeout");
|
|
90
|
+
const ready = options.ready ?? true;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
...status,
|
|
94
|
+
activity: "active",
|
|
95
|
+
ready,
|
|
96
|
+
runtimeStatus: preservesStreamState ? status.runtimeStatus : "healthy",
|
|
97
|
+
reason: preservesStreamState ? status.reason : undefined,
|
|
98
|
+
lastReceivedAt: options.lastReceivedAt ?? status.lastReceivedAt,
|
|
99
|
+
lastReadyAt: ready
|
|
100
|
+
? (options.lastReadyAt ??
|
|
101
|
+
(options.preserveStatus ? status.lastReadyAt : undefined) ??
|
|
102
|
+
Date.now())
|
|
103
|
+
: status.lastReadyAt,
|
|
104
|
+
inactiveSince: undefined,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
59
108
|
export class AccountManagerImpl
|
|
60
109
|
implements
|
|
61
110
|
AccountManager,
|
|
@@ -277,7 +326,7 @@ export class AccountManagerImpl
|
|
|
277
326
|
accountId: string,
|
|
278
327
|
venue: Venue,
|
|
279
328
|
update: RawAccountUpdate,
|
|
280
|
-
options: { preserveStatus?: boolean } = {},
|
|
329
|
+
options: { preserveStatus?: boolean; requestStartedAt?: number } = {},
|
|
281
330
|
): void {
|
|
282
331
|
const record = this.getOrCreateRecord(accountId, venue);
|
|
283
332
|
if (!record.subscribed) {
|
|
@@ -295,7 +344,17 @@ export class AccountManagerImpl
|
|
|
295
344
|
);
|
|
296
345
|
let risk = previous.risk;
|
|
297
346
|
|
|
347
|
+
let latestAppliedAt = 0;
|
|
298
348
|
for (const balance of update.balances ?? []) {
|
|
349
|
+
if (
|
|
350
|
+
!shouldApplyWatermarkedUpdate(balances[balance.asset], balance, {
|
|
351
|
+
requestStartedAt: options.requestStartedAt,
|
|
352
|
+
source: options.requestStartedAt === undefined ? "stream" : "rest",
|
|
353
|
+
})
|
|
354
|
+
) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
|
|
299
358
|
const nextBalance = this.createBalance(
|
|
300
359
|
accountId,
|
|
301
360
|
venue,
|
|
@@ -303,6 +362,7 @@ export class AccountManagerImpl
|
|
|
303
362
|
balances[balance.asset],
|
|
304
363
|
);
|
|
305
364
|
balances[balance.asset] = nextBalance;
|
|
365
|
+
latestAppliedAt = Math.max(latestAppliedAt, nextBalance.receivedAt);
|
|
306
366
|
this.accountBus.publish({
|
|
307
367
|
type: "balance.updated",
|
|
308
368
|
accountId,
|
|
@@ -315,6 +375,15 @@ export class AccountManagerImpl
|
|
|
315
375
|
|
|
316
376
|
for (const position of update.positions ?? []) {
|
|
317
377
|
const key = positionKey(position.symbol, position.side);
|
|
378
|
+
if (
|
|
379
|
+
!shouldApplyWatermarkedUpdate(positions.get(key), position, {
|
|
380
|
+
requestStartedAt: options.requestStartedAt,
|
|
381
|
+
source: options.requestStartedAt === undefined ? "stream" : "rest",
|
|
382
|
+
})
|
|
383
|
+
) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
|
|
318
387
|
const nextPosition = this.createPosition(
|
|
319
388
|
accountId,
|
|
320
389
|
venue,
|
|
@@ -322,12 +391,13 @@ export class AccountManagerImpl
|
|
|
322
391
|
positions.get(key),
|
|
323
392
|
);
|
|
324
393
|
|
|
325
|
-
if (nextPosition.size
|
|
394
|
+
if (isZeroDecimal(nextPosition.size)) {
|
|
326
395
|
positions.delete(key);
|
|
327
396
|
} else {
|
|
328
397
|
positions.set(key, nextPosition);
|
|
329
398
|
}
|
|
330
399
|
|
|
400
|
+
latestAppliedAt = Math.max(latestAppliedAt, nextPosition.receivedAt);
|
|
331
401
|
this.accountBus.publish({
|
|
332
402
|
type: "position.updated",
|
|
333
403
|
accountId,
|
|
@@ -338,8 +408,15 @@ export class AccountManagerImpl
|
|
|
338
408
|
});
|
|
339
409
|
}
|
|
340
410
|
|
|
341
|
-
if (
|
|
411
|
+
if (
|
|
412
|
+
update.risk &&
|
|
413
|
+
shouldApplyWatermarkedUpdate(previous.risk, update.risk, {
|
|
414
|
+
requestStartedAt: options.requestStartedAt,
|
|
415
|
+
source: options.requestStartedAt === undefined ? "stream" : "rest",
|
|
416
|
+
})
|
|
417
|
+
) {
|
|
342
418
|
risk = this.createRisk(accountId, venue, update.risk, previous.risk);
|
|
419
|
+
latestAppliedAt = Math.max(latestAppliedAt, risk.receivedAt);
|
|
343
420
|
this.accountBus.publish({
|
|
344
421
|
type: "risk.updated",
|
|
345
422
|
accountId,
|
|
@@ -349,34 +426,166 @@ export class AccountManagerImpl
|
|
|
349
426
|
});
|
|
350
427
|
}
|
|
351
428
|
|
|
429
|
+
if (latestAppliedAt === 0) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
record.snapshot = {
|
|
434
|
+
accountId,
|
|
435
|
+
venue,
|
|
436
|
+
balances,
|
|
437
|
+
positions: [...positions.values()],
|
|
438
|
+
risk,
|
|
439
|
+
exchangeTs:
|
|
440
|
+
update.exchangeTs === undefined
|
|
441
|
+
? previous.exchangeTs
|
|
442
|
+
: update.exchangeTs,
|
|
443
|
+
receivedAt: latestAppliedAt,
|
|
444
|
+
updatedAt: latestAppliedAt,
|
|
445
|
+
};
|
|
446
|
+
record.status = successfulStatus(record.status, {
|
|
447
|
+
preserveStatus: options.preserveStatus,
|
|
448
|
+
lastReceivedAt: latestAppliedAt,
|
|
449
|
+
lastReadyAt: latestAppliedAt,
|
|
450
|
+
});
|
|
451
|
+
this.publishStatus(record);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
onPrivateAccountReconcile(
|
|
455
|
+
accountId: string,
|
|
456
|
+
venue: Venue,
|
|
457
|
+
snapshot: RawAccountBootstrap,
|
|
458
|
+
options: { requestStartedAt: number; preserveStatus?: boolean },
|
|
459
|
+
): void {
|
|
460
|
+
const record = this.getOrCreateRecord(accountId, venue);
|
|
461
|
+
if (!record.subscribed) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const previous =
|
|
466
|
+
record.snapshot ?? this.createEmptySnapshot(accountId, venue);
|
|
467
|
+
const balances = { ...previous.balances };
|
|
468
|
+
const positions = new Map(
|
|
469
|
+
previous.positions.map((position) => [
|
|
470
|
+
positionKey(position.symbol, position.side),
|
|
471
|
+
position,
|
|
472
|
+
]),
|
|
473
|
+
);
|
|
474
|
+
let risk = previous.risk;
|
|
475
|
+
|
|
476
|
+
const incomingBalanceAssets = new Set<string>();
|
|
477
|
+
for (const balance of snapshot.balances) {
|
|
478
|
+
incomingBalanceAssets.add(balance.asset);
|
|
479
|
+
if (
|
|
480
|
+
!shouldApplyWatermarkedUpdate(balances[balance.asset], balance, {
|
|
481
|
+
requestStartedAt: options.requestStartedAt,
|
|
482
|
+
source: "rest",
|
|
483
|
+
})
|
|
484
|
+
) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const nextBalance = this.createBalance(
|
|
489
|
+
accountId,
|
|
490
|
+
venue,
|
|
491
|
+
balance,
|
|
492
|
+
balances[balance.asset],
|
|
493
|
+
);
|
|
494
|
+
if (isZeroBalance(nextBalance)) {
|
|
495
|
+
delete balances[balance.asset];
|
|
496
|
+
} else {
|
|
497
|
+
balances[balance.asset] = nextBalance;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
for (const [asset, balance] of Object.entries(balances)) {
|
|
502
|
+
if (
|
|
503
|
+
(!incomingBalanceAssets.has(asset) || isZeroBalance(balance)) &&
|
|
504
|
+
canDeleteMissingFromSnapshot(balance, {
|
|
505
|
+
requestStartedAt: options.requestStartedAt,
|
|
506
|
+
snapshotExchangeTs: snapshot.exchangeTs,
|
|
507
|
+
})
|
|
508
|
+
) {
|
|
509
|
+
delete balances[asset];
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const incomingPositionKeys = new Set<string>();
|
|
514
|
+
for (const position of snapshot.positions) {
|
|
515
|
+
const key = positionKey(position.symbol, position.side);
|
|
516
|
+
incomingPositionKeys.add(key);
|
|
517
|
+
if (
|
|
518
|
+
!shouldApplyWatermarkedUpdate(positions.get(key), position, {
|
|
519
|
+
requestStartedAt: options.requestStartedAt,
|
|
520
|
+
source: "rest",
|
|
521
|
+
})
|
|
522
|
+
) {
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const nextPosition = this.createPosition(
|
|
527
|
+
accountId,
|
|
528
|
+
venue,
|
|
529
|
+
position,
|
|
530
|
+
positions.get(key),
|
|
531
|
+
);
|
|
532
|
+
if (isZeroDecimal(nextPosition.size)) {
|
|
533
|
+
positions.delete(key);
|
|
534
|
+
} else {
|
|
535
|
+
positions.set(key, nextPosition);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
for (const [key, position] of positions.entries()) {
|
|
540
|
+
if (
|
|
541
|
+
!incomingPositionKeys.has(key) &&
|
|
542
|
+
canDeleteMissingFromSnapshot(position, {
|
|
543
|
+
requestStartedAt: options.requestStartedAt,
|
|
544
|
+
snapshotExchangeTs: snapshot.exchangeTs,
|
|
545
|
+
})
|
|
546
|
+
) {
|
|
547
|
+
positions.delete(key);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (
|
|
552
|
+
snapshot.risk &&
|
|
553
|
+
shouldApplyWatermarkedUpdate(previous.risk, snapshot.risk, {
|
|
554
|
+
requestStartedAt: options.requestStartedAt,
|
|
555
|
+
source: "rest",
|
|
556
|
+
})
|
|
557
|
+
) {
|
|
558
|
+
risk = this.createRisk(accountId, venue, snapshot.risk, previous.risk);
|
|
559
|
+
}
|
|
560
|
+
|
|
352
561
|
record.snapshot = {
|
|
353
562
|
accountId,
|
|
354
563
|
venue,
|
|
355
564
|
balances,
|
|
356
565
|
positions: [...positions.values()],
|
|
357
566
|
risk,
|
|
358
|
-
exchangeTs:
|
|
359
|
-
|
|
360
|
-
|
|
567
|
+
exchangeTs:
|
|
568
|
+
snapshot.exchangeTs === undefined
|
|
569
|
+
? previous.exchangeTs
|
|
570
|
+
: snapshot.exchangeTs,
|
|
571
|
+
receivedAt: snapshot.receivedAt,
|
|
572
|
+
updatedAt: snapshot.receivedAt,
|
|
361
573
|
};
|
|
362
|
-
record.status =
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
lastReadyAt: update.receivedAt,
|
|
378
|
-
inactiveSince: undefined,
|
|
379
|
-
};
|
|
574
|
+
record.status = successfulStatus(record.status, {
|
|
575
|
+
preserveStatus: options.preserveStatus,
|
|
576
|
+
lastReceivedAt: snapshot.receivedAt,
|
|
577
|
+
lastReadyAt: snapshot.receivedAt,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const event: AccountSnapshotReplacedEvent = {
|
|
581
|
+
type: "account.snapshot_replaced",
|
|
582
|
+
accountId,
|
|
583
|
+
venue,
|
|
584
|
+
snapshot: record.snapshot,
|
|
585
|
+
ts: this.context.now(),
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
this.accountBus.publish(event);
|
|
380
589
|
this.publishStatus(record);
|
|
381
590
|
}
|
|
382
591
|
|
|
@@ -461,7 +670,7 @@ export class AccountManagerImpl
|
|
|
461
670
|
);
|
|
462
671
|
const positions = bootstrap.positions
|
|
463
672
|
.map((position) => this.createPosition(accountId, venue, position))
|
|
464
|
-
.filter((position) => !position.size
|
|
673
|
+
.filter((position) => !isZeroDecimal(position.size));
|
|
465
674
|
const risk = bootstrap.risk
|
|
466
675
|
? this.createRisk(accountId, venue, bootstrap.risk)
|
|
467
676
|
: undefined;
|
|
@@ -499,9 +708,12 @@ export class AccountManagerImpl
|
|
|
499
708
|
input: RawBalanceUpdate,
|
|
500
709
|
previous?: BalanceSnapshot,
|
|
501
710
|
): BalanceSnapshot {
|
|
502
|
-
const previousFree = previous?.free ??
|
|
503
|
-
const previousUsed = previous?.used ??
|
|
504
|
-
const previousTotal =
|
|
711
|
+
const previousFree = new BigNumber(previous?.free ?? 0);
|
|
712
|
+
const previousUsed = new BigNumber(previous?.used ?? 0);
|
|
713
|
+
const previousTotal =
|
|
714
|
+
previous?.total === undefined
|
|
715
|
+
? previousFree.plus(previousUsed)
|
|
716
|
+
: new BigNumber(previous.total);
|
|
505
717
|
const free = getBigNumber(input.free, previousFree);
|
|
506
718
|
const total = getBigNumber(input.total, previousTotal);
|
|
507
719
|
const used =
|
|
@@ -515,27 +727,27 @@ export class AccountManagerImpl
|
|
|
515
727
|
accountId,
|
|
516
728
|
venue,
|
|
517
729
|
asset: input.asset,
|
|
518
|
-
free,
|
|
519
|
-
used,
|
|
520
|
-
total,
|
|
730
|
+
free: toCanonical(free),
|
|
731
|
+
used: toCanonical(used),
|
|
732
|
+
total: toCanonical(total),
|
|
521
733
|
exchangeTs: input.exchangeTs,
|
|
522
734
|
receivedAt: input.receivedAt,
|
|
523
735
|
updatedAt: input.receivedAt,
|
|
524
736
|
seq: (previous?.seq ?? 0) + 1,
|
|
525
737
|
lending: input.lending
|
|
526
738
|
? {
|
|
527
|
-
supplied:
|
|
528
|
-
borrowed:
|
|
529
|
-
interest:
|
|
530
|
-
netAsset:
|
|
739
|
+
supplied: toCanonical(input.lending.supplied),
|
|
740
|
+
borrowed: toCanonical(input.lending.borrowed),
|
|
741
|
+
interest: toCanonical(input.lending.interest),
|
|
742
|
+
netAsset: toCanonical(input.lending.netAsset),
|
|
531
743
|
supplyAPY:
|
|
532
744
|
input.lending.supplyAPY === undefined
|
|
533
745
|
? undefined
|
|
534
|
-
:
|
|
746
|
+
: toCanonical(input.lending.supplyAPY),
|
|
535
747
|
borrowAPY:
|
|
536
748
|
input.lending.borrowAPY === undefined
|
|
537
749
|
? undefined
|
|
538
|
-
:
|
|
750
|
+
: toCanonical(input.lending.borrowAPY),
|
|
539
751
|
}
|
|
540
752
|
: previous?.lending,
|
|
541
753
|
};
|
|
@@ -552,27 +764,27 @@ export class AccountManagerImpl
|
|
|
552
764
|
venue,
|
|
553
765
|
symbol: input.symbol,
|
|
554
766
|
side: input.side,
|
|
555
|
-
size:
|
|
767
|
+
size: toCanonical(input.size),
|
|
556
768
|
entryPrice:
|
|
557
769
|
input.entryPrice === undefined
|
|
558
770
|
? previous?.entryPrice
|
|
559
|
-
:
|
|
771
|
+
: toCanonical(input.entryPrice),
|
|
560
772
|
markPrice:
|
|
561
773
|
input.markPrice === undefined
|
|
562
774
|
? previous?.markPrice
|
|
563
|
-
:
|
|
775
|
+
: toCanonical(input.markPrice),
|
|
564
776
|
unrealizedPnl:
|
|
565
777
|
input.unrealizedPnl === undefined
|
|
566
778
|
? previous?.unrealizedPnl
|
|
567
|
-
:
|
|
779
|
+
: toCanonical(input.unrealizedPnl),
|
|
568
780
|
leverage:
|
|
569
781
|
input.leverage === undefined
|
|
570
782
|
? previous?.leverage
|
|
571
|
-
:
|
|
783
|
+
: toCanonical(input.leverage),
|
|
572
784
|
liquidationPrice:
|
|
573
785
|
input.liquidationPrice === undefined
|
|
574
786
|
? previous?.liquidationPrice
|
|
575
|
-
:
|
|
787
|
+
: toCanonical(input.liquidationPrice),
|
|
576
788
|
exchangeTs: input.exchangeTs,
|
|
577
789
|
receivedAt: input.receivedAt,
|
|
578
790
|
updatedAt: input.receivedAt,
|
|
@@ -592,27 +804,27 @@ export class AccountManagerImpl
|
|
|
592
804
|
netEquity:
|
|
593
805
|
input.netEquity === undefined
|
|
594
806
|
? previous?.netEquity
|
|
595
|
-
:
|
|
807
|
+
: toCanonical(input.netEquity),
|
|
596
808
|
riskEquity:
|
|
597
809
|
input.riskEquity === undefined
|
|
598
810
|
? previous?.riskEquity
|
|
599
|
-
:
|
|
811
|
+
: toCanonical(input.riskEquity),
|
|
600
812
|
riskRatio:
|
|
601
813
|
input.riskRatio === undefined
|
|
602
814
|
? previous?.riskRatio
|
|
603
|
-
:
|
|
815
|
+
: toCanonical(input.riskRatio),
|
|
604
816
|
riskLeverage:
|
|
605
817
|
input.riskLeverage === undefined
|
|
606
818
|
? previous?.riskLeverage
|
|
607
|
-
:
|
|
819
|
+
: toCanonical(input.riskLeverage),
|
|
608
820
|
initialMargin:
|
|
609
821
|
input.initialMargin === undefined
|
|
610
822
|
? previous?.initialMargin
|
|
611
|
-
:
|
|
823
|
+
: toCanonical(input.initialMargin),
|
|
612
824
|
maintenanceMargin:
|
|
613
825
|
input.maintenanceMargin === undefined
|
|
614
826
|
? previous?.maintenanceMargin
|
|
615
|
-
:
|
|
827
|
+
: toCanonical(input.maintenanceMargin),
|
|
616
828
|
exchangeTs: input.exchangeTs,
|
|
617
829
|
receivedAt: input.receivedAt,
|
|
618
830
|
updatedAt: input.receivedAt,
|
|
@@ -622,27 +834,27 @@ export class AccountManagerImpl
|
|
|
622
834
|
marginLevel:
|
|
623
835
|
input.lending.marginLevel === undefined
|
|
624
836
|
? undefined
|
|
625
|
-
:
|
|
837
|
+
: toCanonical(input.lending.marginLevel),
|
|
626
838
|
healthFactor:
|
|
627
839
|
input.lending.healthFactor === undefined
|
|
628
840
|
? undefined
|
|
629
|
-
:
|
|
841
|
+
: toCanonical(input.lending.healthFactor),
|
|
630
842
|
ltv:
|
|
631
843
|
input.lending.ltv === undefined
|
|
632
844
|
? undefined
|
|
633
|
-
:
|
|
845
|
+
: toCanonical(input.lending.ltv),
|
|
634
846
|
liquidationThreshold:
|
|
635
847
|
input.lending.liquidationThreshold === undefined
|
|
636
848
|
? undefined
|
|
637
|
-
:
|
|
849
|
+
: toCanonical(input.lending.liquidationThreshold),
|
|
638
850
|
totalCollateralUSD:
|
|
639
851
|
input.lending.totalCollateralUSD === undefined
|
|
640
852
|
? undefined
|
|
641
|
-
:
|
|
853
|
+
: toCanonical(input.lending.totalCollateralUSD),
|
|
642
854
|
totalDebtUSD:
|
|
643
855
|
input.lending.totalDebtUSD === undefined
|
|
644
856
|
? undefined
|
|
645
|
-
:
|
|
857
|
+
: toCanonical(input.lending.totalDebtUSD),
|
|
646
858
|
}
|
|
647
859
|
: previous?.lending,
|
|
648
860
|
};
|