@lifi/perps-sdk 15.0.0 → 16.0.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 +27 -0
- package/dist/cjs/client/PerpsClient.d.ts +6 -1
- package/dist/cjs/client/PerpsClient.d.ts.map +1 -1
- package/dist/cjs/client/PerpsClient.js +43 -8
- package/dist/cjs/client/PerpsClient.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +6 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/registry/assetRegistry.d.ts +2 -1
- package/dist/cjs/registry/assetRegistry.d.ts.map +1 -1
- package/dist/cjs/registry/assetRegistry.js +11 -1
- package/dist/cjs/registry/assetRegistry.js.map +1 -1
- package/dist/cjs/types/provider.d.ts +6 -1
- package/dist/cjs/types/provider.d.ts.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/websocket/decodeChain.d.ts +11 -0
- package/dist/cjs/websocket/decodeChain.d.ts.map +1 -0
- package/dist/cjs/websocket/decodeChain.js +37 -0
- package/dist/cjs/websocket/decodeChain.js.map +1 -0
- package/dist/esm/client/PerpsClient.d.ts +30 -5
- package/dist/esm/client/PerpsClient.d.ts.map +1 -1
- package/dist/esm/client/PerpsClient.js +77 -13
- package/dist/esm/client/PerpsClient.js.map +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/registry/assetRegistry.d.ts +7 -1
- package/dist/esm/registry/assetRegistry.d.ts.map +1 -1
- package/dist/esm/registry/assetRegistry.js +14 -0
- package/dist/esm/registry/assetRegistry.js.map +1 -1
- package/dist/esm/types/provider.d.ts +20 -1
- package/dist/esm/types/provider.d.ts.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/websocket/decodeChain.d.ts +30 -0
- package/dist/esm/websocket/decodeChain.d.ts.map +1 -0
- package/dist/esm/websocket/decodeChain.js +44 -0
- package/dist/esm/websocket/decodeChain.js.map +1 -0
- package/dist/types/client/PerpsClient.d.ts +30 -5
- package/dist/types/client/PerpsClient.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/registry/assetRegistry.d.ts +7 -1
- package/dist/types/registry/assetRegistry.d.ts.map +1 -1
- package/dist/types/types/provider.d.ts +20 -1
- package/dist/types/types/provider.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/websocket/decodeChain.d.ts +30 -0
- package/dist/types/websocket/decodeChain.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/client/PerpsClient.ts +111 -18
- package/src/index.ts +8 -5
- package/src/registry/assetRegistry.ts +16 -1
- package/src/types/provider.ts +25 -0
- package/src/version.ts +1 -1
- package/src/websocket/decodeChain.ts +54 -0
- package/dist/cjs/utils/accountSummary.d.ts +0 -4
- package/dist/cjs/utils/accountSummary.d.ts.map +0 -1
- package/dist/cjs/utils/accountSummary.js +0 -35
- package/dist/cjs/utils/accountSummary.js.map +0 -1
- package/dist/esm/utils/accountSummary.d.ts +0 -32
- package/dist/esm/utils/accountSummary.d.ts.map +0 -1
- package/dist/esm/utils/accountSummary.js +0 -46
- package/dist/esm/utils/accountSummary.js.map +0 -1
- package/dist/types/utils/accountSummary.d.ts +0 -32
- package/dist/types/utils/accountSummary.d.ts.map +0 -1
- package/src/utils/accountSummary.ts +0 -90
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Asset, AssetsResponse } from '@lifi/perps-types'
|
|
1
|
+
import type { Asset, AssetDisplay, AssetsResponse } from '@lifi/perps-types'
|
|
2
2
|
import { PerpsErrorCode } from '@lifi/perps-types'
|
|
3
3
|
import { PerpsError } from '../errors/PerpsError.js'
|
|
4
4
|
import { buildUrl, request } from '../transport/request.js'
|
|
@@ -59,6 +59,21 @@ export class AssetRegistry extends ReferenceDataRegistry<Asset> {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Project an {@link Asset} to the identity and labels a display needs.
|
|
64
|
+
*
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
export const toAssetDisplay = (asset: Asset): AssetDisplay => ({
|
|
68
|
+
providerId: asset.providerId,
|
|
69
|
+
id: asset.id,
|
|
70
|
+
displaySymbol: asset.displaySymbol,
|
|
71
|
+
logoURI: asset.logoURI,
|
|
72
|
+
...(asset.displayName === undefined
|
|
73
|
+
? {}
|
|
74
|
+
: { displayName: asset.displayName }),
|
|
75
|
+
})
|
|
76
|
+
|
|
62
77
|
const registries = new WeakMap<PerpsSDKClient, Map<string, AssetRegistry>>()
|
|
63
78
|
|
|
64
79
|
/**
|
package/src/types/provider.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ActionType,
|
|
9
9
|
ActivitiesResponse,
|
|
10
10
|
ActivityType,
|
|
11
|
+
AvailableToTrade,
|
|
11
12
|
FillsResponse,
|
|
12
13
|
Market,
|
|
13
14
|
MarketRef,
|
|
@@ -216,6 +217,17 @@ export interface ProviderGetMarketSettingsParams {
|
|
|
216
217
|
market: MarketRef
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Read params for {@link PerpsProviderPlugin.getAvailableToTrade}.
|
|
222
|
+
*
|
|
223
|
+
* @public
|
|
224
|
+
*/
|
|
225
|
+
export interface ProviderGetAvailableToTradeParams {
|
|
226
|
+
address: Address
|
|
227
|
+
/** The market's opaque `Market.id` (not a display symbol). */
|
|
228
|
+
marketId: string
|
|
229
|
+
}
|
|
230
|
+
|
|
219
231
|
/**
|
|
220
232
|
* Read params for {@link PerpsProvider.getOrders}.
|
|
221
233
|
*
|
|
@@ -442,6 +454,19 @@ export interface PerpsProviderPlugin {
|
|
|
442
454
|
options?: SDKRequestOptions
|
|
443
455
|
): Promise<MarketSettings | undefined>
|
|
444
456
|
|
|
457
|
+
/**
|
|
458
|
+
* The amounts the account can still buy and sell on one market, in that
|
|
459
|
+
* market's margin asset. Optional because venues expose this unevenly:
|
|
460
|
+
* Hyperliquid reads it directly (`activeAssetData`), other venues publish
|
|
461
|
+
* only an account-scoped figure. `undefined` means the venue has nothing
|
|
462
|
+
* to read for this market, and the caller falls back to the account
|
|
463
|
+
* summary.
|
|
464
|
+
*/
|
|
465
|
+
getAvailableToTrade?(
|
|
466
|
+
params: ProviderGetAvailableToTradeParams,
|
|
467
|
+
options?: SDKRequestOptions
|
|
468
|
+
): Promise<AvailableToTrade | undefined>
|
|
469
|
+
|
|
445
470
|
getOrders(
|
|
446
471
|
params: ProviderGetOrdersParams,
|
|
447
472
|
options?: SDKRequestOptions
|
package/src/version.ts
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame semantics of a {@link DecodeChain}:
|
|
3
|
+
* - `'every'`: every frame decodes and applies in arrival order — required for
|
|
4
|
+
* delta-carrying channels, where dropping a frame corrupts downstream state.
|
|
5
|
+
* - `'latest'`: frames queued behind an in-flight decode coalesce to the
|
|
6
|
+
* newest — for snapshot-like channels, where a newer frame supersedes
|
|
7
|
+
* anything still waiting.
|
|
8
|
+
*/
|
|
9
|
+
export type DecodeChainMode = 'every' | 'latest'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Serializes async WS frame decodes so results apply in arrival order.
|
|
13
|
+
* In `'latest'` mode a backlog (e.g. queued behind a main-thread stall)
|
|
14
|
+
* collapses to its newest frame instead of replaying every stale decode.
|
|
15
|
+
* Decode failures are reported to `onError` and never break the chain.
|
|
16
|
+
*/
|
|
17
|
+
export class DecodeChain {
|
|
18
|
+
private tail: Promise<void> = Promise.resolve()
|
|
19
|
+
private queued: (() => Promise<void>) | undefined
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
private readonly mode: DecodeChainMode,
|
|
23
|
+
private readonly onError: (error: unknown) => void
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
push(decode: () => Promise<void>): void {
|
|
27
|
+
if (this.mode === 'every') {
|
|
28
|
+
this.tail = this.tail.then(decode).catch(this.onError)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
const drainScheduled = this.queued !== undefined
|
|
32
|
+
this.queued = decode
|
|
33
|
+
if (drainScheduled) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
this.tail = this.tail
|
|
37
|
+
.then(() => {
|
|
38
|
+
const next = this.queued
|
|
39
|
+
this.queued = undefined
|
|
40
|
+
return next?.()
|
|
41
|
+
})
|
|
42
|
+
.catch(this.onError)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Detach on connection teardown: drops the queued latest-mode decode and
|
|
47
|
+
* starts subsequent pushes on a fresh chain. A decode already in flight
|
|
48
|
+
* still settles.
|
|
49
|
+
*/
|
|
50
|
+
reset(): void {
|
|
51
|
+
this.tail = Promise.resolve()
|
|
52
|
+
this.queued = undefined
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { AccountResponse, AccountSummary, Position } from '@lifi/perps-types';
|
|
2
|
-
export type CollateralSemantics = 'free' | 'net' | 'gross' | 'equity';
|
|
3
|
-
export declare function summarizeAccount(account: AccountResponse, positions: Position[], semantics: CollateralSemantics): AccountSummary;
|
|
4
|
-
//# sourceMappingURL=accountSummary.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountSummary.d.ts","sourceRoot":"","sources":["../../../src/utils/accountSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,QAAQ,EACT,MAAM,mBAAmB,CAAA;AAgC1B,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAUrE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,QAAQ,EAAE,EACrB,SAAS,EAAE,mBAAmB,GAC7B,cAAc,CAuChB"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.summarizeAccount = summarizeAccount;
|
|
4
|
-
const parse_js_1 = require("./parse.js");
|
|
5
|
-
const sumValueUsd = (balances) => balances.reduce((sum, b) => sum + (0, parse_js_1.stringToFloat)(b.valueUsd), 0);
|
|
6
|
-
const sumMarginUsd = (balances) => balances.reduce((sum, b) => sum + (0, parse_js_1.stringToFloat)(b.valueUsd) * (b.collateralWeight ?? 1), 0);
|
|
7
|
-
function summarizeAccount(account, positions, semantics) {
|
|
8
|
-
let marginUsed = 0;
|
|
9
|
-
let unrealizedPnl = 0;
|
|
10
|
-
for (const p of positions) {
|
|
11
|
-
marginUsed += (0, parse_js_1.stringToFloat)(p.marginUsed);
|
|
12
|
-
unrealizedPnl += (0, parse_js_1.stringToFloat)(p.unrealizedPnl);
|
|
13
|
-
}
|
|
14
|
-
const collateral = sumValueUsd(account.collateralBalances);
|
|
15
|
-
const marginCollateral = sumMarginUsd(account.collateralBalances);
|
|
16
|
-
const balances = sumValueUsd(account.balances);
|
|
17
|
-
const withLocked = semantics === 'free' || semantics === 'net';
|
|
18
|
-
const grossCollateral = withLocked ? collateral + marginUsed : collateral;
|
|
19
|
-
const grossMarginCollateral = withLocked
|
|
20
|
-
? marginCollateral + marginUsed
|
|
21
|
-
: marginCollateral;
|
|
22
|
-
const equity = semantics === 'equity' || semantics === 'net'
|
|
23
|
-
? grossCollateral
|
|
24
|
-
: grossCollateral + unrealizedPnl;
|
|
25
|
-
const availableMargin = grossMarginCollateral +
|
|
26
|
-
(semantics === 'gross' ? unrealizedPnl : 0) -
|
|
27
|
-
marginUsed;
|
|
28
|
-
return {
|
|
29
|
-
portfolioValue: (balances + equity).toString(),
|
|
30
|
-
availableMargin: availableMargin.toString(),
|
|
31
|
-
marginUsed: marginUsed.toString(),
|
|
32
|
-
unrealizedPnl: unrealizedPnl.toString(),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=accountSummary.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountSummary.js","sourceRoot":"","sources":["../../../src/utils/accountSummary.ts"],"names":[],"mappings":";;AA8CA,4CA2CC;AApFD,yCAA0C;AAE1C,MAAM,WAAW,GAAG,CAAC,QAAqC,EAAU,EAAE,CACpE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAA,wBAAa,EAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAA;AAEjE,MAAM,YAAY,GAAG,CAAC,QAAqC,EAAU,EAAE,CACrE,QAAQ,CAAC,MAAM,CACb,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAA,wBAAa,EAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,EACvE,CAAC,CACF,CAAA;AAgCH,SAAgB,gBAAgB,CAC9B,OAAwB,EACxB,SAAqB,EACrB,SAA8B;IAE9B,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,aAAa,GAAG,CAAC,CAAA;IACrB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,UAAU,IAAI,IAAA,wBAAa,EAAC,CAAC,CAAC,UAAU,CAAC,CAAA;QACzC,aAAa,IAAI,IAAA,wBAAa,EAAC,CAAC,CAAC,aAAa,CAAC,CAAA;IACjD,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAI1D,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAE9C,MAAM,UAAU,GAAG,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,KAAK,CAAA;IAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAA;IACzE,MAAM,qBAAqB,GAAG,UAAU;QACtC,CAAC,CAAC,gBAAgB,GAAG,UAAU;QAC/B,CAAC,CAAC,gBAAgB,CAAA;IACpB,MAAM,MAAM,GACV,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,KAAK;QAC3C,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,eAAe,GAAG,aAAa,CAAA;IAKrC,MAAM,eAAe,GACnB,qBAAqB;QACrB,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,UAAU,CAAA;IAEZ,OAAO;QACL,cAAc,EAAE,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE;QAC9C,eAAe,EAAE,eAAe,CAAC,QAAQ,EAAE;QAC3C,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE;QACjC,aAAa,EAAE,aAAa,CAAC,QAAQ,EAAE;KACxC,CAAA;AACH,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { AccountResponse, AccountSummary, Position } from '@lifi/perps-types';
|
|
2
|
-
/**
|
|
3
|
-
* What the summed `collateralBalances` rows already contain, relative to the
|
|
4
|
-
* positions' locked margin and unrealized PnL:
|
|
5
|
-
*
|
|
6
|
-
* - `'free'` — free collateral only; locked margin and unrealized PnL are
|
|
7
|
-
* both carried by the positions. Available margin is the free collateral
|
|
8
|
-
* as-is; unrealized PnL is not counted toward it.
|
|
9
|
-
* - `'net'` — free collateral with unrealized PnL already marked in; only
|
|
10
|
-
* the locked margin is carried by the positions (e.g. a venue-reported
|
|
11
|
-
* available balance).
|
|
12
|
-
* - `'gross'` — locked margin included, unrealized PnL carried by the
|
|
13
|
-
* positions (e.g. spot holdings backing a unified account). The venue
|
|
14
|
-
* counts unrealized PnL toward buying power, so it is added to available
|
|
15
|
-
* margin on top of the gross collateral.
|
|
16
|
-
* - `'equity'` — total equity: locked margin AND unrealized PnL included
|
|
17
|
-
* (e.g. a venue-reported account value). Unrealized PnL is thus already
|
|
18
|
-
* counted toward available margin.
|
|
19
|
-
*
|
|
20
|
-
* @public
|
|
21
|
-
*/
|
|
22
|
-
export type CollateralSemantics = 'free' | 'net' | 'gross' | 'equity';
|
|
23
|
-
/**
|
|
24
|
-
* Roll an {@link AccountResponse} and its open positions up into an
|
|
25
|
-
* {@link AccountSummary}.
|
|
26
|
-
*
|
|
27
|
-
* @param semantics - How the collateral rows relate to the positions'
|
|
28
|
-
* locked margin and unrealized PnL; see {@link CollateralSemantics}.
|
|
29
|
-
* @public
|
|
30
|
-
*/
|
|
31
|
-
export declare function summarizeAccount(account: AccountResponse, positions: Position[], semantics: CollateralSemantics): AccountSummary;
|
|
32
|
-
//# sourceMappingURL=accountSummary.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountSummary.d.ts","sourceRoot":"","sources":["../../../src/utils/accountSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,QAAQ,EACT,MAAM,mBAAmB,CAAA;AAY1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAErE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,QAAQ,EAAE,EACrB,SAAS,EAAE,mBAAmB,GAC7B,cAAc,CAuChB"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { stringToFloat } from './parse.js';
|
|
2
|
-
const sumValueUsd = (balances) => balances.reduce((sum, b) => sum + stringToFloat(b.valueUsd), 0);
|
|
3
|
-
const sumMarginUsd = (balances) => balances.reduce((sum, b) => sum + stringToFloat(b.valueUsd) * (b.collateralWeight ?? 1), 0);
|
|
4
|
-
/**
|
|
5
|
-
* Roll an {@link AccountResponse} and its open positions up into an
|
|
6
|
-
* {@link AccountSummary}.
|
|
7
|
-
*
|
|
8
|
-
* @param semantics - How the collateral rows relate to the positions'
|
|
9
|
-
* locked margin and unrealized PnL; see {@link CollateralSemantics}.
|
|
10
|
-
* @public
|
|
11
|
-
*/
|
|
12
|
-
export function summarizeAccount(account, positions, semantics) {
|
|
13
|
-
let marginUsed = 0;
|
|
14
|
-
let unrealizedPnl = 0;
|
|
15
|
-
for (const p of positions) {
|
|
16
|
-
marginUsed += stringToFloat(p.marginUsed);
|
|
17
|
-
unrealizedPnl += stringToFloat(p.unrealizedPnl);
|
|
18
|
-
}
|
|
19
|
-
const collateral = sumValueUsd(account.collateralBalances);
|
|
20
|
-
// Margin-eligible collateral: each row's value scaled by its loan-to-value
|
|
21
|
-
// weight (1 when unset), so a haircut asset backs buying power at less than
|
|
22
|
-
// face while `portfolioValue` still reflects its full value.
|
|
23
|
-
const marginCollateral = sumMarginUsd(account.collateralBalances);
|
|
24
|
-
const balances = sumValueUsd(account.balances);
|
|
25
|
-
const withLocked = semantics === 'free' || semantics === 'net';
|
|
26
|
-
const grossCollateral = withLocked ? collateral + marginUsed : collateral;
|
|
27
|
-
const grossMarginCollateral = withLocked
|
|
28
|
-
? marginCollateral + marginUsed
|
|
29
|
-
: marginCollateral;
|
|
30
|
-
const equity = semantics === 'equity' || semantics === 'net'
|
|
31
|
-
? grossCollateral
|
|
32
|
-
: grossCollateral + unrealizedPnl;
|
|
33
|
-
// Buying power is equity net of locked margin, so unrealized PnL counts
|
|
34
|
-
// toward it. The `'free'` rows exclude uPnL from available margin, holding
|
|
35
|
-
// it purely as free collateral.
|
|
36
|
-
const availableMargin = grossMarginCollateral +
|
|
37
|
-
(semantics === 'gross' ? unrealizedPnl : 0) -
|
|
38
|
-
marginUsed;
|
|
39
|
-
return {
|
|
40
|
-
portfolioValue: (balances + equity).toString(),
|
|
41
|
-
availableMargin: availableMargin.toString(),
|
|
42
|
-
marginUsed: marginUsed.toString(),
|
|
43
|
-
unrealizedPnl: unrealizedPnl.toString(),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=accountSummary.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountSummary.js","sourceRoot":"","sources":["../../../src/utils/accountSummary.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,MAAM,WAAW,GAAG,CAAC,QAAqC,EAAU,EAAE,CACpE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAA;AAEjE,MAAM,YAAY,GAAG,CAAC,QAAqC,EAAU,EAAE,CACrE,QAAQ,CAAC,MAAM,CACb,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,EACvE,CAAC,CACF,CAAA;AAwBH;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAwB,EACxB,SAAqB,EACrB,SAA8B;IAE9B,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,aAAa,GAAG,CAAC,CAAA;IACrB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,UAAU,IAAI,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;QACzC,aAAa,IAAI,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;IACjD,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC1D,2EAA2E;IAC3E,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAE9C,MAAM,UAAU,GAAG,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,KAAK,CAAA;IAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAA;IACzE,MAAM,qBAAqB,GAAG,UAAU;QACtC,CAAC,CAAC,gBAAgB,GAAG,UAAU;QAC/B,CAAC,CAAC,gBAAgB,CAAA;IACpB,MAAM,MAAM,GACV,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,KAAK;QAC3C,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,eAAe,GAAG,aAAa,CAAA;IAErC,wEAAwE;IACxE,2EAA2E;IAC3E,gCAAgC;IAChC,MAAM,eAAe,GACnB,qBAAqB;QACrB,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,UAAU,CAAA;IAEZ,OAAO;QACL,cAAc,EAAE,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE;QAC9C,eAAe,EAAE,eAAe,CAAC,QAAQ,EAAE;QAC3C,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE;QACjC,aAAa,EAAE,aAAa,CAAC,QAAQ,EAAE;KACxC,CAAA;AACH,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { AccountResponse, AccountSummary, Position } from '@lifi/perps-types';
|
|
2
|
-
/**
|
|
3
|
-
* What the summed `collateralBalances` rows already contain, relative to the
|
|
4
|
-
* positions' locked margin and unrealized PnL:
|
|
5
|
-
*
|
|
6
|
-
* - `'free'` — free collateral only; locked margin and unrealized PnL are
|
|
7
|
-
* both carried by the positions. Available margin is the free collateral
|
|
8
|
-
* as-is; unrealized PnL is not counted toward it.
|
|
9
|
-
* - `'net'` — free collateral with unrealized PnL already marked in; only
|
|
10
|
-
* the locked margin is carried by the positions (e.g. a venue-reported
|
|
11
|
-
* available balance).
|
|
12
|
-
* - `'gross'` — locked margin included, unrealized PnL carried by the
|
|
13
|
-
* positions (e.g. spot holdings backing a unified account). The venue
|
|
14
|
-
* counts unrealized PnL toward buying power, so it is added to available
|
|
15
|
-
* margin on top of the gross collateral.
|
|
16
|
-
* - `'equity'` — total equity: locked margin AND unrealized PnL included
|
|
17
|
-
* (e.g. a venue-reported account value). Unrealized PnL is thus already
|
|
18
|
-
* counted toward available margin.
|
|
19
|
-
*
|
|
20
|
-
* @public
|
|
21
|
-
*/
|
|
22
|
-
export type CollateralSemantics = 'free' | 'net' | 'gross' | 'equity';
|
|
23
|
-
/**
|
|
24
|
-
* Roll an {@link AccountResponse} and its open positions up into an
|
|
25
|
-
* {@link AccountSummary}.
|
|
26
|
-
*
|
|
27
|
-
* @param semantics - How the collateral rows relate to the positions'
|
|
28
|
-
* locked margin and unrealized PnL; see {@link CollateralSemantics}.
|
|
29
|
-
* @public
|
|
30
|
-
*/
|
|
31
|
-
export declare function summarizeAccount(account: AccountResponse, positions: Position[], semantics: CollateralSemantics): AccountSummary;
|
|
32
|
-
//# sourceMappingURL=accountSummary.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountSummary.d.ts","sourceRoot":"","sources":["../../../src/utils/accountSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,QAAQ,EACT,MAAM,mBAAmB,CAAA;AAY1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAErE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,QAAQ,EAAE,EACrB,SAAS,EAAE,mBAAmB,GAC7B,cAAc,CAuChB"}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AccountResponse,
|
|
3
|
-
AccountSummary,
|
|
4
|
-
Position,
|
|
5
|
-
} from '@lifi/perps-types'
|
|
6
|
-
import { stringToFloat } from './parse.js'
|
|
7
|
-
|
|
8
|
-
const sumValueUsd = (balances: AccountResponse['balances']): number =>
|
|
9
|
-
balances.reduce((sum, b) => sum + stringToFloat(b.valueUsd), 0)
|
|
10
|
-
|
|
11
|
-
const sumMarginUsd = (balances: AccountResponse['balances']): number =>
|
|
12
|
-
balances.reduce(
|
|
13
|
-
(sum, b) => sum + stringToFloat(b.valueUsd) * (b.collateralWeight ?? 1),
|
|
14
|
-
0
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* What the summed `collateralBalances` rows already contain, relative to the
|
|
19
|
-
* positions' locked margin and unrealized PnL:
|
|
20
|
-
*
|
|
21
|
-
* - `'free'` — free collateral only; locked margin and unrealized PnL are
|
|
22
|
-
* both carried by the positions. Available margin is the free collateral
|
|
23
|
-
* as-is; unrealized PnL is not counted toward it.
|
|
24
|
-
* - `'net'` — free collateral with unrealized PnL already marked in; only
|
|
25
|
-
* the locked margin is carried by the positions (e.g. a venue-reported
|
|
26
|
-
* available balance).
|
|
27
|
-
* - `'gross'` — locked margin included, unrealized PnL carried by the
|
|
28
|
-
* positions (e.g. spot holdings backing a unified account). The venue
|
|
29
|
-
* counts unrealized PnL toward buying power, so it is added to available
|
|
30
|
-
* margin on top of the gross collateral.
|
|
31
|
-
* - `'equity'` — total equity: locked margin AND unrealized PnL included
|
|
32
|
-
* (e.g. a venue-reported account value). Unrealized PnL is thus already
|
|
33
|
-
* counted toward available margin.
|
|
34
|
-
*
|
|
35
|
-
* @public
|
|
36
|
-
*/
|
|
37
|
-
export type CollateralSemantics = 'free' | 'net' | 'gross' | 'equity'
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Roll an {@link AccountResponse} and its open positions up into an
|
|
41
|
-
* {@link AccountSummary}.
|
|
42
|
-
*
|
|
43
|
-
* @param semantics - How the collateral rows relate to the positions'
|
|
44
|
-
* locked margin and unrealized PnL; see {@link CollateralSemantics}.
|
|
45
|
-
* @public
|
|
46
|
-
*/
|
|
47
|
-
export function summarizeAccount(
|
|
48
|
-
account: AccountResponse,
|
|
49
|
-
positions: Position[],
|
|
50
|
-
semantics: CollateralSemantics
|
|
51
|
-
): AccountSummary {
|
|
52
|
-
let marginUsed = 0
|
|
53
|
-
let unrealizedPnl = 0
|
|
54
|
-
for (const p of positions) {
|
|
55
|
-
marginUsed += stringToFloat(p.marginUsed)
|
|
56
|
-
unrealizedPnl += stringToFloat(p.unrealizedPnl)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const collateral = sumValueUsd(account.collateralBalances)
|
|
60
|
-
// Margin-eligible collateral: each row's value scaled by its loan-to-value
|
|
61
|
-
// weight (1 when unset), so a haircut asset backs buying power at less than
|
|
62
|
-
// face while `portfolioValue` still reflects its full value.
|
|
63
|
-
const marginCollateral = sumMarginUsd(account.collateralBalances)
|
|
64
|
-
const balances = sumValueUsd(account.balances)
|
|
65
|
-
|
|
66
|
-
const withLocked = semantics === 'free' || semantics === 'net'
|
|
67
|
-
const grossCollateral = withLocked ? collateral + marginUsed : collateral
|
|
68
|
-
const grossMarginCollateral = withLocked
|
|
69
|
-
? marginCollateral + marginUsed
|
|
70
|
-
: marginCollateral
|
|
71
|
-
const equity =
|
|
72
|
-
semantics === 'equity' || semantics === 'net'
|
|
73
|
-
? grossCollateral
|
|
74
|
-
: grossCollateral + unrealizedPnl
|
|
75
|
-
|
|
76
|
-
// Buying power is equity net of locked margin, so unrealized PnL counts
|
|
77
|
-
// toward it. The `'free'` rows exclude uPnL from available margin, holding
|
|
78
|
-
// it purely as free collateral.
|
|
79
|
-
const availableMargin =
|
|
80
|
-
grossMarginCollateral +
|
|
81
|
-
(semantics === 'gross' ? unrealizedPnl : 0) -
|
|
82
|
-
marginUsed
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
portfolioValue: (balances + equity).toString(),
|
|
86
|
-
availableMargin: availableMargin.toString(),
|
|
87
|
-
marginUsed: marginUsed.toString(),
|
|
88
|
-
unrealizedPnl: unrealizedPnl.toString(),
|
|
89
|
-
}
|
|
90
|
-
}
|