@stryke-xyz/premarket-sdk 1.2.8 → 1.2.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.
@@ -1 +1 @@
1
- {"name":"@stryke-xyz/premarket-sdk","version":"1.2.7","type":"commonjs"}
1
+ {"name":"@stryke-xyz/premarket-sdk","version":"1.2.10","type":"commonjs"}
@@ -315,12 +315,41 @@ function _object_spread(target) {
315
315
  {
316
316
  key: "handleMessage",
317
317
  value: function handleMessage(ev) {
318
- var msg;
318
+ var parsed;
319
319
  try {
320
- msg = JSON.parse(ev.data);
320
+ parsed = JSON.parse(ev.data);
321
321
  } catch (unused) {
322
322
  return;
323
323
  }
324
+ // Support both single object and batched array (from the 5ms WS batcher).
325
+ var messages = Array.isArray(parsed) ? parsed : [
326
+ parsed
327
+ ];
328
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
329
+ try {
330
+ for(var _iterator = messages[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
331
+ var msg = _step.value;
332
+ this.dispatchMessage(msg);
333
+ }
334
+ } catch (err) {
335
+ _didIteratorError = true;
336
+ _iteratorError = err;
337
+ } finally{
338
+ try {
339
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
340
+ _iterator.return();
341
+ }
342
+ } finally{
343
+ if (_didIteratorError) {
344
+ throw _iteratorError;
345
+ }
346
+ }
347
+ }
348
+ }
349
+ },
350
+ {
351
+ key: "dispatchMessage",
352
+ value: function dispatchMessage(msg) {
324
353
  var type = msg.type;
325
354
  if (type === "pong") {
326
355
  this.clearHeartbeatTimeout();
@@ -345,7 +374,7 @@ function _object_spread(target) {
345
374
  /* noop */ return;
346
375
  }
347
376
  if (type === "fill" || type === "order_update") {
348
- var _$ev = _object_spread({
377
+ var ev = _object_spread({
349
378
  type: type,
350
379
  orderHash: msg.orderHash,
351
380
  marketId: msg.marketId,
@@ -359,7 +388,7 @@ function _object_spread(target) {
359
388
  var cbs = _step.value;
360
389
  cbs.forEach(function(cb) {
361
390
  try {
362
- cb(_$ev);
391
+ cb(ev);
363
392
  } catch (unused) {}
364
393
  });
365
394
  }
@@ -257,7 +257,7 @@ function normalizePrice(price) {
257
257
  if (isNaN(num)) return price;
258
258
  return num.toString();
259
259
  }
260
- /** A market + its token IDs to subscribe to. */ /** Current depth state for a token within a market subscription. */ /** One bid or ask level change in the normalized SDK format. */ /** Raw level shape inside the wire `depth_update.levels[]` array. */ /** Raw `depth_update` frame as published by the depth projector. */ /** Consolidated depth update emitted to SDK listeners after normalization. */ /** Last applied executor sequenceId for this token (== endSeq of the frame). */ /** Range covered by this frame; clients can detect gaps via startSeq != prevSeq + 1. */ /**
260
+ /** A market + its token IDs to subscribe to. */ /** Current depth state for a token within a market subscription. */ /** ms epoch when lastPrice was set on the server, or null if unknown. */ /** One bid or ask level change in the normalized SDK format. */ /** Raw level shape inside the wire `depth_update.levels[]` array. */ /** Raw `depth_update` frame as published by the depth projector. */ /** Consolidated depth update emitted to SDK listeners after normalization. */ /** ms epoch when lastPrice was set on the server, or null if unknown. */ /** Last applied executor sequenceId for this token (== endSeq of the frame). */ /** Range covered by this frame; clients can detect gaps via startSeq != prevSeq + 1. */ /**
261
261
  * Configuration for the market depth websocket client.
262
262
  *
263
263
  * Supports multiple markets over a single WebSocket connection.
@@ -309,6 +309,7 @@ function normalizePrice(price) {
309
309
  _define_property(this, "statusListeners", new Set());
310
310
  _define_property(this, "snapshotListeners", new Set());
311
311
  _define_property(this, "deltaListeners", new Set());
312
+ _define_property(this, "lastPriceListeners", new Set());
312
313
  // Reconnection state
313
314
  _define_property(this, "shouldBeConnected", false);
314
315
  _define_property(this, "reconnectAttempts", 0);
@@ -696,6 +697,23 @@ function normalizePrice(price) {
696
697
  };
697
698
  }
698
699
  },
700
+ {
701
+ /**
702
+ * Subscribe to actual executor fill prices emitted by the depth projector's
703
+ * dedicated `last_price` WS message. Fires once per fill price in each flush
704
+ * window — does NOT fire for bid/ask-only market_state updates.
705
+ *
706
+ * @param listener Called with (marketId, tokenId, price, at) for each fill.
707
+ * @returns Unsubscribe function.
708
+ */ key: "onLastPrice",
709
+ value: function onLastPrice(listener) {
710
+ var _this = this;
711
+ this.lastPriceListeners.add(listener);
712
+ return function() {
713
+ return _this.lastPriceListeners.delete(listener);
714
+ };
715
+ }
716
+ },
699
717
  {
700
718
  key: "onStatus",
701
719
  value: function onStatus(listener) {
@@ -756,12 +774,16 @@ function normalizePrice(price) {
756
774
  try {
757
775
  for(var _iterator = snapshots[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
758
776
  var snapshot = _step.value;
777
+ var _snapshot_bestBidAt, _snapshot_bestAskAt, _snapshot_lastPriceAt;
759
778
  var state = {
760
779
  bids: new Map(),
761
780
  asks: new Map(),
762
781
  bestBid: snapshot.bestBid,
763
782
  bestAsk: snapshot.bestAsk,
783
+ bestBidAt: (_snapshot_bestBidAt = snapshot.bestBidAt) !== null && _snapshot_bestBidAt !== void 0 ? _snapshot_bestBidAt : null,
784
+ bestAskAt: (_snapshot_bestAskAt = snapshot.bestAskAt) !== null && _snapshot_bestAskAt !== void 0 ? _snapshot_bestAskAt : null,
764
785
  lastPrice: snapshot.lastPrice,
786
+ lastPriceAt: (_snapshot_lastPriceAt = snapshot.lastPriceAt) !== null && _snapshot_lastPriceAt !== void 0 ? _snapshot_lastPriceAt : null,
765
787
  seq: snapshot.seq
766
788
  };
767
789
  var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
@@ -857,24 +879,80 @@ function normalizePrice(price) {
857
879
  {
858
880
  key: "handleMarketStateUpdate",
859
881
  value: function handleMarketStateUpdate(msg) {
860
- var _msg_bestBid, _msg_bestAsk, _msg_lastPrice;
861
882
  var state = this.tokenStates.get(String(msg.tokenId));
862
883
  if (!state) return;
863
- state.bestBid = (_msg_bestBid = msg.bestBid) !== null && _msg_bestBid !== void 0 ? _msg_bestBid : state.bestBid;
864
- state.bestAsk = (_msg_bestAsk = msg.bestAsk) !== null && _msg_bestAsk !== void 0 ? _msg_bestAsk : state.bestAsk;
865
- state.lastPrice = (_msg_lastPrice = msg.lastPrice) !== null && _msg_lastPrice !== void 0 ? _msg_lastPrice : state.lastPrice;
884
+ if (msg.bestBid != null) {
885
+ var _msg_bestBidAt;
886
+ state.bestBid = msg.bestBid;
887
+ state.bestBidAt = (_msg_bestBidAt = msg.bestBidAt) !== null && _msg_bestBidAt !== void 0 ? _msg_bestBidAt : state.bestBidAt;
888
+ }
889
+ if (msg.bestAsk != null) {
890
+ var _msg_bestAskAt;
891
+ state.bestAsk = msg.bestAsk;
892
+ state.bestAskAt = (_msg_bestAskAt = msg.bestAskAt) !== null && _msg_bestAskAt !== void 0 ? _msg_bestAskAt : state.bestAskAt;
893
+ }
894
+ if (msg.lastPrice != null) {
895
+ var _msg_lastPriceAt;
896
+ state.lastPrice = msg.lastPrice;
897
+ state.lastPriceAt = (_msg_lastPriceAt = msg.lastPriceAt) !== null && _msg_lastPriceAt !== void 0 ? _msg_lastPriceAt : state.lastPriceAt;
898
+ }
866
899
  this.emitOutOfBandUpdate(msg.marketId, msg.tokenId, state);
867
900
  }
868
901
  },
869
902
  {
870
903
  key: "handleLastPriceUpdate",
871
- value: function handleLastPriceUpdate(msg) {
904
+ value: function handleLastPriceUpdate(msg) /** New batched format: all fill prices in this flush window. */ /** Legacy single-price format. */ {
872
905
  var _ref, _msg_marketId;
873
906
  var state = this.tokenStates.get(String(msg.tokenId));
874
907
  if (!state) return;
875
- state.lastPrice = msg.lastPrice;
876
908
  var marketId = (_ref = (_msg_marketId = msg.marketId) !== null && _msg_marketId !== void 0 ? _msg_marketId : this.tokenToMarket.get(msg.tokenId)) !== null && _ref !== void 0 ? _ref : "";
877
- this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
909
+ if (msg.prices && msg.prices.length > 0) {
910
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
911
+ try {
912
+ var _this, _loop = function() {
913
+ var entry = _step.value;
914
+ state.lastPrice = entry.price;
915
+ state.lastPriceAt = entry.at;
916
+ _this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
917
+ _this.lastPriceListeners.forEach(function(listener) {
918
+ try {
919
+ listener(marketId, msg.tokenId, entry.price, entry.at);
920
+ } catch (e) {
921
+ console.error(e);
922
+ }
923
+ });
924
+ };
925
+ // Emit one DepthUpdate per price so listeners see every fill price.
926
+ for(var _iterator = msg.prices[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_this = this, _loop();
927
+ } catch (err) {
928
+ _didIteratorError = true;
929
+ _iteratorError = err;
930
+ } finally{
931
+ try {
932
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
933
+ _iterator.return();
934
+ }
935
+ } finally{
936
+ if (_didIteratorError) {
937
+ throw _iteratorError;
938
+ }
939
+ }
940
+ }
941
+ } else if (msg.lastPrice != null) {
942
+ var _msg_lastPriceAt, _ref1, _msg_lastPriceAt1;
943
+ // Legacy single-price fallback.
944
+ state.lastPrice = msg.lastPrice;
945
+ state.lastPriceAt = (_msg_lastPriceAt = msg.lastPriceAt) !== null && _msg_lastPriceAt !== void 0 ? _msg_lastPriceAt : state.lastPriceAt;
946
+ this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
947
+ var at = (_ref1 = (_msg_lastPriceAt1 = msg.lastPriceAt) !== null && _msg_lastPriceAt1 !== void 0 ? _msg_lastPriceAt1 : state.lastPriceAt) !== null && _ref1 !== void 0 ? _ref1 : Date.now();
948
+ this.lastPriceListeners.forEach(function(listener) {
949
+ try {
950
+ listener(marketId, msg.tokenId, msg.lastPrice, at);
951
+ } catch (e) {
952
+ console.error(e);
953
+ }
954
+ });
955
+ }
878
956
  }
879
957
  },
880
958
  {
@@ -885,7 +963,10 @@ function normalizePrice(price) {
885
963
  levels: [],
886
964
  bestBid: state.bestBid,
887
965
  bestAsk: state.bestAsk,
966
+ bestBidAt: state.bestBidAt,
967
+ bestAskAt: state.bestAskAt,
888
968
  lastPrice: state.lastPrice,
969
+ lastPriceAt: state.lastPriceAt,
889
970
  seq: state.seq,
890
971
  startSeq: state.seq,
891
972
  endSeq: state.seq
@@ -970,7 +1051,10 @@ function normalizePrice(price) {
970
1051
  levels: emittedLevels,
971
1052
  bestBid: state.bestBid,
972
1053
  bestAsk: state.bestAsk,
1054
+ bestBidAt: state.bestBidAt,
1055
+ bestAskAt: state.bestAskAt,
973
1056
  lastPrice: state.lastPrice,
1057
+ lastPriceAt: state.lastPriceAt,
974
1058
  seq: state.seq,
975
1059
  startSeq: startSeq,
976
1060
  endSeq: endSeq
@@ -1 +1 @@
1
- {"name":"@stryke-xyz/premarket-sdk","version":"1.2.7","type":"module"}
1
+ {"name":"@stryke-xyz/premarket-sdk","version":"1.2.10","type":"module"}
@@ -305,12 +305,41 @@ function _object_spread(target) {
305
305
  {
306
306
  key: "handleMessage",
307
307
  value: function handleMessage(ev) {
308
- var msg;
308
+ var parsed;
309
309
  try {
310
- msg = JSON.parse(ev.data);
310
+ parsed = JSON.parse(ev.data);
311
311
  } catch (unused) {
312
312
  return;
313
313
  }
314
+ // Support both single object and batched array (from the 5ms WS batcher).
315
+ var messages = Array.isArray(parsed) ? parsed : [
316
+ parsed
317
+ ];
318
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
319
+ try {
320
+ for(var _iterator = messages[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
321
+ var msg = _step.value;
322
+ this.dispatchMessage(msg);
323
+ }
324
+ } catch (err) {
325
+ _didIteratorError = true;
326
+ _iteratorError = err;
327
+ } finally{
328
+ try {
329
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
330
+ _iterator.return();
331
+ }
332
+ } finally{
333
+ if (_didIteratorError) {
334
+ throw _iteratorError;
335
+ }
336
+ }
337
+ }
338
+ }
339
+ },
340
+ {
341
+ key: "dispatchMessage",
342
+ value: function dispatchMessage(msg) {
314
343
  var type = msg.type;
315
344
  if (type === "pong") {
316
345
  this.clearHeartbeatTimeout();
@@ -335,7 +364,7 @@ function _object_spread(target) {
335
364
  /* noop */ return;
336
365
  }
337
366
  if (type === "fill" || type === "order_update") {
338
- var _$ev = _object_spread({
367
+ var ev = _object_spread({
339
368
  type: type,
340
369
  orderHash: msg.orderHash,
341
370
  marketId: msg.marketId,
@@ -349,7 +378,7 @@ function _object_spread(target) {
349
378
  var cbs = _step.value;
350
379
  cbs.forEach(function(cb) {
351
380
  try {
352
- cb(_$ev);
381
+ cb(ev);
353
382
  } catch (unused) {}
354
383
  });
355
384
  }
@@ -247,7 +247,7 @@ function normalizePrice(price) {
247
247
  if (isNaN(num)) return price;
248
248
  return num.toString();
249
249
  }
250
- /** A market + its token IDs to subscribe to. */ /** Current depth state for a token within a market subscription. */ /** One bid or ask level change in the normalized SDK format. */ /** Raw level shape inside the wire `depth_update.levels[]` array. */ /** Raw `depth_update` frame as published by the depth projector. */ /** Consolidated depth update emitted to SDK listeners after normalization. */ /** Last applied executor sequenceId for this token (== endSeq of the frame). */ /** Range covered by this frame; clients can detect gaps via startSeq != prevSeq + 1. */ /**
250
+ /** A market + its token IDs to subscribe to. */ /** Current depth state for a token within a market subscription. */ /** ms epoch when lastPrice was set on the server, or null if unknown. */ /** One bid or ask level change in the normalized SDK format. */ /** Raw level shape inside the wire `depth_update.levels[]` array. */ /** Raw `depth_update` frame as published by the depth projector. */ /** Consolidated depth update emitted to SDK listeners after normalization. */ /** ms epoch when lastPrice was set on the server, or null if unknown. */ /** Last applied executor sequenceId for this token (== endSeq of the frame). */ /** Range covered by this frame; clients can detect gaps via startSeq != prevSeq + 1. */ /**
251
251
  * Configuration for the market depth websocket client.
252
252
  *
253
253
  * Supports multiple markets over a single WebSocket connection.
@@ -299,6 +299,7 @@ function normalizePrice(price) {
299
299
  _define_property(this, "statusListeners", new Set());
300
300
  _define_property(this, "snapshotListeners", new Set());
301
301
  _define_property(this, "deltaListeners", new Set());
302
+ _define_property(this, "lastPriceListeners", new Set());
302
303
  // Reconnection state
303
304
  _define_property(this, "shouldBeConnected", false);
304
305
  _define_property(this, "reconnectAttempts", 0);
@@ -686,6 +687,23 @@ function normalizePrice(price) {
686
687
  };
687
688
  }
688
689
  },
690
+ {
691
+ /**
692
+ * Subscribe to actual executor fill prices emitted by the depth projector's
693
+ * dedicated `last_price` WS message. Fires once per fill price in each flush
694
+ * window — does NOT fire for bid/ask-only market_state updates.
695
+ *
696
+ * @param listener Called with (marketId, tokenId, price, at) for each fill.
697
+ * @returns Unsubscribe function.
698
+ */ key: "onLastPrice",
699
+ value: function onLastPrice(listener) {
700
+ var _this = this;
701
+ this.lastPriceListeners.add(listener);
702
+ return function() {
703
+ return _this.lastPriceListeners.delete(listener);
704
+ };
705
+ }
706
+ },
689
707
  {
690
708
  key: "onStatus",
691
709
  value: function onStatus(listener) {
@@ -746,12 +764,16 @@ function normalizePrice(price) {
746
764
  try {
747
765
  for(var _iterator = snapshots[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
748
766
  var snapshot = _step.value;
767
+ var _snapshot_bestBidAt, _snapshot_bestAskAt, _snapshot_lastPriceAt;
749
768
  var state = {
750
769
  bids: new Map(),
751
770
  asks: new Map(),
752
771
  bestBid: snapshot.bestBid,
753
772
  bestAsk: snapshot.bestAsk,
773
+ bestBidAt: (_snapshot_bestBidAt = snapshot.bestBidAt) !== null && _snapshot_bestBidAt !== void 0 ? _snapshot_bestBidAt : null,
774
+ bestAskAt: (_snapshot_bestAskAt = snapshot.bestAskAt) !== null && _snapshot_bestAskAt !== void 0 ? _snapshot_bestAskAt : null,
754
775
  lastPrice: snapshot.lastPrice,
776
+ lastPriceAt: (_snapshot_lastPriceAt = snapshot.lastPriceAt) !== null && _snapshot_lastPriceAt !== void 0 ? _snapshot_lastPriceAt : null,
755
777
  seq: snapshot.seq
756
778
  };
757
779
  var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
@@ -847,24 +869,80 @@ function normalizePrice(price) {
847
869
  {
848
870
  key: "handleMarketStateUpdate",
849
871
  value: function handleMarketStateUpdate(msg) {
850
- var _msg_bestBid, _msg_bestAsk, _msg_lastPrice;
851
872
  var state = this.tokenStates.get(String(msg.tokenId));
852
873
  if (!state) return;
853
- state.bestBid = (_msg_bestBid = msg.bestBid) !== null && _msg_bestBid !== void 0 ? _msg_bestBid : state.bestBid;
854
- state.bestAsk = (_msg_bestAsk = msg.bestAsk) !== null && _msg_bestAsk !== void 0 ? _msg_bestAsk : state.bestAsk;
855
- state.lastPrice = (_msg_lastPrice = msg.lastPrice) !== null && _msg_lastPrice !== void 0 ? _msg_lastPrice : state.lastPrice;
874
+ if (msg.bestBid != null) {
875
+ var _msg_bestBidAt;
876
+ state.bestBid = msg.bestBid;
877
+ state.bestBidAt = (_msg_bestBidAt = msg.bestBidAt) !== null && _msg_bestBidAt !== void 0 ? _msg_bestBidAt : state.bestBidAt;
878
+ }
879
+ if (msg.bestAsk != null) {
880
+ var _msg_bestAskAt;
881
+ state.bestAsk = msg.bestAsk;
882
+ state.bestAskAt = (_msg_bestAskAt = msg.bestAskAt) !== null && _msg_bestAskAt !== void 0 ? _msg_bestAskAt : state.bestAskAt;
883
+ }
884
+ if (msg.lastPrice != null) {
885
+ var _msg_lastPriceAt;
886
+ state.lastPrice = msg.lastPrice;
887
+ state.lastPriceAt = (_msg_lastPriceAt = msg.lastPriceAt) !== null && _msg_lastPriceAt !== void 0 ? _msg_lastPriceAt : state.lastPriceAt;
888
+ }
856
889
  this.emitOutOfBandUpdate(msg.marketId, msg.tokenId, state);
857
890
  }
858
891
  },
859
892
  {
860
893
  key: "handleLastPriceUpdate",
861
- value: function handleLastPriceUpdate(msg) {
894
+ value: function handleLastPriceUpdate(msg) /** New batched format: all fill prices in this flush window. */ /** Legacy single-price format. */ {
862
895
  var _ref, _msg_marketId;
863
896
  var state = this.tokenStates.get(String(msg.tokenId));
864
897
  if (!state) return;
865
- state.lastPrice = msg.lastPrice;
866
898
  var marketId = (_ref = (_msg_marketId = msg.marketId) !== null && _msg_marketId !== void 0 ? _msg_marketId : this.tokenToMarket.get(msg.tokenId)) !== null && _ref !== void 0 ? _ref : "";
867
- this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
899
+ if (msg.prices && msg.prices.length > 0) {
900
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
901
+ try {
902
+ var _this, _loop = function() {
903
+ var entry = _step.value;
904
+ state.lastPrice = entry.price;
905
+ state.lastPriceAt = entry.at;
906
+ _this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
907
+ _this.lastPriceListeners.forEach(function(listener) {
908
+ try {
909
+ listener(marketId, msg.tokenId, entry.price, entry.at);
910
+ } catch (e) {
911
+ console.error(e);
912
+ }
913
+ });
914
+ };
915
+ // Emit one DepthUpdate per price so listeners see every fill price.
916
+ for(var _iterator = msg.prices[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_this = this, _loop();
917
+ } catch (err) {
918
+ _didIteratorError = true;
919
+ _iteratorError = err;
920
+ } finally{
921
+ try {
922
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
923
+ _iterator.return();
924
+ }
925
+ } finally{
926
+ if (_didIteratorError) {
927
+ throw _iteratorError;
928
+ }
929
+ }
930
+ }
931
+ } else if (msg.lastPrice != null) {
932
+ var _msg_lastPriceAt, _ref1, _msg_lastPriceAt1;
933
+ // Legacy single-price fallback.
934
+ state.lastPrice = msg.lastPrice;
935
+ state.lastPriceAt = (_msg_lastPriceAt = msg.lastPriceAt) !== null && _msg_lastPriceAt !== void 0 ? _msg_lastPriceAt : state.lastPriceAt;
936
+ this.emitOutOfBandUpdate(marketId, msg.tokenId, state);
937
+ var at = (_ref1 = (_msg_lastPriceAt1 = msg.lastPriceAt) !== null && _msg_lastPriceAt1 !== void 0 ? _msg_lastPriceAt1 : state.lastPriceAt) !== null && _ref1 !== void 0 ? _ref1 : Date.now();
938
+ this.lastPriceListeners.forEach(function(listener) {
939
+ try {
940
+ listener(marketId, msg.tokenId, msg.lastPrice, at);
941
+ } catch (e) {
942
+ console.error(e);
943
+ }
944
+ });
945
+ }
868
946
  }
869
947
  },
870
948
  {
@@ -875,7 +953,10 @@ function normalizePrice(price) {
875
953
  levels: [],
876
954
  bestBid: state.bestBid,
877
955
  bestAsk: state.bestAsk,
956
+ bestBidAt: state.bestBidAt,
957
+ bestAskAt: state.bestAskAt,
878
958
  lastPrice: state.lastPrice,
959
+ lastPriceAt: state.lastPriceAt,
879
960
  seq: state.seq,
880
961
  startSeq: state.seq,
881
962
  endSeq: state.seq
@@ -960,7 +1041,10 @@ function normalizePrice(price) {
960
1041
  levels: emittedLevels,
961
1042
  bestBid: state.bestBid,
962
1043
  bestAsk: state.bestAsk,
1044
+ bestBidAt: state.bestBidAt,
1045
+ bestAskAt: state.bestAskAt,
963
1046
  lastPrice: state.lastPrice,
1047
+ lastPriceAt: state.lastPriceAt,
964
1048
  seq: state.seq,
965
1049
  startSeq: startSeq,
966
1050
  endSeq: endSeq
@@ -81,6 +81,7 @@ export declare class ActivitySyncClient {
81
81
  private send;
82
82
  private resubscribeAll;
83
83
  private handleMessage;
84
+ private dispatchMessage;
84
85
  private normalizeFill;
85
86
  private startHeartbeat;
86
87
  private stopHeartbeat;
@@ -15,7 +15,11 @@ export interface TokenDepthSnapshot {
15
15
  asks: DepthLevel[];
16
16
  bestBid: string | null;
17
17
  bestAsk: string | null;
18
+ bestBidAt: number | null;
19
+ bestAskAt: number | null;
18
20
  lastPrice: string | null;
21
+ /** ms epoch when lastPrice was set on the server, or null if unknown. */
22
+ lastPriceAt: number | null;
19
23
  seq: number;
20
24
  }
21
25
  /** One bid or ask level change in the normalized SDK format. */
@@ -30,7 +34,11 @@ export interface DepthUpdate {
30
34
  levels: DepthLevelUpdate[];
31
35
  bestBid: string | null;
32
36
  bestAsk: string | null;
37
+ bestBidAt: number | null;
38
+ bestAskAt: number | null;
33
39
  lastPrice: string | null;
40
+ /** ms epoch when lastPrice was set on the server, or null if unknown. */
41
+ lastPriceAt: number | null;
34
42
  /** Last applied executor sequenceId for this token (== endSeq of the frame). */
35
43
  seq: number;
36
44
  /** Range covered by this frame; clients can detect gaps via startSeq != prevSeq + 1. */
@@ -98,6 +106,7 @@ export declare class MarketDepthSyncClient {
98
106
  private statusListeners;
99
107
  private snapshotListeners;
100
108
  private deltaListeners;
109
+ private lastPriceListeners;
101
110
  private shouldBeConnected;
102
111
  private reconnectAttempts;
103
112
  private reconnectTimeoutId;
@@ -133,6 +142,15 @@ export declare class MarketDepthSyncClient {
133
142
  getLastPrice(tokenId: string): string | null;
134
143
  onSnapshot(listener: (marketId: string, snapshots: TokenDepthSnapshot[]) => void): () => void;
135
144
  onDelta(listener: (marketId: string, update: DepthUpdate) => void): () => void;
145
+ /**
146
+ * Subscribe to actual executor fill prices emitted by the depth projector's
147
+ * dedicated `last_price` WS message. Fires once per fill price in each flush
148
+ * window — does NOT fire for bid/ask-only market_state updates.
149
+ *
150
+ * @param listener Called with (marketId, tokenId, price, at) for each fill.
151
+ * @returns Unsubscribe function.
152
+ */
153
+ onLastPrice(listener: (marketId: string, tokenId: string, price: string, at: number) => void): () => void;
136
154
  onStatus(listener: (status: SyncStatus) => void): () => void;
137
155
  private _sendSubscribeMarket;
138
156
  private handleSubscribedMarket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stryke-xyz/premarket-sdk",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "type": "module",
5
5
  "module": "dist/esm/index.js",
6
6
  "main": "dist/cjs/index.js",