@solana/web3.js 1.41.1 → 1.41.2

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/lib/index.iife.js CHANGED
@@ -16446,6 +16446,82 @@ var solanaWeb3 = (function (exports) {
16446
16446
 
16447
16447
  var crossFetch = /*@__PURE__*/getDefaultExportFromCjs(browserPonyfill.exports);
16448
16448
 
16449
+ var objToString = Object.prototype.toString;
16450
+ var objKeys = Object.keys || function(obj) {
16451
+ var keys = [];
16452
+ for (var name in obj) {
16453
+ keys.push(name);
16454
+ }
16455
+ return keys;
16456
+ };
16457
+
16458
+ function stringify$1(val, isArrayProp) {
16459
+ var i, max, str, keys, key, propVal, toStr;
16460
+ if (val === true) {
16461
+ return "true";
16462
+ }
16463
+ if (val === false) {
16464
+ return "false";
16465
+ }
16466
+ switch (typeof val) {
16467
+ case "object":
16468
+ if (val === null) {
16469
+ return null;
16470
+ } else if (val.toJSON && typeof val.toJSON === "function") {
16471
+ return stringify$1(val.toJSON(), isArrayProp);
16472
+ } else {
16473
+ toStr = objToString.call(val);
16474
+ if (toStr === "[object Array]") {
16475
+ str = '[';
16476
+ max = val.length - 1;
16477
+ for(i = 0; i < max; i++) {
16478
+ str += stringify$1(val[i], true) + ',';
16479
+ }
16480
+ if (max > -1) {
16481
+ str += stringify$1(val[i], true);
16482
+ }
16483
+ return str + ']';
16484
+ } else if (toStr === "[object Object]") {
16485
+ // only object is left
16486
+ keys = objKeys(val).sort();
16487
+ max = keys.length;
16488
+ str = "";
16489
+ i = 0;
16490
+ while (i < max) {
16491
+ key = keys[i];
16492
+ propVal = stringify$1(val[key], false);
16493
+ if (propVal !== undefined) {
16494
+ if (str) {
16495
+ str += ',';
16496
+ }
16497
+ str += JSON.stringify(key) + ':' + propVal;
16498
+ }
16499
+ i++;
16500
+ }
16501
+ return '{' + str + '}';
16502
+ } else {
16503
+ return JSON.stringify(val);
16504
+ }
16505
+ }
16506
+ case "function":
16507
+ case "undefined":
16508
+ return isArrayProp ? null : undefined;
16509
+ case "string":
16510
+ return JSON.stringify(val);
16511
+ default:
16512
+ return isFinite(val) ? val : null;
16513
+ }
16514
+ }
16515
+
16516
+ var fastStableStringify = function(val) {
16517
+ var returnVal = stringify$1(val, false);
16518
+ if (returnVal !== undefined) {
16519
+ return ''+ returnVal;
16520
+ }
16521
+ };
16522
+
16523
+ var fastStableStringify$1 = fastStableStringify;
16524
+
16449
16525
  /**
16450
16526
  * A `StructFailure` represents a single specific failure in validation.
16451
16527
  */
@@ -17070,6 +17146,31 @@ var solanaWeb3 = (function (exports) {
17070
17146
  module.exports = _interopRequireDefault, module.exports.__esModule = true, module.exports["default"] = module.exports;
17071
17147
  }(interopRequireDefault));
17072
17148
 
17149
+ var createClass = {exports: {}};
17150
+
17151
+ (function (module) {
17152
+ function _defineProperties(target, props) {
17153
+ for (var i = 0; i < props.length; i++) {
17154
+ var descriptor = props[i];
17155
+ descriptor.enumerable = descriptor.enumerable || false;
17156
+ descriptor.configurable = true;
17157
+ if ("value" in descriptor) descriptor.writable = true;
17158
+ Object.defineProperty(target, descriptor.key, descriptor);
17159
+ }
17160
+ }
17161
+
17162
+ function _createClass(Constructor, protoProps, staticProps) {
17163
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
17164
+ if (staticProps) _defineProperties(Constructor, staticProps);
17165
+ Object.defineProperty(Constructor, "prototype", {
17166
+ writable: false
17167
+ });
17168
+ return Constructor;
17169
+ }
17170
+
17171
+ module.exports = _createClass, module.exports.__esModule = true, module.exports["default"] = module.exports;
17172
+ }(createClass));
17173
+
17073
17174
  var classCallCheck = {exports: {}};
17074
17175
 
17075
17176
  (function (module) {
@@ -17187,31 +17288,6 @@ var solanaWeb3 = (function (exports) {
17187
17288
 
17188
17289
  var websocket_browser = {};
17189
17290
 
17190
- var createClass = {exports: {}};
17191
-
17192
- (function (module) {
17193
- function _defineProperties(target, props) {
17194
- for (var i = 0; i < props.length; i++) {
17195
- var descriptor = props[i];
17196
- descriptor.enumerable = descriptor.enumerable || false;
17197
- descriptor.configurable = true;
17198
- if ("value" in descriptor) descriptor.writable = true;
17199
- Object.defineProperty(target, descriptor.key, descriptor);
17200
- }
17201
- }
17202
-
17203
- function _createClass(Constructor, protoProps, staticProps) {
17204
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
17205
- if (staticProps) _defineProperties(Constructor, staticProps);
17206
- Object.defineProperty(Constructor, "prototype", {
17207
- writable: false
17208
- });
17209
- return Constructor;
17210
- }
17211
-
17212
- module.exports = _createClass, module.exports.__esModule = true, module.exports["default"] = module.exports;
17213
- }(createClass));
17214
-
17215
17291
  var eventemitter3 = {exports: {}};
17216
17292
 
17217
17293
  (function (module) {
@@ -17580,7 +17656,7 @@ var solanaWeb3 = (function (exports) {
17580
17656
 
17581
17657
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
17582
17658
 
17583
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
17659
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
17584
17660
 
17585
17661
  var WebSocketBrowserImpl = /*#__PURE__*/function (_EventEmitter) {
17586
17662
  (0, _inherits2["default"])(WebSocketBrowserImpl, _EventEmitter);
@@ -18481,215 +18557,6 @@ var solanaWeb3 = (function (exports) {
18481
18557
  module.exports = _asyncToGenerator, module.exports.__esModule = true, module.exports["default"] = module.exports;
18482
18558
  }(asyncToGenerator));
18483
18559
 
18484
- /*!
18485
- Copyright (C) 2013-2017 by Andrea Giammarchi - @WebReflection
18486
-
18487
- Permission is hereby granted, free of charge, to any person obtaining a copy
18488
- of this software and associated documentation files (the "Software"), to deal
18489
- in the Software without restriction, including without limitation the rights
18490
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18491
- copies of the Software, and to permit persons to whom the Software is
18492
- furnished to do so, subject to the following conditions:
18493
-
18494
- The above copyright notice and this permission notice shall be included in
18495
- all copies or substantial portions of the Software.
18496
-
18497
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18498
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18499
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18500
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18501
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18502
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18503
- THE SOFTWARE.
18504
-
18505
- */
18506
-
18507
- var
18508
- // should be a not so common char
18509
- // possibly one JSON does not encode
18510
- // possibly one encodeURIComponent does not encode
18511
- // right now this char is '~' but this might change in the future
18512
- specialChar = '~',
18513
- safeSpecialChar = '\\x' + (
18514
- '0' + specialChar.charCodeAt(0).toString(16)
18515
- ).slice(-2),
18516
- escapedSafeSpecialChar = '\\' + safeSpecialChar,
18517
- specialCharRG = new RegExp(safeSpecialChar, 'g'),
18518
- safeSpecialCharRG = new RegExp(escapedSafeSpecialChar, 'g'),
18519
-
18520
- safeStartWithSpecialCharRG = new RegExp('(?:^|([^\\\\]))' + escapedSafeSpecialChar),
18521
-
18522
- indexOf = [].indexOf || function(v){
18523
- for(var i=this.length;i--&&this[i]!==v;);
18524
- return i;
18525
- },
18526
- $String = String // there's no way to drop warnings in JSHint
18527
- // about new String ... well, I need that here!
18528
- // faked, and happy linter!
18529
- ;
18530
-
18531
- function generateReplacer(value, replacer, resolve) {
18532
- var
18533
- doNotIgnore = false,
18534
- inspect = !!replacer,
18535
- path = [],
18536
- all = [value],
18537
- seen = [value],
18538
- mapp = [resolve ? specialChar : '[Circular]'],
18539
- last = value,
18540
- lvl = 1,
18541
- i, fn
18542
- ;
18543
- if (inspect) {
18544
- fn = typeof replacer === 'object' ?
18545
- function (key, value) {
18546
- return key !== '' && replacer.indexOf(key) < 0 ? void 0 : value;
18547
- } :
18548
- replacer;
18549
- }
18550
- return function(key, value) {
18551
- // the replacer has rights to decide
18552
- // if a new object should be returned
18553
- // or if there's some key to drop
18554
- // let's call it here rather than "too late"
18555
- if (inspect) value = fn.call(this, key, value);
18556
-
18557
- // first pass should be ignored, since it's just the initial object
18558
- if (doNotIgnore) {
18559
- if (last !== this) {
18560
- i = lvl - indexOf.call(all, this) - 1;
18561
- lvl -= i;
18562
- all.splice(lvl, all.length);
18563
- path.splice(lvl - 1, path.length);
18564
- last = this;
18565
- }
18566
- // console.log(lvl, key, path);
18567
- if (typeof value === 'object' && value) {
18568
- // if object isn't referring to parent object, add to the
18569
- // object path stack. Otherwise it is already there.
18570
- if (indexOf.call(all, value) < 0) {
18571
- all.push(last = value);
18572
- }
18573
- lvl = all.length;
18574
- i = indexOf.call(seen, value);
18575
- if (i < 0) {
18576
- i = seen.push(value) - 1;
18577
- if (resolve) {
18578
- // key cannot contain specialChar but could be not a string
18579
- path.push(('' + key).replace(specialCharRG, safeSpecialChar));
18580
- mapp[i] = specialChar + path.join(specialChar);
18581
- } else {
18582
- mapp[i] = mapp[0];
18583
- }
18584
- } else {
18585
- value = mapp[i];
18586
- }
18587
- } else {
18588
- if (typeof value === 'string' && resolve) {
18589
- // ensure no special char involved on deserialization
18590
- // in this case only first char is important
18591
- // no need to replace all value (better performance)
18592
- value = value .replace(safeSpecialChar, escapedSafeSpecialChar)
18593
- .replace(specialChar, safeSpecialChar);
18594
- }
18595
- }
18596
- } else {
18597
- doNotIgnore = true;
18598
- }
18599
- return value;
18600
- };
18601
- }
18602
-
18603
- function retrieveFromPath(current, keys) {
18604
- for(var i = 0, length = keys.length; i < length; current = current[
18605
- // keys should be normalized back here
18606
- keys[i++].replace(safeSpecialCharRG, specialChar)
18607
- ]);
18608
- return current;
18609
- }
18610
-
18611
- function generateReviver(reviver) {
18612
- return function(key, value) {
18613
- var isString = typeof value === 'string';
18614
- if (isString && value.charAt(0) === specialChar) {
18615
- return new $String(value.slice(1));
18616
- }
18617
- if (key === '') value = regenerate(value, value, {});
18618
- // again, only one needed, do not use the RegExp for this replacement
18619
- // only keys need the RegExp
18620
- if (isString) value = value .replace(safeStartWithSpecialCharRG, '$1' + specialChar)
18621
- .replace(escapedSafeSpecialChar, safeSpecialChar);
18622
- return reviver ? reviver.call(this, key, value) : value;
18623
- };
18624
- }
18625
-
18626
- function regenerateArray(root, current, retrieve) {
18627
- for (var i = 0, length = current.length; i < length; i++) {
18628
- current[i] = regenerate(root, current[i], retrieve);
18629
- }
18630
- return current;
18631
- }
18632
-
18633
- function regenerateObject(root, current, retrieve) {
18634
- for (var key in current) {
18635
- if (current.hasOwnProperty(key)) {
18636
- current[key] = regenerate(root, current[key], retrieve);
18637
- }
18638
- }
18639
- return current;
18640
- }
18641
-
18642
- function regenerate(root, current, retrieve) {
18643
- return current instanceof Array ?
18644
- // fast Array reconstruction
18645
- regenerateArray(root, current, retrieve) :
18646
- (
18647
- current instanceof $String ?
18648
- (
18649
- // root is an empty string
18650
- current.length ?
18651
- (
18652
- retrieve.hasOwnProperty(current) ?
18653
- retrieve[current] :
18654
- retrieve[current] = retrieveFromPath(
18655
- root, current.split(specialChar)
18656
- )
18657
- ) :
18658
- root
18659
- ) :
18660
- (
18661
- current instanceof Object ?
18662
- // dedicated Object parser
18663
- regenerateObject(root, current, retrieve) :
18664
- // value as it is
18665
- current
18666
- )
18667
- )
18668
- ;
18669
- }
18670
-
18671
- var CircularJSON = {
18672
- stringify: function stringify(value, replacer, space, doNotResolve) {
18673
- return CircularJSON.parser.stringify(
18674
- value,
18675
- generateReplacer(value, replacer, !doNotResolve),
18676
- space
18677
- );
18678
- },
18679
- parse: function parse(text, reviver) {
18680
- return CircularJSON.parser.parse(
18681
- text,
18682
- generateReviver(reviver)
18683
- );
18684
- },
18685
- // A parser should be an API 1:1 compatible with JSON
18686
- // it should expose stringify and parse methods.
18687
- // The default parser is the native JSON.
18688
- parser: JSON
18689
- };
18690
-
18691
- var circularJson_node = CircularJSON;
18692
-
18693
18560
  /**
18694
18561
  * "Client" wraps "ws" or a browser-implemented "WebSocket" library
18695
18562
  * according to the environment providing JSON RPC 2.0 support on top.
@@ -18723,11 +18590,9 @@ var solanaWeb3 = (function (exports) {
18723
18590
 
18724
18591
  var _eventemitter = eventemitter3.exports;
18725
18592
 
18726
- var _circularJson = _interopRequireDefault(circularJson_node);
18727
-
18728
18593
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
18729
18594
 
18730
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
18595
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
18731
18596
 
18732
18597
  var __rest = function (s, e) {
18733
18598
  var t = {};
@@ -19111,7 +18976,7 @@ var solanaWeb3 = (function (exports) {
19111
18976
  if (message instanceof ArrayBuffer) message = Buffer.from(message).toString();
19112
18977
 
19113
18978
  try {
19114
- message = _circularJson["default"].parse(message);
18979
+ message = JSON.parse(message);
19115
18980
  } catch (error) {
19116
18981
  return;
19117
18982
  } // check if any listeners are attached and forward event
@@ -19182,6 +19047,8 @@ var solanaWeb3 = (function (exports) {
19182
19047
  });
19183
19048
  var Client_1 = index_browser.Client = void 0;
19184
19049
 
19050
+ var _createClass2 = _interopRequireDefault(createClass.exports);
19051
+
19185
19052
  var _classCallCheck2 = _interopRequireDefault(classCallCheck.exports);
19186
19053
 
19187
19054
  var _inherits2 = _interopRequireDefault(inherits$3.exports);
@@ -19196,7 +19063,7 @@ var solanaWeb3 = (function (exports) {
19196
19063
 
19197
19064
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
19198
19065
 
19199
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
19066
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
19200
19067
 
19201
19068
  var Client = /*#__PURE__*/function (_CommonClient) {
19202
19069
  (0, _inherits2["default"])(Client, _CommonClient);
@@ -19226,7 +19093,7 @@ var solanaWeb3 = (function (exports) {
19226
19093
  }, generate_request_id);
19227
19094
  }
19228
19095
 
19229
- return Client;
19096
+ return (0, _createClass2["default"])(Client);
19230
19097
  }(_client["default"]);
19231
19098
 
19232
19099
  Client_1 = index_browser.Client = Client;
@@ -20223,6 +20090,12 @@ var solanaWeb3 = (function (exports) {
20223
20090
  */
20224
20091
 
20225
20092
  const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
20093
+ /**
20094
+ * HACK.
20095
+ * Copied from rpc-websockets/dist/lib/client.
20096
+ * Otherwise, `yarn build` fails with:
20097
+ * https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
20098
+ */
20226
20099
 
20227
20100
  /**
20228
20101
  * @internal
@@ -21091,14 +20964,9 @@ var solanaWeb3 = (function (exports) {
21091
20964
  * Filter for log subscriptions.
21092
20965
  */
21093
20966
 
21094
- function createSubscriptionWarningMessage(id, label) {
21095
- return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
21096
- }
21097
20967
  /**
21098
20968
  * A connection to a fullnode JSON RPC endpoint
21099
20969
  */
21100
-
21101
-
21102
20970
  class Connection {
21103
20971
  /** @internal */
21104
20972
 
@@ -21122,21 +20990,13 @@ var solanaWeb3 = (function (exports) {
21122
20990
 
21123
20991
  /** @internal */
21124
20992
 
21125
- /** @internal */
21126
-
21127
- /** @internal */
21128
-
21129
- /** @internal */
21130
-
21131
- /** @internal */
21132
-
21133
- /** @internal */
21134
-
21135
- /** @internal */
21136
-
21137
- /** @internal */
21138
-
21139
- /** @internal */
20993
+ /** @internal
20994
+ * A number that we increment every time an active connection closes.
20995
+ * Used to determine whether the same socket connection that was open
20996
+ * when an async operation started is the same one that's active when
20997
+ * its continuation fires.
20998
+ *
20999
+ */
21140
21000
 
21141
21001
  /** @internal */
21142
21002
 
@@ -21152,7 +21012,19 @@ var solanaWeb3 = (function (exports) {
21152
21012
 
21153
21013
  /** @internal */
21154
21014
 
21155
- /** @internal */
21015
+ /**
21016
+ * Special case.
21017
+ * After a signature is processed, RPCs automatically dispose of the
21018
+ * subscription on the server side. We need to track which of these
21019
+ * subscriptions have been disposed in such a way, so that we know
21020
+ * whether the client is dealing with a not-yet-processed signature
21021
+ * (in which case we must tear down the server subscription) or an
21022
+ * already-processed signature (in which case the client can simply
21023
+ * clear out the subscription locally without telling the server).
21024
+ *
21025
+ * NOTE: There is a proposal to eliminate this special case, here:
21026
+ * https://github.com/solana-labs/solana/issues/18892
21027
+ */
21156
21028
 
21157
21029
  /** @internal */
21158
21030
 
@@ -21174,6 +21046,7 @@ var solanaWeb3 = (function (exports) {
21174
21046
  this._rpcWebSocketConnected = false;
21175
21047
  this._rpcWebSocketHeartbeat = null;
21176
21048
  this._rpcWebSocketIdleTimeout = null;
21049
+ this._rpcWebSocketGeneration = 0;
21177
21050
  this._disableBlockhashCaching = false;
21178
21051
  this._pollingBlockhash = false;
21179
21052
  this._blockhashInfo = {
@@ -21182,20 +21055,11 @@ var solanaWeb3 = (function (exports) {
21182
21055
  transactionSignatures: [],
21183
21056
  simulatedSignatures: []
21184
21057
  };
21185
- this._accountChangeSubscriptionCounter = 0;
21186
- this._accountChangeSubscriptions = {};
21187
- this._programAccountChangeSubscriptionCounter = 0;
21188
- this._programAccountChangeSubscriptions = {};
21189
- this._rootSubscriptionCounter = 0;
21190
- this._rootSubscriptions = {};
21191
- this._signatureSubscriptionCounter = 0;
21192
- this._signatureSubscriptions = {};
21193
- this._slotSubscriptionCounter = 0;
21194
- this._slotSubscriptions = {};
21195
- this._logsSubscriptionCounter = 0;
21196
- this._logsSubscriptions = {};
21197
- this._slotUpdateSubscriptionCounter = 0;
21198
- this._slotUpdateSubscriptions = {};
21058
+ this._nextClientSubscriptionId = 0;
21059
+ this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
21060
+ this._subscriptionCallbacksByServerSubscriptionId = {};
21061
+ this._subscriptionsByHash = {};
21062
+ this._subscriptionsAutoDisposedByRpc = new Set();
21199
21063
  let url = new URL(endpoint);
21200
21064
  const useHttps = url.protocol === 'https:';
21201
21065
  let wsEndpoint;
@@ -22963,6 +22827,8 @@ var solanaWeb3 = (function (exports) {
22963
22827
 
22964
22828
 
22965
22829
  _wsOnClose(code) {
22830
+ this._rpcWebSocketGeneration++;
22831
+
22966
22832
  if (this._rpcWebSocketHeartbeat) {
22967
22833
  clearInterval(this._rpcWebSocketHeartbeat);
22968
22834
  this._rpcWebSocketHeartbeat = null;
@@ -22976,85 +22842,20 @@ var solanaWeb3 = (function (exports) {
22976
22842
  } // implicit close, prepare subscriptions for auto-reconnect
22977
22843
 
22978
22844
 
22979
- this._resetSubscriptions();
22980
- }
22981
- /**
22982
- * @internal
22983
- */
22984
-
22985
-
22986
- async _subscribe(sub, rpcMethod, rpcArgs) {
22987
- if (sub.subscriptionId == null) {
22988
- sub.subscriptionId = 'subscribing';
22989
-
22990
- try {
22991
- const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
22992
-
22993
- if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
22994
- // eslint-disable-next-line require-atomic-updates
22995
- sub.subscriptionId = id;
22996
- }
22997
- } catch (err) {
22998
- if (sub.subscriptionId === 'subscribing') {
22999
- // eslint-disable-next-line require-atomic-updates
23000
- sub.subscriptionId = null;
23001
- }
23002
-
23003
- if (err instanceof Error) {
23004
- console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
23005
- }
23006
- }
23007
- }
23008
- }
23009
- /**
23010
- * @internal
23011
- */
23012
-
23013
-
23014
- async _unsubscribe(sub, rpcMethod) {
23015
- const subscriptionId = sub.subscriptionId;
23016
-
23017
- if (subscriptionId != null && typeof subscriptionId != 'string') {
23018
- const unsubscribeId = subscriptionId;
23019
-
23020
- try {
23021
- await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
23022
- } catch (err) {
23023
- if (err instanceof Error) {
23024
- console.error(`${rpcMethod} error:`, err.message);
23025
- }
23026
- }
23027
- }
23028
- }
23029
- /**
23030
- * @internal
23031
- */
23032
-
23033
-
23034
- _resetSubscriptions() {
23035
- Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
23036
- Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
23037
- Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
23038
- Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
23039
- Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
23040
- Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
23041
- Object.values(this._slotUpdateSubscriptions).forEach(s => s.subscriptionId = null);
22845
+ this._subscriptionCallbacksByServerSubscriptionId = {};
22846
+ Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
22847
+ this._subscriptionsByHash[hash] = { ...subscription,
22848
+ state: 'pending'
22849
+ };
22850
+ });
23042
22851
  }
23043
22852
  /**
23044
22853
  * @internal
23045
22854
  */
23046
22855
 
23047
22856
 
23048
- _updateSubscriptions() {
23049
- const accountKeys = Object.keys(this._accountChangeSubscriptions).map(Number);
23050
- const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
23051
- const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
23052
- const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
23053
- const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
23054
- const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
23055
- const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
23056
-
23057
- if (accountKeys.length === 0 && programKeys.length === 0 && slotKeys.length === 0 && slotUpdateKeys.length === 0 && signatureKeys.length === 0 && rootKeys.length === 0 && logsKeys.length === 0) {
22857
+ async _updateSubscriptions() {
22858
+ if (Object.keys(this._subscriptionsByHash).length === 0) {
23058
22859
  if (this._rpcWebSocketConnected) {
23059
22860
  this._rpcWebSocketConnected = false;
23060
22861
  this._rpcWebSocketIdleTimeout = setTimeout(() => {
@@ -23086,60 +22887,167 @@ var solanaWeb3 = (function (exports) {
23086
22887
  return;
23087
22888
  }
23088
22889
 
23089
- for (let id of accountKeys) {
23090
- const sub = this._accountChangeSubscriptions[id];
23091
-
23092
- this._subscribe(sub, 'accountSubscribe', this._buildArgs([sub.publicKey], sub.commitment, 'base64'));
23093
- }
22890
+ const activeWebSocketGeneration = this._rpcWebSocketGeneration;
23094
22891
 
23095
- for (let id of programKeys) {
23096
- const sub = this._programAccountChangeSubscriptions[id];
22892
+ const isCurrentConnectionStillActive = () => {
22893
+ return activeWebSocketGeneration === this._rpcWebSocketGeneration;
22894
+ };
23097
22895
 
23098
- this._subscribe(sub, 'programSubscribe', this._buildArgs([sub.programId], sub.commitment, 'base64', {
23099
- filters: sub.filters
23100
- }));
23101
- }
22896
+ await Promise.all( // Don't be tempted to change this to `Object.entries`. We call
22897
+ // `_updateSubscriptions` recursively when processing the state,
22898
+ // so it's important that we look up the *current* version of
22899
+ // each subscription, every time we process a hash.
22900
+ Object.keys(this._subscriptionsByHash).map(async hash => {
22901
+ const subscription = this._subscriptionsByHash[hash];
23102
22902
 
23103
- for (let id of slotKeys) {
23104
- const sub = this._slotSubscriptions[id];
22903
+ if (subscription === undefined) {
22904
+ // This entry has since been deleted. Skip.
22905
+ return;
22906
+ }
23105
22907
 
23106
- this._subscribe(sub, 'slotSubscribe', []);
23107
- }
22908
+ switch (subscription.state) {
22909
+ case 'pending':
22910
+ case 'unsubscribed':
22911
+ if (subscription.callbacks.size === 0) {
22912
+ /**
22913
+ * You can end up here when:
22914
+ *
22915
+ * - a subscription has recently unsubscribed
22916
+ * without having new callbacks added to it
22917
+ * while the unsubscribe was in flight, or
22918
+ * - when a pending subscription has its
22919
+ * listeners removed before a request was
22920
+ * sent to the server.
22921
+ *
22922
+ * Being that nobody is interested in this
22923
+ * subscription any longer, delete it.
22924
+ */
22925
+ delete this._subscriptionsByHash[hash];
22926
+
22927
+ if (subscription.state === 'unsubscribed') {
22928
+ delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId];
22929
+ }
23108
22930
 
23109
- for (let id of slotUpdateKeys) {
23110
- const sub = this._slotUpdateSubscriptions[id];
22931
+ await this._updateSubscriptions();
22932
+ return;
22933
+ }
23111
22934
 
23112
- this._subscribe(sub, 'slotsUpdatesSubscribe', []);
23113
- }
22935
+ await (async () => {
22936
+ const {
22937
+ args,
22938
+ method
22939
+ } = subscription;
23114
22940
 
23115
- for (let id of signatureKeys) {
23116
- const sub = this._signatureSubscriptions[id];
23117
- const args = [sub.signature];
23118
- if (sub.options) args.push(sub.options);
22941
+ try {
22942
+ this._subscriptionsByHash[hash] = { ...subscription,
22943
+ state: 'subscribing'
22944
+ };
22945
+ const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
22946
+ this._subscriptionsByHash[hash] = { ...subscription,
22947
+ serverSubscriptionId,
22948
+ state: 'subscribed'
22949
+ };
22950
+ this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
22951
+ await this._updateSubscriptions();
22952
+ } catch (e) {
22953
+ if (e instanceof Error) {
22954
+ console.error(`${method} error for argument`, args, e.message);
22955
+ }
22956
+
22957
+ if (!isCurrentConnectionStillActive()) {
22958
+ return;
22959
+ } // TODO: Maybe add an 'errored' state or a retry limit?
23119
22960
 
23120
- this._subscribe(sub, 'signatureSubscribe', args);
23121
- }
23122
22961
 
23123
- for (let id of rootKeys) {
23124
- const sub = this._rootSubscriptions[id];
22962
+ this._subscriptionsByHash[hash] = { ...subscription,
22963
+ state: 'pending'
22964
+ };
22965
+ await this._updateSubscriptions();
22966
+ }
22967
+ })();
22968
+ break;
23125
22969
 
23126
- this._subscribe(sub, 'rootSubscribe', []);
23127
- }
22970
+ case 'subscribed':
22971
+ if (subscription.callbacks.size === 0) {
22972
+ // By the time we successfully set up a subscription
22973
+ // with the server, the client stopped caring about it.
22974
+ // Tear it down now.
22975
+ await (async () => {
22976
+ const {
22977
+ serverSubscriptionId,
22978
+ unsubscribeMethod
22979
+ } = subscription;
22980
+
22981
+ if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) {
22982
+ /**
22983
+ * Special case.
22984
+ * If we're dealing with a subscription that has been auto-
22985
+ * disposed by the RPC, then we can skip the RPC call to
22986
+ * tear down the subscription here.
22987
+ *
22988
+ * NOTE: There is a proposal to eliminate this special case, here:
22989
+ * https://github.com/solana-labs/solana/issues/18892
22990
+ */
22991
+ this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
22992
+ } else {
22993
+ this._subscriptionsByHash[hash] = { ...subscription,
22994
+ state: 'unsubscribing'
22995
+ };
22996
+
22997
+ try {
22998
+ await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
22999
+ } catch (e) {
23000
+ if (e instanceof Error) {
23001
+ console.error(`${unsubscribeMethod} error:`, e.message);
23002
+ }
23003
+
23004
+ if (!isCurrentConnectionStillActive()) {
23005
+ return;
23006
+ } // TODO: Maybe add an 'errored' state or a retry limit?
23007
+
23008
+
23009
+ this._subscriptionsByHash[hash] = { ...subscription,
23010
+ state: 'subscribed'
23011
+ };
23012
+ await this._updateSubscriptions();
23013
+ return;
23014
+ }
23015
+ }
23128
23016
 
23129
- for (let id of logsKeys) {
23130
- const sub = this._logsSubscriptions[id];
23131
- let filter;
23017
+ this._subscriptionsByHash[hash] = { ...subscription,
23018
+ state: 'unsubscribed'
23019
+ };
23020
+ await this._updateSubscriptions();
23021
+ })();
23022
+ }
23132
23023
 
23133
- if (typeof sub.filter === 'object') {
23134
- filter = {
23135
- mentions: [sub.filter.toString()]
23136
- };
23137
- } else {
23138
- filter = sub.filter;
23024
+ break;
23139
23025
  }
23026
+ }));
23027
+ }
23028
+ /**
23029
+ * @internal
23030
+ */
23031
+
23140
23032
 
23141
- this._subscribe(sub, 'logsSubscribe', this._buildArgs([filter], sub.commitment));
23033
+ _handleServerNotification(serverSubscriptionId, callbackArgs) {
23034
+ const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
23035
+
23036
+ if (callbacks === undefined) {
23037
+ return;
23142
23038
  }
23039
+
23040
+ callbacks.forEach(cb => {
23041
+ try {
23042
+ cb( // I failed to find a way to convince TypeScript that `cb` is of type
23043
+ // `TCallback` which is certainly compatible with `Parameters<TCallback>`.
23044
+ // See https://github.com/microsoft/TypeScript/issues/47615
23045
+ // @ts-ignore
23046
+ ...callbackArgs);
23047
+ } catch (e) {
23048
+ console.error(e);
23049
+ }
23050
+ });
23143
23051
  }
23144
23052
  /**
23145
23053
  * @internal
@@ -23147,14 +23055,71 @@ var solanaWeb3 = (function (exports) {
23147
23055
 
23148
23056
 
23149
23057
  _wsOnAccountNotification(notification) {
23150
- const res = create(notification, AccountNotificationResult);
23058
+ const {
23059
+ result,
23060
+ subscription
23061
+ } = create(notification, AccountNotificationResult);
23151
23062
 
23152
- for (const sub of Object.values(this._accountChangeSubscriptions)) {
23153
- if (sub.subscriptionId === res.subscription) {
23154
- sub.callback(res.result.value, res.result.context);
23155
- return;
23156
- }
23063
+ this._handleServerNotification(subscription, [result.value, result.context]);
23064
+ }
23065
+ /**
23066
+ * @internal
23067
+ */
23068
+
23069
+
23070
+ _makeSubscription(subscriptionConfig,
23071
+ /**
23072
+ * When preparing `args` for a call to `_makeSubscription`, be sure
23073
+ * to carefully apply a default `commitment` property, if necessary.
23074
+ *
23075
+ * - If the user supplied a `commitment` use that.
23076
+ * - Otherwise, if the `Connection::commitment` is set, use that.
23077
+ * - Otherwise, set it to the RPC server default: `finalized`.
23078
+ *
23079
+ * This is extremely important to ensure that these two fundamentally
23080
+ * identical subscriptions produce the same identifying hash:
23081
+ *
23082
+ * - A subscription made without specifying a commitment.
23083
+ * - A subscription made where the commitment specified is the same
23084
+ * as the default applied to the subscription above.
23085
+ *
23086
+ * Example; these two subscriptions must produce the same hash:
23087
+ *
23088
+ * - An `accountSubscribe` subscription for `'PUBKEY'`
23089
+ * - An `accountSubscribe` subscription for `'PUBKEY'` with commitment
23090
+ * `'finalized'`.
23091
+ *
23092
+ * See the 'making a subscription with defaulted params omitted' test
23093
+ * in `connection-subscriptions.ts` for more.
23094
+ */
23095
+ args) {
23096
+ const clientSubscriptionId = this._nextClientSubscriptionId++;
23097
+ const hash = fastStableStringify$1([subscriptionConfig.method, args], true
23098
+ /* isArrayProp */
23099
+ );
23100
+ const existingSubscription = this._subscriptionsByHash[hash];
23101
+
23102
+ if (existingSubscription === undefined) {
23103
+ this._subscriptionsByHash[hash] = { ...subscriptionConfig,
23104
+ args,
23105
+ callbacks: new Set([subscriptionConfig.callback]),
23106
+ state: 'pending'
23107
+ };
23108
+ } else {
23109
+ existingSubscription.callbacks.add(subscriptionConfig.callback);
23157
23110
  }
23111
+
23112
+ this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
23113
+ delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
23114
+ const subscription = this._subscriptionsByHash[hash];
23115
+ assert$c(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
23116
+ subscription.callbacks.delete(subscriptionConfig.callback);
23117
+ await this._updateSubscriptions();
23118
+ };
23119
+
23120
+ this._updateSubscriptions();
23121
+
23122
+ return clientSubscriptionId;
23158
23123
  }
23159
23124
  /**
23160
23125
  * Register a callback to be invoked whenever the specified account changes
@@ -23167,35 +23132,24 @@ var solanaWeb3 = (function (exports) {
23167
23132
 
23168
23133
 
23169
23134
  onAccountChange(publicKey, callback, commitment) {
23170
- const id = ++this._accountChangeSubscriptionCounter;
23171
- this._accountChangeSubscriptions[id] = {
23172
- publicKey: publicKey.toBase58(),
23173
- callback,
23174
- commitment,
23175
- subscriptionId: null
23176
- };
23177
-
23178
- this._updateSubscriptions();
23135
+ const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
23136
+ 'base64');
23179
23137
 
23180
- return id;
23138
+ return this._makeSubscription({
23139
+ callback,
23140
+ method: 'accountSubscribe',
23141
+ unsubscribeMethod: 'accountUnsubscribe'
23142
+ }, args);
23181
23143
  }
23182
23144
  /**
23183
23145
  * Deregister an account notification callback
23184
23146
  *
23185
- * @param id subscription id to deregister
23147
+ * @param id client subscription id to deregister
23186
23148
  */
23187
23149
 
23188
23150
 
23189
- async removeAccountChangeListener(id) {
23190
- if (this._accountChangeSubscriptions[id]) {
23191
- const subInfo = this._accountChangeSubscriptions[id];
23192
- delete this._accountChangeSubscriptions[id];
23193
- await this._unsubscribe(subInfo, 'accountUnsubscribe');
23194
-
23195
- this._updateSubscriptions();
23196
- } else {
23197
- console.warn(createSubscriptionWarningMessage(id, 'account change'));
23198
- }
23151
+ async removeAccountChangeListener(clientSubscriptionId) {
23152
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
23199
23153
  }
23200
23154
  /**
23201
23155
  * @internal
@@ -23203,21 +23157,15 @@ var solanaWeb3 = (function (exports) {
23203
23157
 
23204
23158
 
23205
23159
  _wsOnProgramAccountNotification(notification) {
23206
- const res = create(notification, ProgramAccountNotificationResult);
23160
+ const {
23161
+ result,
23162
+ subscription
23163
+ } = create(notification, ProgramAccountNotificationResult);
23207
23164
 
23208
- for (const sub of Object.values(this._programAccountChangeSubscriptions)) {
23209
- if (sub.subscriptionId === res.subscription) {
23210
- const {
23211
- value,
23212
- context
23213
- } = res.result;
23214
- sub.callback({
23215
- accountId: value.pubkey,
23216
- accountInfo: value.account
23217
- }, context);
23218
- return;
23219
- }
23220
- }
23165
+ this._handleServerNotification(subscription, [{
23166
+ accountId: result.value.pubkey,
23167
+ accountInfo: result.value.account
23168
+ }, result.context]);
23221
23169
  }
23222
23170
  /**
23223
23171
  * Register a callback to be invoked whenever accounts owned by the
@@ -23232,36 +23180,30 @@ var solanaWeb3 = (function (exports) {
23232
23180
 
23233
23181
 
23234
23182
  onProgramAccountChange(programId, callback, commitment, filters) {
23235
- const id = ++this._programAccountChangeSubscriptionCounter;
23236
- this._programAccountChangeSubscriptions[id] = {
23237
- programId: programId.toBase58(),
23238
- callback,
23239
- commitment,
23240
- subscriptionId: null,
23241
- filters
23242
- };
23243
-
23244
- this._updateSubscriptions();
23183
+ const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
23184
+ 'base64'
23185
+ /* encoding */
23186
+ , filters ? {
23187
+ filters: filters
23188
+ } : undefined
23189
+ /* extra */
23190
+ );
23245
23191
 
23246
- return id;
23192
+ return this._makeSubscription({
23193
+ callback,
23194
+ method: 'programSubscribe',
23195
+ unsubscribeMethod: 'programUnsubscribe'
23196
+ }, args);
23247
23197
  }
23248
23198
  /**
23249
23199
  * Deregister an account notification callback
23250
23200
  *
23251
- * @param id subscription id to deregister
23201
+ * @param id client subscription id to deregister
23252
23202
  */
23253
23203
 
23254
23204
 
23255
- async removeProgramAccountChangeListener(id) {
23256
- if (this._programAccountChangeSubscriptions[id]) {
23257
- const subInfo = this._programAccountChangeSubscriptions[id];
23258
- delete this._programAccountChangeSubscriptions[id];
23259
- await this._unsubscribe(subInfo, 'programUnsubscribe');
23260
-
23261
- this._updateSubscriptions();
23262
- } else {
23263
- console.warn(createSubscriptionWarningMessage(id, 'program account change'));
23264
- }
23205
+ async removeProgramAccountChangeListener(clientSubscriptionId) {
23206
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
23265
23207
  }
23266
23208
  /**
23267
23209
  * Registers a callback to be invoked whenever logs are emitted.
@@ -23269,35 +23211,26 @@ var solanaWeb3 = (function (exports) {
23269
23211
 
23270
23212
 
23271
23213
  onLogs(filter, callback, commitment) {
23272
- const id = ++this._logsSubscriptionCounter;
23273
- this._logsSubscriptions[id] = {
23274
- filter,
23275
- callback,
23276
- commitment,
23277
- subscriptionId: null
23278
- };
23279
-
23280
- this._updateSubscriptions();
23214
+ const args = this._buildArgs([typeof filter === 'object' ? {
23215
+ mentions: [filter.toString()]
23216
+ } : filter], commitment || this._commitment || 'finalized' // Apply connection/server default.
23217
+ );
23281
23218
 
23282
- return id;
23219
+ return this._makeSubscription({
23220
+ callback,
23221
+ method: 'logsSubscribe',
23222
+ unsubscribeMethod: 'logsUnsubscribe'
23223
+ }, args);
23283
23224
  }
23284
23225
  /**
23285
23226
  * Deregister a logs callback.
23286
23227
  *
23287
- * @param id subscription id to deregister.
23228
+ * @param id client subscription id to deregister.
23288
23229
  */
23289
23230
 
23290
23231
 
23291
- async removeOnLogsListener(id) {
23292
- if (this._logsSubscriptions[id]) {
23293
- const subInfo = this._logsSubscriptions[id];
23294
- delete this._logsSubscriptions[id];
23295
- await this._unsubscribe(subInfo, 'logsUnsubscribe');
23296
-
23297
- this._updateSubscriptions();
23298
- } else {
23299
- console.warn(createSubscriptionWarningMessage(id, 'logs'));
23300
- }
23232
+ async removeOnLogsListener(clientSubscriptionId) {
23233
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
23301
23234
  }
23302
23235
  /**
23303
23236
  * @internal
@@ -23305,17 +23238,12 @@ var solanaWeb3 = (function (exports) {
23305
23238
 
23306
23239
 
23307
23240
  _wsOnLogsNotification(notification) {
23308
- const res = create(notification, LogsNotificationResult);
23309
- const keys = Object.keys(this._logsSubscriptions).map(Number);
23310
-
23311
- for (let id of keys) {
23312
- const sub = this._logsSubscriptions[id];
23241
+ const {
23242
+ result,
23243
+ subscription
23244
+ } = create(notification, LogsNotificationResult);
23313
23245
 
23314
- if (sub.subscriptionId === res.subscription) {
23315
- sub.callback(res.result.value, res.result.context);
23316
- return;
23317
- }
23318
- }
23246
+ this._handleServerNotification(subscription, [result.value, result.context]);
23319
23247
  }
23320
23248
  /**
23321
23249
  * @internal
@@ -23323,14 +23251,12 @@ var solanaWeb3 = (function (exports) {
23323
23251
 
23324
23252
 
23325
23253
  _wsOnSlotNotification(notification) {
23326
- const res = create(notification, SlotNotificationResult);
23254
+ const {
23255
+ result,
23256
+ subscription
23257
+ } = create(notification, SlotNotificationResult);
23327
23258
 
23328
- for (const sub of Object.values(this._slotSubscriptions)) {
23329
- if (sub.subscriptionId === res.subscription) {
23330
- sub.callback(res.result);
23331
- return;
23332
- }
23333
- }
23259
+ this._handleServerNotification(subscription, [result]);
23334
23260
  }
23335
23261
  /**
23336
23262
  * Register a callback to be invoked upon slot changes
@@ -23341,33 +23267,23 @@ var solanaWeb3 = (function (exports) {
23341
23267
 
23342
23268
 
23343
23269
  onSlotChange(callback) {
23344
- const id = ++this._slotSubscriptionCounter;
23345
- this._slotSubscriptions[id] = {
23270
+ return this._makeSubscription({
23346
23271
  callback,
23347
- subscriptionId: null
23348
- };
23349
-
23350
- this._updateSubscriptions();
23351
-
23352
- return id;
23272
+ method: 'slotSubscribe',
23273
+ unsubscribeMethod: 'slotUnsubscribe'
23274
+ }, []
23275
+ /* args */
23276
+ );
23353
23277
  }
23354
23278
  /**
23355
23279
  * Deregister a slot notification callback
23356
23280
  *
23357
- * @param id subscription id to deregister
23281
+ * @param id client subscription id to deregister
23358
23282
  */
23359
23283
 
23360
23284
 
23361
- async removeSlotChangeListener(id) {
23362
- if (this._slotSubscriptions[id]) {
23363
- const subInfo = this._slotSubscriptions[id];
23364
- delete this._slotSubscriptions[id];
23365
- await this._unsubscribe(subInfo, 'slotUnsubscribe');
23366
-
23367
- this._updateSubscriptions();
23368
- } else {
23369
- console.warn(createSubscriptionWarningMessage(id, 'slot change'));
23370
- }
23285
+ async removeSlotChangeListener(clientSubscriptionId) {
23286
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
23371
23287
  }
23372
23288
  /**
23373
23289
  * @internal
@@ -23375,14 +23291,12 @@ var solanaWeb3 = (function (exports) {
23375
23291
 
23376
23292
 
23377
23293
  _wsOnSlotUpdatesNotification(notification) {
23378
- const res = create(notification, SlotUpdateNotificationResult);
23294
+ const {
23295
+ result,
23296
+ subscription
23297
+ } = create(notification, SlotUpdateNotificationResult);
23379
23298
 
23380
- for (const sub of Object.values(this._slotUpdateSubscriptions)) {
23381
- if (sub.subscriptionId === res.subscription) {
23382
- sub.callback(res.result);
23383
- return;
23384
- }
23385
- }
23299
+ this._handleServerNotification(subscription, [result]);
23386
23300
  }
23387
23301
  /**
23388
23302
  * Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
@@ -23394,32 +23308,36 @@ var solanaWeb3 = (function (exports) {
23394
23308
 
23395
23309
 
23396
23310
  onSlotUpdate(callback) {
23397
- const id = ++this._slotUpdateSubscriptionCounter;
23398
- this._slotUpdateSubscriptions[id] = {
23311
+ return this._makeSubscription({
23399
23312
  callback,
23400
- subscriptionId: null
23401
- };
23402
-
23403
- this._updateSubscriptions();
23404
-
23405
- return id;
23313
+ method: 'slotsUpdatesSubscribe',
23314
+ unsubscribeMethod: 'slotsUpdatesUnsubscribe'
23315
+ }, []
23316
+ /* args */
23317
+ );
23406
23318
  }
23407
23319
  /**
23408
23320
  * Deregister a slot update notification callback
23409
23321
  *
23410
- * @param id subscription id to deregister
23322
+ * @param id client subscription id to deregister
23411
23323
  */
23412
23324
 
23413
23325
 
23414
- async removeSlotUpdateListener(id) {
23415
- if (this._slotUpdateSubscriptions[id]) {
23416
- const subInfo = this._slotUpdateSubscriptions[id];
23417
- delete this._slotUpdateSubscriptions[id];
23418
- await this._unsubscribe(subInfo, 'slotsUpdatesUnsubscribe');
23326
+ async removeSlotUpdateListener(clientSubscriptionId) {
23327
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
23328
+ }
23329
+ /**
23330
+ * @internal
23331
+ */
23419
23332
 
23420
- this._updateSubscriptions();
23333
+
23334
+ async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
23335
+ const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
23336
+
23337
+ if (dispose) {
23338
+ await dispose();
23421
23339
  } else {
23422
- console.warn(createSubscriptionWarningMessage(id, 'slot update'));
23340
+ console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
23423
23341
  }
23424
23342
  }
23425
23343
 
@@ -23466,30 +23384,34 @@ var solanaWeb3 = (function (exports) {
23466
23384
 
23467
23385
 
23468
23386
  _wsOnSignatureNotification(notification) {
23469
- const res = create(notification, SignatureNotificationResult);
23470
-
23471
- for (const [id, sub] of Object.entries(this._signatureSubscriptions)) {
23472
- if (sub.subscriptionId === res.subscription) {
23473
- if (res.result.value === 'receivedSignature') {
23474
- sub.callback({
23475
- type: 'received'
23476
- }, res.result.context);
23477
- } else {
23478
- // Signatures subscriptions are auto-removed by the RPC service so
23479
- // no need to explicitly send an unsubscribe message
23480
- delete this._signatureSubscriptions[Number(id)];
23481
-
23482
- this._updateSubscriptions();
23483
-
23484
- sub.callback({
23485
- type: 'status',
23486
- result: res.result.value
23487
- }, res.result.context);
23488
- }
23489
-
23490
- return;
23491
- }
23492
- }
23387
+ const {
23388
+ result,
23389
+ subscription
23390
+ } = create(notification, SignatureNotificationResult);
23391
+
23392
+ if (result.value !== 'receivedSignature') {
23393
+ /**
23394
+ * Special case.
23395
+ * After a signature is processed, RPCs automatically dispose of the
23396
+ * subscription on the server side. We need to track which of these
23397
+ * subscriptions have been disposed in such a way, so that we know
23398
+ * whether the client is dealing with a not-yet-processed signature
23399
+ * (in which case we must tear down the server subscription) or an
23400
+ * already-processed signature (in which case the client can simply
23401
+ * clear out the subscription locally without telling the server).
23402
+ *
23403
+ * NOTE: There is a proposal to eliminate this special case, here:
23404
+ * https://github.com/solana-labs/solana/issues/18892
23405
+ */
23406
+ this._subscriptionsAutoDisposedByRpc.add(subscription);
23407
+ }
23408
+
23409
+ this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{
23410
+ type: 'received'
23411
+ }, result.context] : [{
23412
+ type: 'status',
23413
+ result: result.value
23414
+ }, result.context]);
23493
23415
  }
23494
23416
  /**
23495
23417
  * Register a callback to be invoked upon signature updates
@@ -23502,23 +23424,26 @@ var solanaWeb3 = (function (exports) {
23502
23424
 
23503
23425
 
23504
23426
  onSignature(signature, callback, commitment) {
23505
- const id = ++this._signatureSubscriptionCounter;
23506
- this._signatureSubscriptions[id] = {
23507
- signature,
23427
+ const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
23428
+ );
23429
+
23430
+ const clientSubscriptionId = this._makeSubscription({
23508
23431
  callback: (notification, context) => {
23509
23432
  if (notification.type === 'status') {
23510
- callback(notification.result, context);
23433
+ callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service
23434
+ // so no need to explicitly send an unsubscribe message.
23435
+
23436
+ try {
23437
+ this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
23438
+ } catch {// Already removed.
23439
+ }
23511
23440
  }
23512
23441
  },
23513
- options: {
23514
- commitment
23515
- },
23516
- subscriptionId: null
23517
- };
23442
+ method: 'signatureSubscribe',
23443
+ unsubscribeMethod: 'signatureUnsubscribe'
23444
+ }, args);
23518
23445
 
23519
- this._updateSubscriptions();
23520
-
23521
- return id;
23446
+ return clientSubscriptionId;
23522
23447
  }
23523
23448
  /**
23524
23449
  * Register a callback to be invoked when a transaction is
@@ -23533,35 +23458,43 @@ var solanaWeb3 = (function (exports) {
23533
23458
 
23534
23459
 
23535
23460
  onSignatureWithOptions(signature, callback, options) {
23536
- const id = ++this._signatureSubscriptionCounter;
23537
- this._signatureSubscriptions[id] = {
23538
- signature,
23539
- callback,
23540
- options,
23541
- subscriptionId: null
23461
+ const {
23462
+ commitment,
23463
+ ...extra
23464
+ } = { ...options,
23465
+ commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
23466
+
23542
23467
  };
23543
23468
 
23544
- this._updateSubscriptions();
23469
+ const args = this._buildArgs([signature], commitment, undefined
23470
+ /* encoding */
23471
+ , extra);
23472
+
23473
+ const clientSubscriptionId = this._makeSubscription({
23474
+ callback: (notification, context) => {
23475
+ callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service
23476
+ // so no need to explicitly send an unsubscribe message.
23545
23477
 
23546
- return id;
23478
+ try {
23479
+ this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
23480
+ } catch {// Already removed.
23481
+ }
23482
+ },
23483
+ method: 'signatureSubscribe',
23484
+ unsubscribeMethod: 'signatureUnsubscribe'
23485
+ }, args);
23486
+
23487
+ return clientSubscriptionId;
23547
23488
  }
23548
23489
  /**
23549
23490
  * Deregister a signature notification callback
23550
23491
  *
23551
- * @param id subscription id to deregister
23492
+ * @param id client subscription id to deregister
23552
23493
  */
23553
23494
 
23554
23495
 
23555
- async removeSignatureListener(id) {
23556
- if (this._signatureSubscriptions[id]) {
23557
- const subInfo = this._signatureSubscriptions[id];
23558
- delete this._signatureSubscriptions[id];
23559
- await this._unsubscribe(subInfo, 'signatureUnsubscribe');
23560
-
23561
- this._updateSubscriptions();
23562
- } else {
23563
- console.warn(createSubscriptionWarningMessage(id, 'signature result'));
23564
- }
23496
+ async removeSignatureListener(clientSubscriptionId) {
23497
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
23565
23498
  }
23566
23499
  /**
23567
23500
  * @internal
@@ -23569,14 +23502,12 @@ var solanaWeb3 = (function (exports) {
23569
23502
 
23570
23503
 
23571
23504
  _wsOnRootNotification(notification) {
23572
- const res = create(notification, RootNotificationResult);
23505
+ const {
23506
+ result,
23507
+ subscription
23508
+ } = create(notification, RootNotificationResult);
23573
23509
 
23574
- for (const sub of Object.values(this._rootSubscriptions)) {
23575
- if (sub.subscriptionId === res.subscription) {
23576
- sub.callback(res.result);
23577
- return;
23578
- }
23579
- }
23510
+ this._handleServerNotification(subscription, [result]);
23580
23511
  }
23581
23512
  /**
23582
23513
  * Register a callback to be invoked upon root changes
@@ -23587,33 +23518,23 @@ var solanaWeb3 = (function (exports) {
23587
23518
 
23588
23519
 
23589
23520
  onRootChange(callback) {
23590
- const id = ++this._rootSubscriptionCounter;
23591
- this._rootSubscriptions[id] = {
23521
+ return this._makeSubscription({
23592
23522
  callback,
23593
- subscriptionId: null
23594
- };
23595
-
23596
- this._updateSubscriptions();
23597
-
23598
- return id;
23523
+ method: 'rootSubscribe',
23524
+ unsubscribeMethod: 'rootUnsubscribe'
23525
+ }, []
23526
+ /* args */
23527
+ );
23599
23528
  }
23600
23529
  /**
23601
23530
  * Deregister a root notification callback
23602
23531
  *
23603
- * @param id subscription id to deregister
23532
+ * @param id client subscription id to deregister
23604
23533
  */
23605
23534
 
23606
23535
 
23607
- async removeRootChangeListener(id) {
23608
- if (this._rootSubscriptions[id]) {
23609
- const subInfo = this._rootSubscriptions[id];
23610
- delete this._rootSubscriptions[id];
23611
- await this._unsubscribe(subInfo, 'rootUnsubscribe');
23612
-
23613
- this._updateSubscriptions();
23614
- } else {
23615
- console.warn(createSubscriptionWarningMessage(id, 'root change'));
23616
- }
23536
+ async removeRootChangeListener(clientSubscriptionId) {
23537
+ await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
23617
23538
  }
23618
23539
 
23619
23540
  }