@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.
Files changed (103) hide show
  1. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  2. package/dist/cjs/LighterProvider.js +4 -6
  3. package/dist/cjs/LighterProvider.js.map +1 -1
  4. package/dist/cjs/accountSummary.d.ts.map +1 -1
  5. package/dist/cjs/accountSummary.js +13 -6
  6. package/dist/cjs/accountSummary.js.map +1 -1
  7. package/dist/cjs/utils/index.d.ts +1 -1
  8. package/dist/cjs/utils/index.d.ts.map +1 -1
  9. package/dist/cjs/utils/index.js +1 -3
  10. package/dist/cjs/utils/index.js.map +1 -1
  11. package/dist/cjs/utils/mapFill.js +1 -1
  12. package/dist/cjs/utils/mapFill.js.map +1 -1
  13. package/dist/cjs/utils/mapOpenPositions.d.ts +1 -2
  14. package/dist/cjs/utils/mapOpenPositions.d.ts.map +1 -1
  15. package/dist/cjs/utils/mapOpenPositions.js +1 -13
  16. package/dist/cjs/utils/mapOpenPositions.js.map +1 -1
  17. package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
  18. package/dist/cjs/utils/mapOrder.js +26 -43
  19. package/dist/cjs/utils/mapOrder.js.map +1 -1
  20. package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
  21. package/dist/cjs/utils/mapPosition.js +34 -16
  22. package/dist/cjs/utils/mapPosition.js.map +1 -1
  23. package/dist/cjs/utils/transferMargin.js +1 -1
  24. package/dist/cjs/utils/transferMargin.js.map +1 -1
  25. package/dist/cjs/utils/wireEncoding.d.ts +0 -2
  26. package/dist/cjs/utils/wireEncoding.d.ts.map +1 -1
  27. package/dist/cjs/utils/wireEncoding.js +1 -15
  28. package/dist/cjs/utils/wireEncoding.js.map +1 -1
  29. package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
  30. package/dist/cjs/websocket/LighterWsProvider.js +46 -26
  31. package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
  32. package/dist/cjs/websocket/orderBookSide.d.ts +2 -1
  33. package/dist/cjs/websocket/orderBookSide.d.ts.map +1 -1
  34. package/dist/cjs/websocket/orderBookSide.js +5 -3
  35. package/dist/cjs/websocket/orderBookSide.js.map +1 -1
  36. package/dist/esm/LighterProvider.d.ts.map +1 -1
  37. package/dist/esm/LighterProvider.js +5 -8
  38. package/dist/esm/LighterProvider.js.map +1 -1
  39. package/dist/esm/accountSummary.d.ts.map +1 -1
  40. package/dist/esm/accountSummary.js +14 -7
  41. package/dist/esm/accountSummary.js.map +1 -1
  42. package/dist/esm/utils/index.d.ts +1 -1
  43. package/dist/esm/utils/index.d.ts.map +1 -1
  44. package/dist/esm/utils/index.js +1 -1
  45. package/dist/esm/utils/index.js.map +1 -1
  46. package/dist/esm/utils/mapFill.js +1 -1
  47. package/dist/esm/utils/mapFill.js.map +1 -1
  48. package/dist/esm/utils/mapOpenPositions.d.ts +1 -8
  49. package/dist/esm/utils/mapOpenPositions.d.ts.map +1 -1
  50. package/dist/esm/utils/mapOpenPositions.js +1 -18
  51. package/dist/esm/utils/mapOpenPositions.js.map +1 -1
  52. package/dist/esm/utils/mapOrder.d.ts +6 -3
  53. package/dist/esm/utils/mapOrder.d.ts.map +1 -1
  54. package/dist/esm/utils/mapOrder.js +33 -47
  55. package/dist/esm/utils/mapOrder.js.map +1 -1
  56. package/dist/esm/utils/mapPortfolioHistory.d.ts +2 -2
  57. package/dist/esm/utils/mapPortfolioHistory.js +2 -2
  58. package/dist/esm/utils/mapPosition.d.ts +4 -3
  59. package/dist/esm/utils/mapPosition.d.ts.map +1 -1
  60. package/dist/esm/utils/mapPosition.js +39 -20
  61. package/dist/esm/utils/mapPosition.js.map +1 -1
  62. package/dist/esm/utils/transferMargin.js +1 -1
  63. package/dist/esm/utils/transferMargin.js.map +1 -1
  64. package/dist/esm/utils/wireEncoding.d.ts +2 -28
  65. package/dist/esm/utils/wireEncoding.d.ts.map +1 -1
  66. package/dist/esm/utils/wireEncoding.js +2 -38
  67. package/dist/esm/utils/wireEncoding.js.map +1 -1
  68. package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
  69. package/dist/esm/websocket/LighterWsProvider.js +56 -27
  70. package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
  71. package/dist/esm/websocket/orderBookSide.d.ts +3 -2
  72. package/dist/esm/websocket/orderBookSide.d.ts.map +1 -1
  73. package/dist/esm/websocket/orderBookSide.js +5 -3
  74. package/dist/esm/websocket/orderBookSide.js.map +1 -1
  75. package/dist/types/LighterProvider.d.ts.map +1 -1
  76. package/dist/types/accountSummary.d.ts.map +1 -1
  77. package/dist/types/utils/index.d.ts +1 -1
  78. package/dist/types/utils/index.d.ts.map +1 -1
  79. package/dist/types/utils/mapOpenPositions.d.ts +1 -8
  80. package/dist/types/utils/mapOpenPositions.d.ts.map +1 -1
  81. package/dist/types/utils/mapOrder.d.ts +6 -3
  82. package/dist/types/utils/mapOrder.d.ts.map +1 -1
  83. package/dist/types/utils/mapPortfolioHistory.d.ts +2 -2
  84. package/dist/types/utils/mapPosition.d.ts +4 -3
  85. package/dist/types/utils/mapPosition.d.ts.map +1 -1
  86. package/dist/types/utils/wireEncoding.d.ts +2 -28
  87. package/dist/types/utils/wireEncoding.d.ts.map +1 -1
  88. package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
  89. package/dist/types/websocket/orderBookSide.d.ts +3 -2
  90. package/dist/types/websocket/orderBookSide.d.ts.map +1 -1
  91. package/package.json +3 -3
  92. package/src/LighterProvider.ts +14 -16
  93. package/src/accountSummary.ts +27 -6
  94. package/src/utils/index.ts +0 -2
  95. package/src/utils/mapFill.ts +1 -1
  96. package/src/utils/mapOpenPositions.ts +2 -30
  97. package/src/utils/mapOrder.ts +46 -67
  98. package/src/utils/mapPortfolioHistory.ts +2 -2
  99. package/src/utils/mapPosition.ts +50 -23
  100. package/src/utils/transferMargin.ts +1 -1
  101. package/src/utils/wireEncoding.ts +2 -43
  102. package/src/websocket/LighterWsProvider.ts +100 -60
  103. package/src/websocket/orderBookSide.ts +17 -4
@@ -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 = (field: string, value: unknown): undefined => {
57
- warnSkippedVenueRow(LIGHTER_PROVIDER_KEY, 'position', field, value)
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 or value, or a non-positive initial margin fraction, gives
64
- * `undefined`: the mapper derives the size, mark price, margin and leverage
65
- * from them. Prices, PnL, funding and isolated margin pass through raw.
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
- if (!isDecimalString(pos.position_value)) {
77
- return skipPosition('position_value', pos.position_value)
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
- return skipPosition('initial_margin_fraction', imf)
104
+ warnUnreadableField('initial_margin_fraction', imf)
83
105
  }
84
- const isIsolated = pos.margin_mode === LT_MARGIN_MODE_ISOLATED
85
- const size = absDecimalString(pos.position)
86
- const positionValue = absDecimalString(pos.position_value)
87
- const initialMarginRequirement = divideDecimalString(
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
- markPrice:
98
- isDecimalStringZero(positionValue) || isDecimalStringZero(size)
99
- ? '0'
100
- : divideDecimalString(positionValue, size),
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 ? pos.allocated_margin : initialMarginRequirement,
106
- initialMarginRequirement,
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}' is not a decimal string.`
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: basis-point margin fractions and
3
- * order-type/time-in-force/expiry resolution mirroring lighter-go's rules.
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 portfolio = unknownToDecimalString(
727
- stats.portfolio_value,
728
- 'stats.portfolio_value',
729
- this.providerKey
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 = unknownToDecimalString(
743
- stats.available_balance,
744
- 'stats.available_balance',
745
- this.providerKey
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 = unknownToDecimalString(
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 = unknownToDecimalString(
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 = unknownToDecimalString(
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
- const isolatedMargin = subtractDecimalString(collateral, crossCollateral)
765
- const crossMargin = subtractDecimalString(crossPortfolio, available)
766
- marginUsed = addDecimalString(isolatedMargin, crossMargin)
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 settlementAssetIndex = this.settlementAssetIndex()
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
- held.map(
855
- ([assetId, balance]) =>
856
- spotValuation(assetId, balance, settlementAssetIndex, spotPrices)
857
- .valueUsd
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 is not a decimal string.
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(this.providerKey, 'order book level', 'price', price)
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(this.providerKey, 'order book level', 'size', size)
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
  }