@icgio/icg-exchanges-wrapper 1.21.20 → 1.21.22

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.
@@ -156,11 +156,12 @@ const get_exchanges_rates = function (Exchanges, exchange_pair_dict, cb, ws_enab
156
156
  ws_promise_with_fallback = ws_connection_promises_with_fallback[ws_key]
157
157
  }
158
158
  } else {
159
- // Create new WebSocket connection
160
- // Log only when actually creating a new connection
161
- if (all_pairs.length > 0) {
162
- console.log(`[WebSocket Rates] ${Exchange_name}: Creating connection with ${all_pairs.length} pair(s): ${all_pairs.join(', ')}`)
163
- }
159
+ // Re-enter this branch every poll (we no longer cache ws_promise below) so
160
+ // a fresh rate_ws cycle runs against the live asks_dict/bids_dict each time.
161
+ // `first_time[Exchange_name]` gates the actual ws_market call so the WS is
162
+ // set up exactly once per process the "Creating connection" log lives
163
+ // inside that gate so it only fires on the genuine one-shot setup, not on
164
+ // every 30s poll.
164
165
  ws_connection_pairs[ws_key] = all_pairs
165
166
  ws_promise = new Promise((resolve, reject) => {
166
167
  if (!Exchange.ws || !Exchange.ws.market) {
@@ -169,9 +170,13 @@ const get_exchanges_rates = function (Exchanges, exchange_pair_dict, cb, ws_enab
169
170
  return
170
171
  }
171
172
 
172
- // Create WebSocket with ALL pairs collected in first pass
173
- // This ensures only ONE WebSocket per exchange, even with multiple clients/pairs
174
- Exchange.ws_market(all_pairs)
173
+ if (!first_time[Exchange_name]) {
174
+ if (all_pairs.length > 0) {
175
+ console.log(`[WebSocket Rates] ${Exchange_name}: Creating connection with ${all_pairs.length} pair(s): ${all_pairs.join(', ')}`)
176
+ }
177
+ Exchange.ws_market(all_pairs)
178
+ first_time[Exchange_name] = true
179
+ }
175
180
 
176
181
  const WS_TIMEOUT_MS = 30000 // 30 seconds timeout
177
182
  const MAX_CHECKS = 300 // 30 seconds / 100ms
@@ -316,12 +321,16 @@ const get_exchanges_rates = function (Exchanges, exchange_pair_dict, cb, ws_enab
316
321
 
317
322
  check_status()
318
323
  })
319
- // Store the cached promise AFTER `new Promise(...)` returns assigning inside
320
- // the synchronous executor reads the outer binding while it's still undefined.
321
- // Keep the entry alive while the socket is alive; the next tick's
322
- // `is_opening_or_opened` check reads `Exchange.ws.market.status` and the
323
- // else-branch above overwrites this slot when the socket is closed/stopped.
324
- ws_connection_promises[ws_key] = ws_promise
324
+ // Do NOT cache this promise. `Exchange.rate_ws(pair, cb)` returns a SNAPSHOT
325
+ // of `asks_dict[pair]`/`bids_dict[pair]` at call time for exchanges using
326
+ // ordered_dict (e.g. Bybit) `.entries().map(...)` creates a new array, and
327
+ // for exchanges using a plain-array depth (e.g. Mexc) every depth message
328
+ // REPLACES the array reference. Either way the result is frozen once the
329
+ // promise resolves. Rerunning the else branch each poll lets a new rate_ws
330
+ // call pick up changes the WebSocket has applied since last tick;
331
+ // `first_time[Exchange_name]` above prevents the underlying WS from being
332
+ // reopened, so there's no reconnect cost. Mirrors v1.17.27 (f815363) which
333
+ // fixed the same bug for get_exchanges_market_history.
325
334
  }
326
335
 
327
336
  // Wrap WebSocket promise to handle rejection and fall back to REST
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icgio/icg-exchanges-wrapper",
3
- "version": "1.21.20",
3
+ "version": "1.21.22",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {