starknet 10.6.6 → 10.6.7

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [10.6.7](https://github.com/starknet-io/starknet.js/compare/v10.6.6...v10.6.7) (2026-08-06)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **ws:** settle in-flight requests when the connection drops ([8eae9c9](https://github.com/starknet-io/starknet.js/commit/8eae9c9457befe6e0c3f4fd30a56025fe5455fd8))
6
+
1
7
  ## [10.6.6](https://github.com/starknet-io/starknet.js/compare/v10.6.5...v10.6.6) (2026-08-05)
2
8
 
3
9
  ### Bug Fixes
package/dist/index.d.ts CHANGED
@@ -5151,6 +5151,8 @@ declare class WebSocketChannel {
5151
5151
  private reconnectTimeoutId;
5152
5152
  private reconnectStabilityTimeoutId;
5153
5153
  private requestQueue;
5154
+ /** Abort handles for the requests currently on the wire, one per pending `sendReceive`. */
5155
+ private inFlight;
5154
5156
  private events;
5155
5157
  private openListener;
5156
5158
  private closeListener;
@@ -5253,6 +5255,15 @@ declare class WebSocketChannel {
5253
5255
  * could rescue them. Settling them here is the only way out.
5254
5256
  */
5255
5257
  private _rejectRequestQueue;
5258
+ /**
5259
+ * Settle every request already on the wire.
5260
+ *
5261
+ * The counterpart of `_rejectRequestQueue`, for requests past the queue. Their only other
5262
+ * exit is the `requestTimeout` timer, so without this the caller waits the whole timeout —
5263
+ * 60s by default — for a reply that can no longer arrive, and that pending timer keeps the
5264
+ * Node event loop alive for just as long.
5265
+ */
5266
+ private _rejectInFlight;
5256
5267
  private _restoreSubscriptions;
5257
5268
  /**
5258
5269
  * Reset the reconnection attempt counter, but only once the current connection has
@@ -12618,6 +12618,8 @@ ${indent}}` : "}";
12618
12618
  // resetting the reconnection attempt counter.
12619
12619
  reconnectStabilityTimeoutId = null;
12620
12620
  requestQueue = [];
12621
+ /** Abort handles for the requests currently on the wire, one per pending `sendReceive`. */
12622
+ inFlight = /* @__PURE__ */ new Set();
12621
12623
  events = new EventEmitter();
12622
12624
  openListener = (ev) => {
12623
12625
  this.scheduleReconnectAttemptsReset();
@@ -12701,12 +12703,19 @@ ${indent}}` : "}";
12701
12703
  });
12702
12704
  }
12703
12705
  const sendId = this.send(method, params);
12706
+ const socket = this.websocket;
12704
12707
  return new Promise((resolve, reject) => {
12705
- let timeoutId;
12706
- if (!this.websocket || this.websocket.readyState !== ws_default.OPEN) {
12708
+ if (socket.readyState !== ws_default.OPEN) {
12707
12709
  reject(new WebSocketNotConnectedError("WebSocket not available or not connected."));
12708
12710
  return;
12709
12711
  }
12712
+ let timeoutId;
12713
+ const settle = () => {
12714
+ clearTimeout(timeoutId);
12715
+ socket.removeEventListener("message", messageHandler);
12716
+ socket.removeEventListener("error", errorHandler);
12717
+ this.inFlight.delete(abort);
12718
+ };
12710
12719
  const messageHandler = (event) => {
12711
12720
  if (!isString(event.data)) {
12712
12721
  logger.warn("WebSocket received non-string message data:", event.data);
@@ -12721,34 +12730,35 @@ ${indent}}` : "}";
12721
12730
  );
12722
12731
  return;
12723
12732
  }
12724
- if (message.id === sendId) {
12725
- clearTimeout(timeoutId);
12726
- this.websocket.removeEventListener("message", messageHandler);
12727
- this.websocket.removeEventListener("error", errorHandler);
12728
- if ("result" in message) {
12729
- resolve(message.result);
12730
- } else {
12731
- reject(
12732
- new Error(`Error on ${method} (id: ${sendId}): ${JSON.stringify(message.error)}`)
12733
- );
12734
- }
12733
+ if (message.id !== sendId) return;
12734
+ settle();
12735
+ if ("result" in message) {
12736
+ resolve(message.result);
12737
+ } else {
12738
+ reject(new Error(`Error on ${method} (id: ${sendId}): ${JSON.stringify(message.error)}`));
12735
12739
  }
12736
12740
  };
12737
12741
  const errorHandler = (event) => {
12738
- clearTimeout(timeoutId);
12739
- this.websocket.removeEventListener("message", messageHandler);
12740
- this.websocket.removeEventListener("error", errorHandler);
12742
+ settle();
12741
12743
  reject(
12742
12744
  new Error(
12743
12745
  `WebSocket error during ${method} (id: ${sendId}): ${event.type || "Unknown error"}`
12744
12746
  )
12745
12747
  );
12746
12748
  };
12747
- this.websocket.addEventListener("message", messageHandler);
12748
- this.websocket.addEventListener("error", errorHandler);
12749
+ const abort = (reason) => {
12750
+ settle();
12751
+ reject(
12752
+ new WebSocketNotConnectedError(
12753
+ `Request ${method} (id: ${sendId}) went unanswered: ${reason}`
12754
+ )
12755
+ );
12756
+ };
12757
+ socket.addEventListener("message", messageHandler);
12758
+ socket.addEventListener("error", errorHandler);
12759
+ this.inFlight.add(abort);
12749
12760
  timeoutId = setTimeout(() => {
12750
- this.websocket.removeEventListener("message", messageHandler);
12751
- this.websocket.removeEventListener("error", errorHandler);
12761
+ settle();
12752
12762
  reject(
12753
12763
  new TimeoutError(
12754
12764
  `Request ${method} (id: ${sendId}) timed out after ${this.requestTimeout}ms`
@@ -12805,6 +12815,7 @@ ${indent}}` : "}";
12805
12815
  this.userInitiatedClose = true;
12806
12816
  this.isReconnecting = false;
12807
12817
  this._rejectRequestQueue("the connection was closed by the user");
12818
+ this._rejectInFlight("the connection was closed by the user");
12808
12819
  this.websocket.close(code, reason);
12809
12820
  }
12810
12821
  /**
@@ -12896,6 +12907,21 @@ ${indent}}` : "}";
12896
12907
  reject(new WebSocketNotConnectedError(`Request ${method} was never sent: ${reason}`));
12897
12908
  });
12898
12909
  }
12910
+ /**
12911
+ * Settle every request already on the wire.
12912
+ *
12913
+ * The counterpart of `_rejectRequestQueue`, for requests past the queue. Their only other
12914
+ * exit is the `requestTimeout` timer, so without this the caller waits the whole timeout —
12915
+ * 60s by default — for a reply that can no longer arrive, and that pending timer keeps the
12916
+ * Node event loop alive for just as long.
12917
+ */
12918
+ _rejectInFlight(reason) {
12919
+ if (this.inFlight.size === 0) return;
12920
+ const pending = Array.from(this.inFlight);
12921
+ this.inFlight.clear();
12922
+ logger.info(`WebSocket: Rejecting ${pending.length} in-flight request(s). Reason: ${reason}.`);
12923
+ pending.forEach((abort) => abort(reason));
12924
+ }
12899
12925
  async _restoreSubscriptions() {
12900
12926
  const oldSubscriptions = Array.from(this.activeSubscriptions.values());
12901
12927
  this.activeSubscriptions.clear();
@@ -12949,18 +12975,24 @@ ${indent}}` : "}";
12949
12975
  `WebSocket: Connection lost. Attempting to reconnect... (${this.reconnectAttempts}/${this.reconnectOptions.retries})`
12950
12976
  );
12951
12977
  this.reconnect();
12978
+ let attemptSettled = false;
12979
+ const scheduleRetry = () => {
12980
+ if (attemptSettled || !this.isReconnecting) return;
12981
+ attemptSettled = true;
12982
+ const delay = this.reconnectOptions.exponential ? this.reconnectOptions.delay * 2 ** (this.reconnectAttempts - 1) : this.reconnectOptions.delay;
12983
+ logger.info(`WebSocket: Reconnect attempt failed. Retrying in ${delay}ms.`);
12984
+ this.reconnectTimeoutId = setTimeout(tryReconnect, delay);
12985
+ };
12952
12986
  this.websocket.onopen = async () => {
12953
12987
  logger.info("WebSocket: Reconnection successful.");
12988
+ attemptSettled = true;
12954
12989
  this.isReconnecting = false;
12955
12990
  await this._restoreSubscriptions();
12956
12991
  this._processRequestQueue();
12957
12992
  this.events.emit("open", new Event("open"));
12958
12993
  };
12959
- this.websocket.onerror = () => {
12960
- const delay = this.reconnectOptions.exponential ? this.reconnectOptions.delay * 2 ** (this.reconnectAttempts - 1) : this.reconnectOptions.delay;
12961
- logger.info(`WebSocket: Reconnect attempt failed. Retrying in ${delay}ms.`);
12962
- this.reconnectTimeoutId = setTimeout(tryReconnect, delay);
12963
- };
12994
+ this.websocket.onerror = scheduleRetry;
12995
+ this.websocket.addEventListener("close", scheduleRetry);
12964
12996
  };
12965
12997
  tryReconnect();
12966
12998
  }
@@ -12969,6 +13001,7 @@ ${indent}}` : "}";
12969
13001
  this.websocket.removeEventListener("close", this.closeListener);
12970
13002
  this.websocket.removeEventListener("message", this.messageListener);
12971
13003
  this.websocket.removeEventListener("error", this.errorListener);
13004
+ this._rejectInFlight("the connection was closed");
12972
13005
  this.events.emit("close", ev);
12973
13006
  if (!this.userInitiatedClose) {
12974
13007
  this._startReconnect();