@lifi/perps-sdk-provider-lighter 36.0.0 → 37.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/dist/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +4 -6
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountSummary.d.ts.map +1 -1
- package/dist/cjs/accountSummary.js +13 -6
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +1 -3
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapFill.js +1 -1
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.d.ts +1 -2
- package/dist/cjs/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.js +1 -13
- package/dist/cjs/utils/mapOpenPositions.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +26 -43
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +34 -16
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/transferMargin.js +1 -1
- package/dist/cjs/utils/transferMargin.js.map +1 -1
- package/dist/cjs/utils/wireEncoding.d.ts +0 -2
- package/dist/cjs/utils/wireEncoding.d.ts.map +1 -1
- package/dist/cjs/utils/wireEncoding.js +1 -15
- package/dist/cjs/utils/wireEncoding.js.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js +46 -26
- package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
- package/dist/cjs/websocket/orderBookSide.d.ts +2 -1
- package/dist/cjs/websocket/orderBookSide.d.ts.map +1 -1
- package/dist/cjs/websocket/orderBookSide.js +5 -3
- package/dist/cjs/websocket/orderBookSide.js.map +1 -1
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +5 -8
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts.map +1 -1
- package/dist/esm/accountSummary.js +14 -7
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapFill.js +1 -1
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapOpenPositions.d.ts +1 -8
- package/dist/esm/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/esm/utils/mapOpenPositions.js +1 -18
- package/dist/esm/utils/mapOpenPositions.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +6 -3
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +33 -47
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/esm/utils/mapPortfolioHistory.d.ts +2 -2
- package/dist/esm/utils/mapPortfolioHistory.js +2 -2
- package/dist/esm/utils/mapPosition.d.ts +4 -3
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +39 -20
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/transferMargin.js +1 -1
- package/dist/esm/utils/transferMargin.js.map +1 -1
- package/dist/esm/utils/wireEncoding.d.ts +2 -28
- package/dist/esm/utils/wireEncoding.d.ts.map +1 -1
- package/dist/esm/utils/wireEncoding.js +2 -38
- package/dist/esm/utils/wireEncoding.js.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.js +56 -27
- package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
- package/dist/esm/websocket/orderBookSide.d.ts +3 -2
- package/dist/esm/websocket/orderBookSide.d.ts.map +1 -1
- package/dist/esm/websocket/orderBookSide.js +5 -3
- package/dist/esm/websocket/orderBookSide.js.map +1 -1
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountSummary.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapOpenPositions.d.ts +1 -8
- package/dist/types/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +6 -3
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/dist/types/utils/mapPortfolioHistory.d.ts +2 -2
- package/dist/types/utils/mapPosition.d.ts +4 -3
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/wireEncoding.d.ts +2 -28
- package/dist/types/utils/wireEncoding.d.ts.map +1 -1
- package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/types/websocket/orderBookSide.d.ts +3 -2
- package/dist/types/websocket/orderBookSide.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/LighterProvider.ts +14 -16
- package/src/accountSummary.ts +27 -6
- package/src/utils/index.ts +0 -2
- package/src/utils/mapFill.ts +1 -1
- package/src/utils/mapOpenPositions.ts +2 -30
- package/src/utils/mapOrder.ts +46 -67
- package/src/utils/mapPortfolioHistory.ts +2 -2
- package/src/utils/mapPosition.ts +50 -23
- package/src/utils/transferMargin.ts +1 -1
- package/src/utils/wireEncoding.ts +2 -43
- package/src/websocket/LighterWsProvider.ts +100 -60
- package/src/websocket/orderBookSide.ts +17 -4
package/src/utils/mapPosition.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
absDecimalString,
|
|
3
|
+
createWarnOnce,
|
|
3
4
|
divideDecimalString,
|
|
4
5
|
isDecimalString,
|
|
5
6
|
isDecimalStringZero,
|
|
@@ -53,16 +54,32 @@ export const leverageFromScaledImf = (imf: number): string | undefined => {
|
|
|
53
54
|
return percent === undefined ? undefined : leverageFromImf(percent)
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
const skipPosition = (
|
|
57
|
-
|
|
57
|
+
const skipPosition = (
|
|
58
|
+
marketId: string,
|
|
59
|
+
field: string,
|
|
60
|
+
value: unknown
|
|
61
|
+
): undefined => {
|
|
62
|
+
warnSkippedVenueRow(LIGHTER_PROVIDER_KEY, 'position', field, value, {
|
|
63
|
+
marketId,
|
|
64
|
+
})
|
|
58
65
|
return undefined
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
const warnUnreadableFieldOnce = createWarnOnce()
|
|
69
|
+
|
|
70
|
+
const warnUnreadableField = (field: string, value: unknown): void => {
|
|
71
|
+
warnUnreadableFieldOnce(
|
|
72
|
+
`${LIGHTER_PROVIDER_KEY}|position.${field}`,
|
|
73
|
+
`[${LIGHTER_PROVIDER_KEY}] position \`${field}\` is not readable, so the derived fields are absent: '${String(value).slice(0, 64)}'`
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
/**
|
|
62
78
|
* Map a raw Lighter account position to the generic Position type. A row with
|
|
63
|
-
* an invalid size
|
|
64
|
-
*
|
|
65
|
-
*
|
|
79
|
+
* an invalid size gives `undefined`. An invalid position value or a
|
|
80
|
+
* non-positive initial margin fraction keeps the row, leaves `leverage` and
|
|
81
|
+
* `initialMarginRequirement` absent, sets a cross `marginUsed` to `'0'` and
|
|
82
|
+
* warns once. Prices, PnL, funding and isolated margin pass through raw.
|
|
66
83
|
* @param market - Backend-resolved market identity for `pos.market_id`.
|
|
67
84
|
* @public
|
|
68
85
|
*/
|
|
@@ -71,39 +88,49 @@ export const mapPosition = (
|
|
|
71
88
|
market: PerpsMarketDisplay
|
|
72
89
|
): Position | undefined => {
|
|
73
90
|
if (!isDecimalString(pos.position)) {
|
|
74
|
-
return skipPosition('position', pos.position)
|
|
91
|
+
return skipPosition(market.id, 'position', pos.position)
|
|
75
92
|
}
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
const isIsolated = pos.margin_mode === LT_MARGIN_MODE_ISOLATED
|
|
94
|
+
const size = absDecimalString(pos.position)
|
|
95
|
+
const positionValue = isDecimalString(pos.position_value)
|
|
96
|
+
? absDecimalString(pos.position_value)
|
|
97
|
+
: undefined
|
|
98
|
+
if (positionValue === undefined) {
|
|
99
|
+
warnUnreadableField('position_value', pos.position_value)
|
|
78
100
|
}
|
|
79
101
|
const imf = pos.initial_margin_fraction
|
|
80
102
|
const leverage = isDecimalString(imf) ? leverageFromImf(imf) : undefined
|
|
81
103
|
if (leverage === undefined) {
|
|
82
|
-
|
|
104
|
+
warnUnreadableField('initial_margin_fraction', imf)
|
|
83
105
|
}
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
multiplyDecimalString(positionValue, imf),
|
|
89
|
-
'100'
|
|
90
|
-
)
|
|
106
|
+
const initialMarginRequirement =
|
|
107
|
+
positionValue === undefined || leverage === undefined
|
|
108
|
+
? undefined
|
|
109
|
+
: divideDecimalString(multiplyDecimalString(positionValue, imf), '100')
|
|
91
110
|
|
|
92
111
|
return {
|
|
93
112
|
market,
|
|
94
113
|
side: pos.sign >= 0 ? PositionSide.LONG : PositionSide.SHORT,
|
|
95
114
|
size,
|
|
96
115
|
entryPrice: pos.avg_entry_price,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
...(positionValue === undefined
|
|
117
|
+
? {}
|
|
118
|
+
: {
|
|
119
|
+
markPrice:
|
|
120
|
+
isDecimalStringZero(positionValue) || isDecimalStringZero(size)
|
|
121
|
+
? '0'
|
|
122
|
+
: divideDecimalString(positionValue, size),
|
|
123
|
+
}),
|
|
101
124
|
liquidationPrice: pos.liquidation_price,
|
|
102
125
|
unrealizedPnl: pos.unrealized_pnl,
|
|
103
126
|
accruedFunding: pos.total_funding_paid_out ?? '0',
|
|
104
|
-
leverage,
|
|
105
|
-
marginUsed: isIsolated
|
|
106
|
-
|
|
127
|
+
...(leverage === undefined ? {} : { leverage }),
|
|
128
|
+
marginUsed: isIsolated
|
|
129
|
+
? pos.allocated_margin
|
|
130
|
+
: (initialMarginRequirement ?? '0'),
|
|
131
|
+
...(initialMarginRequirement === undefined
|
|
132
|
+
? {}
|
|
133
|
+
: { initialMarginRequirement }),
|
|
107
134
|
marginMode: isIsolated ? MarginMode.ISOLATED : MarginMode.CROSS,
|
|
108
135
|
}
|
|
109
136
|
}
|
|
@@ -23,7 +23,7 @@ function positionAmount(
|
|
|
23
23
|
if (!isDecimalString(value)) {
|
|
24
24
|
throw new PerpsError(
|
|
25
25
|
PerpsErrorCode.ValidationError,
|
|
26
|
-
`Invalid \`Position.${field}\`: '${value}'
|
|
26
|
+
`Invalid \`Position.${field}\`: '${value}' does not match the decimal pattern.`
|
|
27
27
|
)
|
|
28
28
|
}
|
|
29
29
|
return value
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lighter wire encoding for the WASM signer:
|
|
3
|
-
*
|
|
2
|
+
* Lighter wire encoding for the WASM signer: order-type/time-in-force/expiry
|
|
3
|
+
* resolution mirroring lighter-go's rules.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { PerpsError } from '@lifi/perps-sdk'
|
|
@@ -19,47 +19,6 @@ import {
|
|
|
19
19
|
LT_TIME_IN_FORCE_POST_ONLY,
|
|
20
20
|
} from '../types/action.js'
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
* Convert Lighter's initial-margin fraction to the largest whole-number
|
|
24
|
-
* leverage exposed by the provider.
|
|
25
|
-
*
|
|
26
|
-
* Lighter expresses margin fractions in basis points (`10_000` = 100%), so
|
|
27
|
-
* the conversion is `floor(10_000 / fraction)`. Non-finite or non-positive
|
|
28
|
-
* input uses the safe `1x` fallback.
|
|
29
|
-
*
|
|
30
|
-
* @param fraction - Lighter's basis-point initial-margin fraction.
|
|
31
|
-
* @returns The floored maximum leverage, or `1` for invalid input.
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
export const marginFractionToMaxLeverage = (fraction: number): number => {
|
|
35
|
-
if (!Number.isFinite(fraction) || fraction <= 0) {
|
|
36
|
-
return 1
|
|
37
|
-
}
|
|
38
|
-
return Math.floor(10_000 / fraction)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Convert requested leverage to Lighter's basis-point margin fraction.
|
|
43
|
-
*
|
|
44
|
-
* The signer expects `round(10_000 / leverage)`, where the result is the
|
|
45
|
-
* margin requirement in basis points.
|
|
46
|
-
*
|
|
47
|
-
* @param leverage - Requested leverage multiplier.
|
|
48
|
-
* @returns The rounded basis-point margin fraction.
|
|
49
|
-
* @throws {PerpsError} With `ValidationError` when leverage is less than
|
|
50
|
-
* or equal to zero.
|
|
51
|
-
* @public
|
|
52
|
-
*/
|
|
53
|
-
export const leverageToFraction = (leverage: number): number => {
|
|
54
|
-
if (leverage <= 0) {
|
|
55
|
-
throw new PerpsError(
|
|
56
|
-
PerpsErrorCode.ValidationError,
|
|
57
|
-
`Invalid leverage: ${leverage}`
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
return Math.round(10_000 / leverage)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
22
|
/**
|
|
64
23
|
* Map a LI.FI `OrderType` value to Lighter's integer wire type.
|
|
65
24
|
* Supported mappings are LIMIT → 0, MARKET → 1, STOP_MARKET → 2,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
addDecimalString,
|
|
3
3
|
cachePromise,
|
|
4
|
+
createSafeFunction,
|
|
4
5
|
getMarketRegistry,
|
|
5
6
|
isDecimalStringGreaterThan,
|
|
6
7
|
type MarketRegistry,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
ReconnectingWebSocket,
|
|
13
14
|
resolveRetryPolicy,
|
|
14
15
|
resolveSubscribeQuote,
|
|
16
|
+
safeUnknownToDecimalString,
|
|
15
17
|
subtractDecimalString,
|
|
16
18
|
toPerpsMarketDisplay,
|
|
17
19
|
unknownToDecimalString,
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
import {
|
|
24
26
|
type AccountSummary,
|
|
25
27
|
type Fill,
|
|
28
|
+
type Market,
|
|
26
29
|
type MarketContext,
|
|
27
30
|
PerpsErrorCode,
|
|
28
31
|
type Position,
|
|
@@ -172,6 +175,57 @@ export interface LighterWsProviderOptions {
|
|
|
172
175
|
resolveAuthToken?: LighterAuthTokenResolver
|
|
173
176
|
}
|
|
174
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Perps equity plus the USD value of every positive held balance. A non-
|
|
180
|
+
* settlement asset counts its spot and margin routes; the settlement asset
|
|
181
|
+
* counts its spot route only, because the equity already holds its margin.
|
|
182
|
+
*
|
|
183
|
+
* @throws {PerpsError} `SDKError` when a held asset's spot mark does not
|
|
184
|
+
* match the decimal pattern.
|
|
185
|
+
*/
|
|
186
|
+
const heldPortfolioValue = (
|
|
187
|
+
perpsEquity: string,
|
|
188
|
+
balances: ReadonlyMap<number, { spot: string; margin: string }>,
|
|
189
|
+
settlementAssetIndex: number,
|
|
190
|
+
markets: readonly Market[],
|
|
191
|
+
contexts: readonly MarketContext[]
|
|
192
|
+
): string => {
|
|
193
|
+
const held = [...balances]
|
|
194
|
+
.map(
|
|
195
|
+
([assetId, { spot, margin }]) =>
|
|
196
|
+
[
|
|
197
|
+
assetId,
|
|
198
|
+
assetId === settlementAssetIndex
|
|
199
|
+
? spot
|
|
200
|
+
: addDecimalString(spot, margin),
|
|
201
|
+
] as const
|
|
202
|
+
)
|
|
203
|
+
.filter(([, balance]) => isDecimalStringGreaterThan(balance, '0'))
|
|
204
|
+
const spotPrices = spotPriceByAssetId(
|
|
205
|
+
markets,
|
|
206
|
+
LIGHTER_SPOT_CATEGORY_ID,
|
|
207
|
+
contexts,
|
|
208
|
+
new Set(
|
|
209
|
+
held
|
|
210
|
+
.filter(([assetId]) => assetId !== settlementAssetIndex)
|
|
211
|
+
.map(([assetId]) => String(assetId))
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
return lighterPortfolioValue(
|
|
215
|
+
perpsEquity,
|
|
216
|
+
held.map(
|
|
217
|
+
([assetId, balance]) =>
|
|
218
|
+
spotValuation(assetId, balance, settlementAssetIndex, spotPrices)
|
|
219
|
+
.valueUsd
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const safeHeldPortfolioValue = createSafeFunction(
|
|
225
|
+
'heldPortfolioValue',
|
|
226
|
+
heldPortfolioValue
|
|
227
|
+
)
|
|
228
|
+
|
|
175
229
|
/**
|
|
176
230
|
* Lighter WebSocket provider (extends {@link WsProviderBase}): subscribes to
|
|
177
231
|
* Lighter's WS channels (orderbook, marketsContext, orders, positions), attaching auth
|
|
@@ -723,47 +777,53 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
723
777
|
return
|
|
724
778
|
}
|
|
725
779
|
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
)
|
|
731
|
-
const collateral = unknownToDecimalString(
|
|
732
|
-
stats.collateral,
|
|
733
|
-
'stats.collateral',
|
|
734
|
-
this.providerKey
|
|
735
|
-
)
|
|
780
|
+
const read = (value: unknown, field: string): string | undefined =>
|
|
781
|
+
safeUnknownToDecimalString(value, field, this.providerKey)
|
|
782
|
+
const portfolio = read(stats.portfolio_value, 'stats.portfolio_value')
|
|
783
|
+
const collateral = read(stats.collateral, 'stats.collateral')
|
|
736
784
|
|
|
737
|
-
let available: string
|
|
738
|
-
let marginUsed: string
|
|
785
|
+
let available: string | undefined
|
|
786
|
+
let marginUsed: string | undefined
|
|
739
787
|
if (stats.cross_stats === undefined) {
|
|
740
788
|
// Compatibility with legacy gateways that omitted the entire
|
|
741
789
|
// cross_stats object.
|
|
742
|
-
available =
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
marginUsed = subtractDecimalString(portfolio, available)
|
|
790
|
+
available = read(stats.available_balance, 'stats.available_balance')
|
|
791
|
+
marginUsed =
|
|
792
|
+
portfolio === undefined || available === undefined
|
|
793
|
+
? undefined
|
|
794
|
+
: subtractDecimalString(portfolio, available)
|
|
748
795
|
} else {
|
|
749
|
-
const crossCollateral =
|
|
796
|
+
const crossCollateral = read(
|
|
750
797
|
stats.cross_stats.collateral,
|
|
751
|
-
'stats.cross_stats.collateral'
|
|
752
|
-
this.providerKey
|
|
798
|
+
'stats.cross_stats.collateral'
|
|
753
799
|
)
|
|
754
|
-
const crossPortfolio =
|
|
800
|
+
const crossPortfolio = read(
|
|
755
801
|
stats.cross_stats.portfolio_value,
|
|
756
|
-
'stats.cross_stats.portfolio_value'
|
|
757
|
-
this.providerKey
|
|
802
|
+
'stats.cross_stats.portfolio_value'
|
|
758
803
|
)
|
|
759
|
-
available =
|
|
804
|
+
available = read(
|
|
760
805
|
stats.cross_stats.available_balance,
|
|
761
|
-
'stats.cross_stats.available_balance'
|
|
762
|
-
this.providerKey
|
|
806
|
+
'stats.cross_stats.available_balance'
|
|
763
807
|
)
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
808
|
+
marginUsed =
|
|
809
|
+
collateral === undefined ||
|
|
810
|
+
crossCollateral === undefined ||
|
|
811
|
+
crossPortfolio === undefined ||
|
|
812
|
+
available === undefined
|
|
813
|
+
? undefined
|
|
814
|
+
: addDecimalString(
|
|
815
|
+
subtractDecimalString(collateral, crossCollateral),
|
|
816
|
+
subtractDecimalString(crossPortfolio, available)
|
|
817
|
+
)
|
|
818
|
+
}
|
|
819
|
+
// Every AccountSummary field is required, so the last summary stays.
|
|
820
|
+
if (
|
|
821
|
+
portfolio === undefined ||
|
|
822
|
+
collateral === undefined ||
|
|
823
|
+
available === undefined ||
|
|
824
|
+
marginUsed === undefined
|
|
825
|
+
) {
|
|
826
|
+
return
|
|
767
827
|
}
|
|
768
828
|
|
|
769
829
|
const inputs = this.accountSummaryInputs.get(address)
|
|
@@ -827,36 +887,16 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
827
887
|
if (inputs?.perps === undefined || inputs.balances === undefined) {
|
|
828
888
|
return
|
|
829
889
|
}
|
|
830
|
-
const
|
|
831
|
-
const held = [...inputs.balances]
|
|
832
|
-
.map(
|
|
833
|
-
([assetId, { spot, margin }]) =>
|
|
834
|
-
[
|
|
835
|
-
assetId,
|
|
836
|
-
assetId === settlementAssetIndex
|
|
837
|
-
? spot
|
|
838
|
-
: addDecimalString(spot, margin),
|
|
839
|
-
] as const
|
|
840
|
-
)
|
|
841
|
-
.filter(([, balance]) => isDecimalStringGreaterThan(balance, '0'))
|
|
842
|
-
const spotPrices = spotPriceByAssetId(
|
|
843
|
-
this.registry?.markets ?? [],
|
|
844
|
-
LIGHTER_SPOT_CATEGORY_ID,
|
|
845
|
-
Object.values(this.marketsContext),
|
|
846
|
-
new Set(
|
|
847
|
-
held
|
|
848
|
-
.filter(([assetId]) => assetId !== settlementAssetIndex)
|
|
849
|
-
.map(([assetId]) => String(assetId))
|
|
850
|
-
)
|
|
851
|
-
)
|
|
852
|
-
const portfolioValue = lighterPortfolioValue(
|
|
890
|
+
const portfolioValue = safeHeldPortfolioValue(
|
|
853
891
|
inputs.perps.equity,
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
)
|
|
892
|
+
inputs.balances,
|
|
893
|
+
this.settlementAssetIndex(),
|
|
894
|
+
this.registry?.markets ?? [],
|
|
895
|
+
Object.values(this.marketsContext)
|
|
859
896
|
)
|
|
897
|
+
if (portfolioValue === undefined) {
|
|
898
|
+
return
|
|
899
|
+
}
|
|
860
900
|
if (onlyOnChange && portfolioValue === inputs.lastPortfolioValue) {
|
|
861
901
|
return
|
|
862
902
|
}
|
|
@@ -1017,8 +1057,8 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
1017
1057
|
let state = this.orderbooks.get(marketId)
|
|
1018
1058
|
if (!state || isSnapshot) {
|
|
1019
1059
|
state = {
|
|
1020
|
-
bids: new OrderBookSide(bidOrder, this.providerKey),
|
|
1021
|
-
asks: new OrderBookSide(askOrder, this.providerKey),
|
|
1060
|
+
bids: new OrderBookSide(bidOrder, this.providerKey, assetId),
|
|
1061
|
+
asks: new OrderBookSide(askOrder, this.providerKey, assetId),
|
|
1022
1062
|
assetId,
|
|
1023
1063
|
}
|
|
1024
1064
|
this.orderbooks.set(marketId, state)
|
|
@@ -9,7 +9,7 @@ import type { LtWsOrderBook } from '../types/index.js'
|
|
|
9
9
|
/**
|
|
10
10
|
* Orders two decimal-string prices: a negative result puts `a` before `b`.
|
|
11
11
|
*
|
|
12
|
-
* @throws {PerpsError} `ValidationError` when a price
|
|
12
|
+
* @throws {PerpsError} `ValidationError` when a price does not match the decimal pattern.
|
|
13
13
|
*/
|
|
14
14
|
export type PriceOrder = (a: string, b: string) => number
|
|
15
15
|
|
|
@@ -31,7 +31,8 @@ export class OrderBookSide {
|
|
|
31
31
|
|
|
32
32
|
constructor(
|
|
33
33
|
private readonly order: PriceOrder,
|
|
34
|
-
private readonly providerKey: string
|
|
34
|
+
private readonly providerKey: string,
|
|
35
|
+
private readonly marketId: string
|
|
35
36
|
) {}
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -42,11 +43,23 @@ export class OrderBookSide {
|
|
|
42
43
|
apply(updates: LtWsOrderBook['bids']): void {
|
|
43
44
|
for (const { price, size } of updates) {
|
|
44
45
|
if (!isDecimalString(price)) {
|
|
45
|
-
wsLog.skippedRow(
|
|
46
|
+
wsLog.skippedRow(
|
|
47
|
+
this.providerKey,
|
|
48
|
+
'order book level',
|
|
49
|
+
'price',
|
|
50
|
+
price,
|
|
51
|
+
this.marketId
|
|
52
|
+
)
|
|
46
53
|
continue
|
|
47
54
|
}
|
|
48
55
|
if (!isDecimalString(size)) {
|
|
49
|
-
wsLog.skippedRow(
|
|
56
|
+
wsLog.skippedRow(
|
|
57
|
+
this.providerKey,
|
|
58
|
+
'order book level',
|
|
59
|
+
'size',
|
|
60
|
+
size,
|
|
61
|
+
this.marketId
|
|
62
|
+
)
|
|
50
63
|
this.remove(price)
|
|
51
64
|
continue
|
|
52
65
|
}
|