@solana/web3.js 1.41.0 → 1.41.3
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.browser.cjs.js +516 -387
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +516 -388
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +516 -387
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +47 -30
- package/lib/index.esm.js +516 -388
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +548 -628
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +2 -24
- package/lib/index.iife.min.js.map +1 -1
- package/package.json +11 -8
- package/src/connection.ts +657 -486
- package/src/index.ts +1 -0
- package/src/loader.ts +2 -1
- package/src/message.ts +1 -1
- package/src/transaction-constants.ts +10 -0
- package/src/transaction.ts +7 -16
package/lib/index.browser.cjs.js
CHANGED
|
@@ -2108,6 +2108,16 @@ class Account {
|
|
|
2108
2108
|
|
|
2109
2109
|
const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader1111111111111111111111111111111111');
|
|
2110
2110
|
|
|
2111
|
+
/**
|
|
2112
|
+
* Maximum over-the-wire size of a Transaction
|
|
2113
|
+
*
|
|
2114
|
+
* 1280 is IPv6 minimum MTU
|
|
2115
|
+
* 40 bytes is the size of the IPv6 header
|
|
2116
|
+
* 8 bytes is the size of the fragment header
|
|
2117
|
+
*/
|
|
2118
|
+
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2119
|
+
const SIGNATURE_LENGTH_IN_BYTES = 64;
|
|
2120
|
+
|
|
2111
2121
|
/**
|
|
2112
2122
|
* Layout for a public key
|
|
2113
2123
|
*/
|
|
@@ -2367,20 +2377,8 @@ function assert (condition, message) {
|
|
|
2367
2377
|
|
|
2368
2378
|
/**
|
|
2369
2379
|
* Default (empty) signature
|
|
2370
|
-
*
|
|
2371
|
-
* Signatures are 64 bytes in length
|
|
2372
2380
|
*/
|
|
2373
|
-
const DEFAULT_SIGNATURE = buffer.Buffer.alloc(
|
|
2374
|
-
/**
|
|
2375
|
-
* Maximum over-the-wire size of a Transaction
|
|
2376
|
-
*
|
|
2377
|
-
* 1280 is IPv6 minimum MTU
|
|
2378
|
-
* 40 bytes is the size of the IPv6 header
|
|
2379
|
-
* 8 bytes is the size of the fragment header
|
|
2380
|
-
*/
|
|
2381
|
-
|
|
2382
|
-
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2383
|
-
const SIGNATURE_LENGTH = 64;
|
|
2381
|
+
const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
|
|
2384
2382
|
/**
|
|
2385
2383
|
* Account metadata used to define instructions
|
|
2386
2384
|
*/
|
|
@@ -3010,8 +3008,8 @@ class Transaction {
|
|
|
3010
3008
|
let signatures = [];
|
|
3011
3009
|
|
|
3012
3010
|
for (let i = 0; i < signatureCount; i++) {
|
|
3013
|
-
const signature = byteArray.slice(0,
|
|
3014
|
-
byteArray = byteArray.slice(
|
|
3011
|
+
const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
|
|
3012
|
+
byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
|
|
3015
3013
|
signatures.push(bs58__default["default"].encode(buffer.Buffer.from(signature)));
|
|
3016
3014
|
}
|
|
3017
3015
|
|
|
@@ -3900,11 +3898,11 @@ class SystemProgram {
|
|
|
3900
3898
|
}
|
|
3901
3899
|
SystemProgram.programId = new PublicKey('11111111111111111111111111111111');
|
|
3902
3900
|
|
|
3903
|
-
// Keep program chunks under PACKET_DATA_SIZE, leaving enough room for the
|
|
3904
3901
|
// rest of the Transaction fields
|
|
3905
3902
|
//
|
|
3906
3903
|
// TODO: replace 300 with a proper constant for the size of the other
|
|
3907
3904
|
// Transaction fields
|
|
3905
|
+
|
|
3908
3906
|
const CHUNK_SIZE = PACKET_DATA_SIZE - 300;
|
|
3909
3907
|
/**
|
|
3910
3908
|
* Program loader interface
|
|
@@ -4795,6 +4793,82 @@ module.exports = exports;
|
|
|
4795
4793
|
|
|
4796
4794
|
var crossFetch = /*@__PURE__*/getDefaultExportFromCjs(browserPonyfill.exports);
|
|
4797
4795
|
|
|
4796
|
+
var objToString = Object.prototype.toString;
|
|
4797
|
+
var objKeys = Object.keys || function(obj) {
|
|
4798
|
+
var keys = [];
|
|
4799
|
+
for (var name in obj) {
|
|
4800
|
+
keys.push(name);
|
|
4801
|
+
}
|
|
4802
|
+
return keys;
|
|
4803
|
+
};
|
|
4804
|
+
|
|
4805
|
+
function stringify(val, isArrayProp) {
|
|
4806
|
+
var i, max, str, keys, key, propVal, toStr;
|
|
4807
|
+
if (val === true) {
|
|
4808
|
+
return "true";
|
|
4809
|
+
}
|
|
4810
|
+
if (val === false) {
|
|
4811
|
+
return "false";
|
|
4812
|
+
}
|
|
4813
|
+
switch (typeof val) {
|
|
4814
|
+
case "object":
|
|
4815
|
+
if (val === null) {
|
|
4816
|
+
return null;
|
|
4817
|
+
} else if (val.toJSON && typeof val.toJSON === "function") {
|
|
4818
|
+
return stringify(val.toJSON(), isArrayProp);
|
|
4819
|
+
} else {
|
|
4820
|
+
toStr = objToString.call(val);
|
|
4821
|
+
if (toStr === "[object Array]") {
|
|
4822
|
+
str = '[';
|
|
4823
|
+
max = val.length - 1;
|
|
4824
|
+
for(i = 0; i < max; i++) {
|
|
4825
|
+
str += stringify(val[i], true) + ',';
|
|
4826
|
+
}
|
|
4827
|
+
if (max > -1) {
|
|
4828
|
+
str += stringify(val[i], true);
|
|
4829
|
+
}
|
|
4830
|
+
return str + ']';
|
|
4831
|
+
} else if (toStr === "[object Object]") {
|
|
4832
|
+
// only object is left
|
|
4833
|
+
keys = objKeys(val).sort();
|
|
4834
|
+
max = keys.length;
|
|
4835
|
+
str = "";
|
|
4836
|
+
i = 0;
|
|
4837
|
+
while (i < max) {
|
|
4838
|
+
key = keys[i];
|
|
4839
|
+
propVal = stringify(val[key], false);
|
|
4840
|
+
if (propVal !== undefined) {
|
|
4841
|
+
if (str) {
|
|
4842
|
+
str += ',';
|
|
4843
|
+
}
|
|
4844
|
+
str += JSON.stringify(key) + ':' + propVal;
|
|
4845
|
+
}
|
|
4846
|
+
i++;
|
|
4847
|
+
}
|
|
4848
|
+
return '{' + str + '}';
|
|
4849
|
+
} else {
|
|
4850
|
+
return JSON.stringify(val);
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
case "function":
|
|
4854
|
+
case "undefined":
|
|
4855
|
+
return isArrayProp ? null : undefined;
|
|
4856
|
+
case "string":
|
|
4857
|
+
return JSON.stringify(val);
|
|
4858
|
+
default:
|
|
4859
|
+
return isFinite(val) ? val : null;
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
var fastStableStringify = function(val) {
|
|
4864
|
+
var returnVal = stringify(val, false);
|
|
4865
|
+
if (returnVal !== undefined) {
|
|
4866
|
+
return ''+ returnVal;
|
|
4867
|
+
}
|
|
4868
|
+
};
|
|
4869
|
+
|
|
4870
|
+
var fastStableStringify$1 = fastStableStringify;
|
|
4871
|
+
|
|
4798
4872
|
const MINIMUM_SLOT_PER_EPOCH = 32; // Returns the number of trailing zeros in the binary representation of self.
|
|
4799
4873
|
|
|
4800
4874
|
function trailingZeros(n) {
|
|
@@ -4961,6 +5035,12 @@ const BufferFromRawAccountData = superstruct.coerce(superstruct.instance(buffer.
|
|
|
4961
5035
|
*/
|
|
4962
5036
|
|
|
4963
5037
|
const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
|
|
5038
|
+
/**
|
|
5039
|
+
* HACK.
|
|
5040
|
+
* Copied from rpc-websockets/dist/lib/client.
|
|
5041
|
+
* Otherwise, `yarn build` fails with:
|
|
5042
|
+
* https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
|
|
5043
|
+
*/
|
|
4964
5044
|
|
|
4965
5045
|
/**
|
|
4966
5046
|
* @internal
|
|
@@ -5829,14 +5909,9 @@ const LogsNotificationResult = superstruct.type({
|
|
|
5829
5909
|
* Filter for log subscriptions.
|
|
5830
5910
|
*/
|
|
5831
5911
|
|
|
5832
|
-
function createSubscriptionWarningMessage(id, label) {
|
|
5833
|
-
return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
|
|
5834
|
-
}
|
|
5835
5912
|
/**
|
|
5836
5913
|
* A connection to a fullnode JSON RPC endpoint
|
|
5837
5914
|
*/
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
5915
|
class Connection {
|
|
5841
5916
|
/** @internal */
|
|
5842
5917
|
|
|
@@ -5860,21 +5935,13 @@ class Connection {
|
|
|
5860
5935
|
|
|
5861
5936
|
/** @internal */
|
|
5862
5937
|
|
|
5863
|
-
/** @internal
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
/** @internal */
|
|
5872
|
-
|
|
5873
|
-
/** @internal */
|
|
5874
|
-
|
|
5875
|
-
/** @internal */
|
|
5876
|
-
|
|
5877
|
-
/** @internal */
|
|
5938
|
+
/** @internal
|
|
5939
|
+
* A number that we increment every time an active connection closes.
|
|
5940
|
+
* Used to determine whether the same socket connection that was open
|
|
5941
|
+
* when an async operation started is the same one that's active when
|
|
5942
|
+
* its continuation fires.
|
|
5943
|
+
*
|
|
5944
|
+
*/
|
|
5878
5945
|
|
|
5879
5946
|
/** @internal */
|
|
5880
5947
|
|
|
@@ -5890,7 +5957,19 @@ class Connection {
|
|
|
5890
5957
|
|
|
5891
5958
|
/** @internal */
|
|
5892
5959
|
|
|
5893
|
-
/**
|
|
5960
|
+
/**
|
|
5961
|
+
* Special case.
|
|
5962
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
5963
|
+
* subscription on the server side. We need to track which of these
|
|
5964
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
5965
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
5966
|
+
* (in which case we must tear down the server subscription) or an
|
|
5967
|
+
* already-processed signature (in which case the client can simply
|
|
5968
|
+
* clear out the subscription locally without telling the server).
|
|
5969
|
+
*
|
|
5970
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
5971
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
5972
|
+
*/
|
|
5894
5973
|
|
|
5895
5974
|
/** @internal */
|
|
5896
5975
|
|
|
@@ -5912,6 +5991,7 @@ class Connection {
|
|
|
5912
5991
|
this._rpcWebSocketConnected = false;
|
|
5913
5992
|
this._rpcWebSocketHeartbeat = null;
|
|
5914
5993
|
this._rpcWebSocketIdleTimeout = null;
|
|
5994
|
+
this._rpcWebSocketGeneration = 0;
|
|
5915
5995
|
this._disableBlockhashCaching = false;
|
|
5916
5996
|
this._pollingBlockhash = false;
|
|
5917
5997
|
this._blockhashInfo = {
|
|
@@ -5920,20 +6000,11 @@ class Connection {
|
|
|
5920
6000
|
transactionSignatures: [],
|
|
5921
6001
|
simulatedSignatures: []
|
|
5922
6002
|
};
|
|
5923
|
-
this.
|
|
5924
|
-
this.
|
|
5925
|
-
this.
|
|
5926
|
-
this.
|
|
5927
|
-
this.
|
|
5928
|
-
this._rootSubscriptions = {};
|
|
5929
|
-
this._signatureSubscriptionCounter = 0;
|
|
5930
|
-
this._signatureSubscriptions = {};
|
|
5931
|
-
this._slotSubscriptionCounter = 0;
|
|
5932
|
-
this._slotSubscriptions = {};
|
|
5933
|
-
this._logsSubscriptionCounter = 0;
|
|
5934
|
-
this._logsSubscriptions = {};
|
|
5935
|
-
this._slotUpdateSubscriptionCounter = 0;
|
|
5936
|
-
this._slotUpdateSubscriptions = {};
|
|
6003
|
+
this._nextClientSubscriptionId = 0;
|
|
6004
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
6005
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
6006
|
+
this._subscriptionsByHash = {};
|
|
6007
|
+
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
5937
6008
|
let url = new URL(endpoint);
|
|
5938
6009
|
const useHttps = url.protocol === 'https:';
|
|
5939
6010
|
let wsEndpoint;
|
|
@@ -7701,6 +7772,8 @@ class Connection {
|
|
|
7701
7772
|
|
|
7702
7773
|
|
|
7703
7774
|
_wsOnClose(code) {
|
|
7775
|
+
this._rpcWebSocketGeneration++;
|
|
7776
|
+
|
|
7704
7777
|
if (this._rpcWebSocketHeartbeat) {
|
|
7705
7778
|
clearInterval(this._rpcWebSocketHeartbeat);
|
|
7706
7779
|
this._rpcWebSocketHeartbeat = null;
|
|
@@ -7714,85 +7787,20 @@ class Connection {
|
|
|
7714
7787
|
} // implicit close, prepare subscriptions for auto-reconnect
|
|
7715
7788
|
|
|
7716
7789
|
|
|
7717
|
-
this.
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
async _subscribe(sub, rpcMethod, rpcArgs) {
|
|
7725
|
-
if (sub.subscriptionId == null) {
|
|
7726
|
-
sub.subscriptionId = 'subscribing';
|
|
7727
|
-
|
|
7728
|
-
try {
|
|
7729
|
-
const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
|
|
7730
|
-
|
|
7731
|
-
if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
|
|
7732
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7733
|
-
sub.subscriptionId = id;
|
|
7734
|
-
}
|
|
7735
|
-
} catch (err) {
|
|
7736
|
-
if (sub.subscriptionId === 'subscribing') {
|
|
7737
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7738
|
-
sub.subscriptionId = null;
|
|
7739
|
-
}
|
|
7740
|
-
|
|
7741
|
-
if (err instanceof Error) {
|
|
7742
|
-
console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
|
|
7743
|
-
}
|
|
7744
|
-
}
|
|
7745
|
-
}
|
|
7746
|
-
}
|
|
7747
|
-
/**
|
|
7748
|
-
* @internal
|
|
7749
|
-
*/
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
async _unsubscribe(sub, rpcMethod) {
|
|
7753
|
-
const subscriptionId = sub.subscriptionId;
|
|
7754
|
-
|
|
7755
|
-
if (subscriptionId != null && typeof subscriptionId != 'string') {
|
|
7756
|
-
const unsubscribeId = subscriptionId;
|
|
7757
|
-
|
|
7758
|
-
try {
|
|
7759
|
-
await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
|
|
7760
|
-
} catch (err) {
|
|
7761
|
-
if (err instanceof Error) {
|
|
7762
|
-
console.error(`${rpcMethod} error:`, err.message);
|
|
7763
|
-
}
|
|
7764
|
-
}
|
|
7765
|
-
}
|
|
7766
|
-
}
|
|
7767
|
-
/**
|
|
7768
|
-
* @internal
|
|
7769
|
-
*/
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
_resetSubscriptions() {
|
|
7773
|
-
Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7774
|
-
Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7775
|
-
Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7776
|
-
Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7777
|
-
Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7778
|
-
Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7779
|
-
Object.values(this._slotUpdateSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7790
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
7791
|
+
Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
|
|
7792
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7793
|
+
state: 'pending'
|
|
7794
|
+
};
|
|
7795
|
+
});
|
|
7780
7796
|
}
|
|
7781
7797
|
/**
|
|
7782
7798
|
* @internal
|
|
7783
7799
|
*/
|
|
7784
7800
|
|
|
7785
7801
|
|
|
7786
|
-
_updateSubscriptions() {
|
|
7787
|
-
|
|
7788
|
-
const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
|
|
7789
|
-
const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
|
|
7790
|
-
const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
|
|
7791
|
-
const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
|
|
7792
|
-
const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
|
|
7793
|
-
const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
|
|
7794
|
-
|
|
7795
|
-
if (accountKeys.length === 0 && programKeys.length === 0 && slotKeys.length === 0 && slotUpdateKeys.length === 0 && signatureKeys.length === 0 && rootKeys.length === 0 && logsKeys.length === 0) {
|
|
7802
|
+
async _updateSubscriptions() {
|
|
7803
|
+
if (Object.keys(this._subscriptionsByHash).length === 0) {
|
|
7796
7804
|
if (this._rpcWebSocketConnected) {
|
|
7797
7805
|
this._rpcWebSocketConnected = false;
|
|
7798
7806
|
this._rpcWebSocketIdleTimeout = setTimeout(() => {
|
|
@@ -7824,60 +7832,167 @@ class Connection {
|
|
|
7824
7832
|
return;
|
|
7825
7833
|
}
|
|
7826
7834
|
|
|
7827
|
-
|
|
7828
|
-
const sub = this._accountChangeSubscriptions[id];
|
|
7835
|
+
const activeWebSocketGeneration = this._rpcWebSocketGeneration;
|
|
7829
7836
|
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
for (let id of programKeys) {
|
|
7834
|
-
const sub = this._programAccountChangeSubscriptions[id];
|
|
7837
|
+
const isCurrentConnectionStillActive = () => {
|
|
7838
|
+
return activeWebSocketGeneration === this._rpcWebSocketGeneration;
|
|
7839
|
+
};
|
|
7835
7840
|
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7841
|
+
await Promise.all( // Don't be tempted to change this to `Object.entries`. We call
|
|
7842
|
+
// `_updateSubscriptions` recursively when processing the state,
|
|
7843
|
+
// so it's important that we look up the *current* version of
|
|
7844
|
+
// each subscription, every time we process a hash.
|
|
7845
|
+
Object.keys(this._subscriptionsByHash).map(async hash => {
|
|
7846
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7840
7847
|
|
|
7841
|
-
|
|
7842
|
-
|
|
7848
|
+
if (subscription === undefined) {
|
|
7849
|
+
// This entry has since been deleted. Skip.
|
|
7850
|
+
return;
|
|
7851
|
+
}
|
|
7843
7852
|
|
|
7844
|
-
|
|
7845
|
-
|
|
7853
|
+
switch (subscription.state) {
|
|
7854
|
+
case 'pending':
|
|
7855
|
+
case 'unsubscribed':
|
|
7856
|
+
if (subscription.callbacks.size === 0) {
|
|
7857
|
+
/**
|
|
7858
|
+
* You can end up here when:
|
|
7859
|
+
*
|
|
7860
|
+
* - a subscription has recently unsubscribed
|
|
7861
|
+
* without having new callbacks added to it
|
|
7862
|
+
* while the unsubscribe was in flight, or
|
|
7863
|
+
* - when a pending subscription has its
|
|
7864
|
+
* listeners removed before a request was
|
|
7865
|
+
* sent to the server.
|
|
7866
|
+
*
|
|
7867
|
+
* Being that nobody is interested in this
|
|
7868
|
+
* subscription any longer, delete it.
|
|
7869
|
+
*/
|
|
7870
|
+
delete this._subscriptionsByHash[hash];
|
|
7871
|
+
|
|
7872
|
+
if (subscription.state === 'unsubscribed') {
|
|
7873
|
+
delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId];
|
|
7874
|
+
}
|
|
7846
7875
|
|
|
7847
|
-
|
|
7848
|
-
|
|
7876
|
+
await this._updateSubscriptions();
|
|
7877
|
+
return;
|
|
7878
|
+
}
|
|
7849
7879
|
|
|
7850
|
-
|
|
7851
|
-
|
|
7880
|
+
await (async () => {
|
|
7881
|
+
const {
|
|
7882
|
+
args,
|
|
7883
|
+
method
|
|
7884
|
+
} = subscription;
|
|
7852
7885
|
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7886
|
+
try {
|
|
7887
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7888
|
+
state: 'subscribing'
|
|
7889
|
+
};
|
|
7890
|
+
const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
|
|
7891
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7892
|
+
serverSubscriptionId,
|
|
7893
|
+
state: 'subscribed'
|
|
7894
|
+
};
|
|
7895
|
+
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
|
|
7896
|
+
await this._updateSubscriptions();
|
|
7897
|
+
} catch (e) {
|
|
7898
|
+
if (e instanceof Error) {
|
|
7899
|
+
console.error(`${method} error for argument`, args, e.message);
|
|
7900
|
+
}
|
|
7901
|
+
|
|
7902
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7903
|
+
return;
|
|
7904
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7857
7905
|
|
|
7858
|
-
this._subscribe(sub, 'signatureSubscribe', args);
|
|
7859
|
-
}
|
|
7860
7906
|
|
|
7861
|
-
|
|
7862
|
-
|
|
7907
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7908
|
+
state: 'pending'
|
|
7909
|
+
};
|
|
7910
|
+
await this._updateSubscriptions();
|
|
7911
|
+
}
|
|
7912
|
+
})();
|
|
7913
|
+
break;
|
|
7863
7914
|
|
|
7864
|
-
|
|
7865
|
-
|
|
7915
|
+
case 'subscribed':
|
|
7916
|
+
if (subscription.callbacks.size === 0) {
|
|
7917
|
+
// By the time we successfully set up a subscription
|
|
7918
|
+
// with the server, the client stopped caring about it.
|
|
7919
|
+
// Tear it down now.
|
|
7920
|
+
await (async () => {
|
|
7921
|
+
const {
|
|
7922
|
+
serverSubscriptionId,
|
|
7923
|
+
unsubscribeMethod
|
|
7924
|
+
} = subscription;
|
|
7925
|
+
|
|
7926
|
+
if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) {
|
|
7927
|
+
/**
|
|
7928
|
+
* Special case.
|
|
7929
|
+
* If we're dealing with a subscription that has been auto-
|
|
7930
|
+
* disposed by the RPC, then we can skip the RPC call to
|
|
7931
|
+
* tear down the subscription here.
|
|
7932
|
+
*
|
|
7933
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
7934
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
7935
|
+
*/
|
|
7936
|
+
this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
|
|
7937
|
+
} else {
|
|
7938
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7939
|
+
state: 'unsubscribing'
|
|
7940
|
+
};
|
|
7941
|
+
|
|
7942
|
+
try {
|
|
7943
|
+
await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
|
|
7944
|
+
} catch (e) {
|
|
7945
|
+
if (e instanceof Error) {
|
|
7946
|
+
console.error(`${unsubscribeMethod} error:`, e.message);
|
|
7947
|
+
}
|
|
7948
|
+
|
|
7949
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7950
|
+
return;
|
|
7951
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7952
|
+
|
|
7953
|
+
|
|
7954
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7955
|
+
state: 'subscribed'
|
|
7956
|
+
};
|
|
7957
|
+
await this._updateSubscriptions();
|
|
7958
|
+
return;
|
|
7959
|
+
}
|
|
7960
|
+
}
|
|
7866
7961
|
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7962
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7963
|
+
state: 'unsubscribed'
|
|
7964
|
+
};
|
|
7965
|
+
await this._updateSubscriptions();
|
|
7966
|
+
})();
|
|
7967
|
+
}
|
|
7870
7968
|
|
|
7871
|
-
|
|
7872
|
-
filter = {
|
|
7873
|
-
mentions: [sub.filter.toString()]
|
|
7874
|
-
};
|
|
7875
|
-
} else {
|
|
7876
|
-
filter = sub.filter;
|
|
7969
|
+
break;
|
|
7877
7970
|
}
|
|
7971
|
+
}));
|
|
7972
|
+
}
|
|
7973
|
+
/**
|
|
7974
|
+
* @internal
|
|
7975
|
+
*/
|
|
7878
7976
|
|
|
7879
|
-
|
|
7977
|
+
|
|
7978
|
+
_handleServerNotification(serverSubscriptionId, callbackArgs) {
|
|
7979
|
+
const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
|
|
7980
|
+
|
|
7981
|
+
if (callbacks === undefined) {
|
|
7982
|
+
return;
|
|
7880
7983
|
}
|
|
7984
|
+
|
|
7985
|
+
callbacks.forEach(cb => {
|
|
7986
|
+
try {
|
|
7987
|
+
cb( // I failed to find a way to convince TypeScript that `cb` is of type
|
|
7988
|
+
// `TCallback` which is certainly compatible with `Parameters<TCallback>`.
|
|
7989
|
+
// See https://github.com/microsoft/TypeScript/issues/47615
|
|
7990
|
+
// @ts-ignore
|
|
7991
|
+
...callbackArgs);
|
|
7992
|
+
} catch (e) {
|
|
7993
|
+
console.error(e);
|
|
7994
|
+
}
|
|
7995
|
+
});
|
|
7881
7996
|
}
|
|
7882
7997
|
/**
|
|
7883
7998
|
* @internal
|
|
@@ -7885,14 +8000,71 @@ class Connection {
|
|
|
7885
8000
|
|
|
7886
8001
|
|
|
7887
8002
|
_wsOnAccountNotification(notification) {
|
|
7888
|
-
const
|
|
8003
|
+
const {
|
|
8004
|
+
result,
|
|
8005
|
+
subscription
|
|
8006
|
+
} = superstruct.create(notification, AccountNotificationResult);
|
|
7889
8007
|
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
8008
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
8009
|
+
}
|
|
8010
|
+
/**
|
|
8011
|
+
* @internal
|
|
8012
|
+
*/
|
|
8013
|
+
|
|
8014
|
+
|
|
8015
|
+
_makeSubscription(subscriptionConfig,
|
|
8016
|
+
/**
|
|
8017
|
+
* When preparing `args` for a call to `_makeSubscription`, be sure
|
|
8018
|
+
* to carefully apply a default `commitment` property, if necessary.
|
|
8019
|
+
*
|
|
8020
|
+
* - If the user supplied a `commitment` use that.
|
|
8021
|
+
* - Otherwise, if the `Connection::commitment` is set, use that.
|
|
8022
|
+
* - Otherwise, set it to the RPC server default: `finalized`.
|
|
8023
|
+
*
|
|
8024
|
+
* This is extremely important to ensure that these two fundamentally
|
|
8025
|
+
* identical subscriptions produce the same identifying hash:
|
|
8026
|
+
*
|
|
8027
|
+
* - A subscription made without specifying a commitment.
|
|
8028
|
+
* - A subscription made where the commitment specified is the same
|
|
8029
|
+
* as the default applied to the subscription above.
|
|
8030
|
+
*
|
|
8031
|
+
* Example; these two subscriptions must produce the same hash:
|
|
8032
|
+
*
|
|
8033
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'`
|
|
8034
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'` with commitment
|
|
8035
|
+
* `'finalized'`.
|
|
8036
|
+
*
|
|
8037
|
+
* See the 'making a subscription with defaulted params omitted' test
|
|
8038
|
+
* in `connection-subscriptions.ts` for more.
|
|
8039
|
+
*/
|
|
8040
|
+
args) {
|
|
8041
|
+
const clientSubscriptionId = this._nextClientSubscriptionId++;
|
|
8042
|
+
const hash = fastStableStringify$1([subscriptionConfig.method, args], true
|
|
8043
|
+
/* isArrayProp */
|
|
8044
|
+
);
|
|
8045
|
+
const existingSubscription = this._subscriptionsByHash[hash];
|
|
8046
|
+
|
|
8047
|
+
if (existingSubscription === undefined) {
|
|
8048
|
+
this._subscriptionsByHash[hash] = { ...subscriptionConfig,
|
|
8049
|
+
args,
|
|
8050
|
+
callbacks: new Set([subscriptionConfig.callback]),
|
|
8051
|
+
state: 'pending'
|
|
8052
|
+
};
|
|
8053
|
+
} else {
|
|
8054
|
+
existingSubscription.callbacks.add(subscriptionConfig.callback);
|
|
7895
8055
|
}
|
|
8056
|
+
|
|
8057
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
|
|
8058
|
+
delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
8059
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
8060
|
+
assert(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
|
|
8061
|
+
subscription.callbacks.delete(subscriptionConfig.callback);
|
|
8062
|
+
await this._updateSubscriptions();
|
|
8063
|
+
};
|
|
8064
|
+
|
|
8065
|
+
this._updateSubscriptions();
|
|
8066
|
+
|
|
8067
|
+
return clientSubscriptionId;
|
|
7896
8068
|
}
|
|
7897
8069
|
/**
|
|
7898
8070
|
* Register a callback to be invoked whenever the specified account changes
|
|
@@ -7905,35 +8077,24 @@ class Connection {
|
|
|
7905
8077
|
|
|
7906
8078
|
|
|
7907
8079
|
onAccountChange(publicKey, callback, commitment) {
|
|
7908
|
-
const
|
|
7909
|
-
|
|
7910
|
-
publicKey: publicKey.toBase58(),
|
|
7911
|
-
callback,
|
|
7912
|
-
commitment,
|
|
7913
|
-
subscriptionId: null
|
|
7914
|
-
};
|
|
8080
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
8081
|
+
'base64');
|
|
7915
8082
|
|
|
7916
|
-
this.
|
|
7917
|
-
|
|
7918
|
-
|
|
8083
|
+
return this._makeSubscription({
|
|
8084
|
+
callback,
|
|
8085
|
+
method: 'accountSubscribe',
|
|
8086
|
+
unsubscribeMethod: 'accountUnsubscribe'
|
|
8087
|
+
}, args);
|
|
7919
8088
|
}
|
|
7920
8089
|
/**
|
|
7921
8090
|
* Deregister an account notification callback
|
|
7922
8091
|
*
|
|
7923
|
-
* @param id subscription id to deregister
|
|
8092
|
+
* @param id client subscription id to deregister
|
|
7924
8093
|
*/
|
|
7925
8094
|
|
|
7926
8095
|
|
|
7927
|
-
async removeAccountChangeListener(
|
|
7928
|
-
|
|
7929
|
-
const subInfo = this._accountChangeSubscriptions[id];
|
|
7930
|
-
delete this._accountChangeSubscriptions[id];
|
|
7931
|
-
await this._unsubscribe(subInfo, 'accountUnsubscribe');
|
|
7932
|
-
|
|
7933
|
-
this._updateSubscriptions();
|
|
7934
|
-
} else {
|
|
7935
|
-
console.warn(createSubscriptionWarningMessage(id, 'account change'));
|
|
7936
|
-
}
|
|
8096
|
+
async removeAccountChangeListener(clientSubscriptionId) {
|
|
8097
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
|
|
7937
8098
|
}
|
|
7938
8099
|
/**
|
|
7939
8100
|
* @internal
|
|
@@ -7941,21 +8102,15 @@ class Connection {
|
|
|
7941
8102
|
|
|
7942
8103
|
|
|
7943
8104
|
_wsOnProgramAccountNotification(notification) {
|
|
7944
|
-
const
|
|
8105
|
+
const {
|
|
8106
|
+
result,
|
|
8107
|
+
subscription
|
|
8108
|
+
} = superstruct.create(notification, ProgramAccountNotificationResult);
|
|
7945
8109
|
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
context
|
|
7951
|
-
} = res.result;
|
|
7952
|
-
sub.callback({
|
|
7953
|
-
accountId: value.pubkey,
|
|
7954
|
-
accountInfo: value.account
|
|
7955
|
-
}, context);
|
|
7956
|
-
return;
|
|
7957
|
-
}
|
|
7958
|
-
}
|
|
8110
|
+
this._handleServerNotification(subscription, [{
|
|
8111
|
+
accountId: result.value.pubkey,
|
|
8112
|
+
accountInfo: result.value.account
|
|
8113
|
+
}, result.context]);
|
|
7959
8114
|
}
|
|
7960
8115
|
/**
|
|
7961
8116
|
* Register a callback to be invoked whenever accounts owned by the
|
|
@@ -7970,36 +8125,30 @@ class Connection {
|
|
|
7970
8125
|
|
|
7971
8126
|
|
|
7972
8127
|
onProgramAccountChange(programId, callback, commitment, filters) {
|
|
7973
|
-
const
|
|
7974
|
-
|
|
7975
|
-
|
|
8128
|
+
const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
8129
|
+
'base64'
|
|
8130
|
+
/* encoding */
|
|
8131
|
+
, filters ? {
|
|
8132
|
+
filters: filters
|
|
8133
|
+
} : undefined
|
|
8134
|
+
/* extra */
|
|
8135
|
+
);
|
|
8136
|
+
|
|
8137
|
+
return this._makeSubscription({
|
|
7976
8138
|
callback,
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
};
|
|
7981
|
-
|
|
7982
|
-
this._updateSubscriptions();
|
|
7983
|
-
|
|
7984
|
-
return id;
|
|
8139
|
+
method: 'programSubscribe',
|
|
8140
|
+
unsubscribeMethod: 'programUnsubscribe'
|
|
8141
|
+
}, args);
|
|
7985
8142
|
}
|
|
7986
8143
|
/**
|
|
7987
8144
|
* Deregister an account notification callback
|
|
7988
8145
|
*
|
|
7989
|
-
* @param id subscription id to deregister
|
|
8146
|
+
* @param id client subscription id to deregister
|
|
7990
8147
|
*/
|
|
7991
8148
|
|
|
7992
8149
|
|
|
7993
|
-
async removeProgramAccountChangeListener(
|
|
7994
|
-
|
|
7995
|
-
const subInfo = this._programAccountChangeSubscriptions[id];
|
|
7996
|
-
delete this._programAccountChangeSubscriptions[id];
|
|
7997
|
-
await this._unsubscribe(subInfo, 'programUnsubscribe');
|
|
7998
|
-
|
|
7999
|
-
this._updateSubscriptions();
|
|
8000
|
-
} else {
|
|
8001
|
-
console.warn(createSubscriptionWarningMessage(id, 'program account change'));
|
|
8002
|
-
}
|
|
8150
|
+
async removeProgramAccountChangeListener(clientSubscriptionId) {
|
|
8151
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
|
|
8003
8152
|
}
|
|
8004
8153
|
/**
|
|
8005
8154
|
* Registers a callback to be invoked whenever logs are emitted.
|
|
@@ -8007,35 +8156,26 @@ class Connection {
|
|
|
8007
8156
|
|
|
8008
8157
|
|
|
8009
8158
|
onLogs(filter, callback, commitment) {
|
|
8010
|
-
const
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
8014
|
-
commitment,
|
|
8015
|
-
subscriptionId: null
|
|
8016
|
-
};
|
|
8159
|
+
const args = this._buildArgs([typeof filter === 'object' ? {
|
|
8160
|
+
mentions: [filter.toString()]
|
|
8161
|
+
} : filter], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8162
|
+
);
|
|
8017
8163
|
|
|
8018
|
-
this.
|
|
8019
|
-
|
|
8020
|
-
|
|
8164
|
+
return this._makeSubscription({
|
|
8165
|
+
callback,
|
|
8166
|
+
method: 'logsSubscribe',
|
|
8167
|
+
unsubscribeMethod: 'logsUnsubscribe'
|
|
8168
|
+
}, args);
|
|
8021
8169
|
}
|
|
8022
8170
|
/**
|
|
8023
8171
|
* Deregister a logs callback.
|
|
8024
8172
|
*
|
|
8025
|
-
* @param id subscription id to deregister.
|
|
8173
|
+
* @param id client subscription id to deregister.
|
|
8026
8174
|
*/
|
|
8027
8175
|
|
|
8028
8176
|
|
|
8029
|
-
async removeOnLogsListener(
|
|
8030
|
-
|
|
8031
|
-
const subInfo = this._logsSubscriptions[id];
|
|
8032
|
-
delete this._logsSubscriptions[id];
|
|
8033
|
-
await this._unsubscribe(subInfo, 'logsUnsubscribe');
|
|
8034
|
-
|
|
8035
|
-
this._updateSubscriptions();
|
|
8036
|
-
} else {
|
|
8037
|
-
console.warn(createSubscriptionWarningMessage(id, 'logs'));
|
|
8038
|
-
}
|
|
8177
|
+
async removeOnLogsListener(clientSubscriptionId) {
|
|
8178
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
|
|
8039
8179
|
}
|
|
8040
8180
|
/**
|
|
8041
8181
|
* @internal
|
|
@@ -8043,17 +8183,12 @@ class Connection {
|
|
|
8043
8183
|
|
|
8044
8184
|
|
|
8045
8185
|
_wsOnLogsNotification(notification) {
|
|
8046
|
-
const
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
const sub = this._logsSubscriptions[id];
|
|
8186
|
+
const {
|
|
8187
|
+
result,
|
|
8188
|
+
subscription
|
|
8189
|
+
} = superstruct.create(notification, LogsNotificationResult);
|
|
8051
8190
|
|
|
8052
|
-
|
|
8053
|
-
sub.callback(res.result.value, res.result.context);
|
|
8054
|
-
return;
|
|
8055
|
-
}
|
|
8056
|
-
}
|
|
8191
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
8057
8192
|
}
|
|
8058
8193
|
/**
|
|
8059
8194
|
* @internal
|
|
@@ -8061,14 +8196,12 @@ class Connection {
|
|
|
8061
8196
|
|
|
8062
8197
|
|
|
8063
8198
|
_wsOnSlotNotification(notification) {
|
|
8064
|
-
const
|
|
8199
|
+
const {
|
|
8200
|
+
result,
|
|
8201
|
+
subscription
|
|
8202
|
+
} = superstruct.create(notification, SlotNotificationResult);
|
|
8065
8203
|
|
|
8066
|
-
|
|
8067
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8068
|
-
sub.callback(res.result);
|
|
8069
|
-
return;
|
|
8070
|
-
}
|
|
8071
|
-
}
|
|
8204
|
+
this._handleServerNotification(subscription, [result]);
|
|
8072
8205
|
}
|
|
8073
8206
|
/**
|
|
8074
8207
|
* Register a callback to be invoked upon slot changes
|
|
@@ -8079,33 +8212,23 @@ class Connection {
|
|
|
8079
8212
|
|
|
8080
8213
|
|
|
8081
8214
|
onSlotChange(callback) {
|
|
8082
|
-
|
|
8083
|
-
this._slotSubscriptions[id] = {
|
|
8215
|
+
return this._makeSubscription({
|
|
8084
8216
|
callback,
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
return id;
|
|
8217
|
+
method: 'slotSubscribe',
|
|
8218
|
+
unsubscribeMethod: 'slotUnsubscribe'
|
|
8219
|
+
}, []
|
|
8220
|
+
/* args */
|
|
8221
|
+
);
|
|
8091
8222
|
}
|
|
8092
8223
|
/**
|
|
8093
8224
|
* Deregister a slot notification callback
|
|
8094
8225
|
*
|
|
8095
|
-
* @param id subscription id to deregister
|
|
8226
|
+
* @param id client subscription id to deregister
|
|
8096
8227
|
*/
|
|
8097
8228
|
|
|
8098
8229
|
|
|
8099
|
-
async removeSlotChangeListener(
|
|
8100
|
-
|
|
8101
|
-
const subInfo = this._slotSubscriptions[id];
|
|
8102
|
-
delete this._slotSubscriptions[id];
|
|
8103
|
-
await this._unsubscribe(subInfo, 'slotUnsubscribe');
|
|
8104
|
-
|
|
8105
|
-
this._updateSubscriptions();
|
|
8106
|
-
} else {
|
|
8107
|
-
console.warn(createSubscriptionWarningMessage(id, 'slot change'));
|
|
8108
|
-
}
|
|
8230
|
+
async removeSlotChangeListener(clientSubscriptionId) {
|
|
8231
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
|
|
8109
8232
|
}
|
|
8110
8233
|
/**
|
|
8111
8234
|
* @internal
|
|
@@ -8113,14 +8236,12 @@ class Connection {
|
|
|
8113
8236
|
|
|
8114
8237
|
|
|
8115
8238
|
_wsOnSlotUpdatesNotification(notification) {
|
|
8116
|
-
const
|
|
8239
|
+
const {
|
|
8240
|
+
result,
|
|
8241
|
+
subscription
|
|
8242
|
+
} = superstruct.create(notification, SlotUpdateNotificationResult);
|
|
8117
8243
|
|
|
8118
|
-
|
|
8119
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8120
|
-
sub.callback(res.result);
|
|
8121
|
-
return;
|
|
8122
|
-
}
|
|
8123
|
-
}
|
|
8244
|
+
this._handleServerNotification(subscription, [result]);
|
|
8124
8245
|
}
|
|
8125
8246
|
/**
|
|
8126
8247
|
* Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
|
|
@@ -8132,32 +8253,36 @@ class Connection {
|
|
|
8132
8253
|
|
|
8133
8254
|
|
|
8134
8255
|
onSlotUpdate(callback) {
|
|
8135
|
-
|
|
8136
|
-
this._slotUpdateSubscriptions[id] = {
|
|
8256
|
+
return this._makeSubscription({
|
|
8137
8257
|
callback,
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
return id;
|
|
8258
|
+
method: 'slotsUpdatesSubscribe',
|
|
8259
|
+
unsubscribeMethod: 'slotsUpdatesUnsubscribe'
|
|
8260
|
+
}, []
|
|
8261
|
+
/* args */
|
|
8262
|
+
);
|
|
8144
8263
|
}
|
|
8145
8264
|
/**
|
|
8146
8265
|
* Deregister a slot update notification callback
|
|
8147
8266
|
*
|
|
8148
|
-
* @param id subscription id to deregister
|
|
8267
|
+
* @param id client subscription id to deregister
|
|
8149
8268
|
*/
|
|
8150
8269
|
|
|
8151
8270
|
|
|
8152
|
-
async removeSlotUpdateListener(
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8271
|
+
async removeSlotUpdateListener(clientSubscriptionId) {
|
|
8272
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
|
|
8273
|
+
}
|
|
8274
|
+
/**
|
|
8275
|
+
* @internal
|
|
8276
|
+
*/
|
|
8157
8277
|
|
|
8158
|
-
|
|
8278
|
+
|
|
8279
|
+
async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
|
|
8280
|
+
const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
8281
|
+
|
|
8282
|
+
if (dispose) {
|
|
8283
|
+
await dispose();
|
|
8159
8284
|
} else {
|
|
8160
|
-
console.warn(
|
|
8285
|
+
console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
|
|
8161
8286
|
}
|
|
8162
8287
|
}
|
|
8163
8288
|
|
|
@@ -8204,30 +8329,34 @@ class Connection {
|
|
|
8204
8329
|
|
|
8205
8330
|
|
|
8206
8331
|
_wsOnSignatureNotification(notification) {
|
|
8207
|
-
const
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8332
|
+
const {
|
|
8333
|
+
result,
|
|
8334
|
+
subscription
|
|
8335
|
+
} = superstruct.create(notification, SignatureNotificationResult);
|
|
8336
|
+
|
|
8337
|
+
if (result.value !== 'receivedSignature') {
|
|
8338
|
+
/**
|
|
8339
|
+
* Special case.
|
|
8340
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
8341
|
+
* subscription on the server side. We need to track which of these
|
|
8342
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
8343
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
8344
|
+
* (in which case we must tear down the server subscription) or an
|
|
8345
|
+
* already-processed signature (in which case the client can simply
|
|
8346
|
+
* clear out the subscription locally without telling the server).
|
|
8347
|
+
*
|
|
8348
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
8349
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
8350
|
+
*/
|
|
8351
|
+
this._subscriptionsAutoDisposedByRpc.add(subscription);
|
|
8352
|
+
}
|
|
8353
|
+
|
|
8354
|
+
this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{
|
|
8355
|
+
type: 'received'
|
|
8356
|
+
}, result.context] : [{
|
|
8357
|
+
type: 'status',
|
|
8358
|
+
result: result.value
|
|
8359
|
+
}, result.context]);
|
|
8231
8360
|
}
|
|
8232
8361
|
/**
|
|
8233
8362
|
* Register a callback to be invoked upon signature updates
|
|
@@ -8240,23 +8369,26 @@ class Connection {
|
|
|
8240
8369
|
|
|
8241
8370
|
|
|
8242
8371
|
onSignature(signature, callback, commitment) {
|
|
8243
|
-
const
|
|
8244
|
-
|
|
8245
|
-
|
|
8372
|
+
const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8373
|
+
);
|
|
8374
|
+
|
|
8375
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
8246
8376
|
callback: (notification, context) => {
|
|
8247
8377
|
if (notification.type === 'status') {
|
|
8248
|
-
callback(notification.result, context);
|
|
8378
|
+
callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
8379
|
+
// so no need to explicitly send an unsubscribe message.
|
|
8380
|
+
|
|
8381
|
+
try {
|
|
8382
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
8383
|
+
} catch {// Already removed.
|
|
8384
|
+
}
|
|
8249
8385
|
}
|
|
8250
8386
|
},
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
subscriptionId: null
|
|
8255
|
-
};
|
|
8256
|
-
|
|
8257
|
-
this._updateSubscriptions();
|
|
8387
|
+
method: 'signatureSubscribe',
|
|
8388
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
8389
|
+
}, args);
|
|
8258
8390
|
|
|
8259
|
-
return
|
|
8391
|
+
return clientSubscriptionId;
|
|
8260
8392
|
}
|
|
8261
8393
|
/**
|
|
8262
8394
|
* Register a callback to be invoked when a transaction is
|
|
@@ -8271,35 +8403,43 @@ class Connection {
|
|
|
8271
8403
|
|
|
8272
8404
|
|
|
8273
8405
|
onSignatureWithOptions(signature, callback, options) {
|
|
8274
|
-
const
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
options
|
|
8279
|
-
|
|
8406
|
+
const {
|
|
8407
|
+
commitment,
|
|
8408
|
+
...extra
|
|
8409
|
+
} = { ...options,
|
|
8410
|
+
commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8411
|
+
|
|
8280
8412
|
};
|
|
8281
8413
|
|
|
8282
|
-
this.
|
|
8414
|
+
const args = this._buildArgs([signature], commitment, undefined
|
|
8415
|
+
/* encoding */
|
|
8416
|
+
, extra);
|
|
8417
|
+
|
|
8418
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
8419
|
+
callback: (notification, context) => {
|
|
8420
|
+
callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
8421
|
+
// so no need to explicitly send an unsubscribe message.
|
|
8422
|
+
|
|
8423
|
+
try {
|
|
8424
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
8425
|
+
} catch {// Already removed.
|
|
8426
|
+
}
|
|
8427
|
+
},
|
|
8428
|
+
method: 'signatureSubscribe',
|
|
8429
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
8430
|
+
}, args);
|
|
8283
8431
|
|
|
8284
|
-
return
|
|
8432
|
+
return clientSubscriptionId;
|
|
8285
8433
|
}
|
|
8286
8434
|
/**
|
|
8287
8435
|
* Deregister a signature notification callback
|
|
8288
8436
|
*
|
|
8289
|
-
* @param id subscription id to deregister
|
|
8437
|
+
* @param id client subscription id to deregister
|
|
8290
8438
|
*/
|
|
8291
8439
|
|
|
8292
8440
|
|
|
8293
|
-
async removeSignatureListener(
|
|
8294
|
-
|
|
8295
|
-
const subInfo = this._signatureSubscriptions[id];
|
|
8296
|
-
delete this._signatureSubscriptions[id];
|
|
8297
|
-
await this._unsubscribe(subInfo, 'signatureUnsubscribe');
|
|
8298
|
-
|
|
8299
|
-
this._updateSubscriptions();
|
|
8300
|
-
} else {
|
|
8301
|
-
console.warn(createSubscriptionWarningMessage(id, 'signature result'));
|
|
8302
|
-
}
|
|
8441
|
+
async removeSignatureListener(clientSubscriptionId) {
|
|
8442
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
|
|
8303
8443
|
}
|
|
8304
8444
|
/**
|
|
8305
8445
|
* @internal
|
|
@@ -8307,14 +8447,12 @@ class Connection {
|
|
|
8307
8447
|
|
|
8308
8448
|
|
|
8309
8449
|
_wsOnRootNotification(notification) {
|
|
8310
|
-
const
|
|
8450
|
+
const {
|
|
8451
|
+
result,
|
|
8452
|
+
subscription
|
|
8453
|
+
} = superstruct.create(notification, RootNotificationResult);
|
|
8311
8454
|
|
|
8312
|
-
|
|
8313
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8314
|
-
sub.callback(res.result);
|
|
8315
|
-
return;
|
|
8316
|
-
}
|
|
8317
|
-
}
|
|
8455
|
+
this._handleServerNotification(subscription, [result]);
|
|
8318
8456
|
}
|
|
8319
8457
|
/**
|
|
8320
8458
|
* Register a callback to be invoked upon root changes
|
|
@@ -8325,33 +8463,23 @@ class Connection {
|
|
|
8325
8463
|
|
|
8326
8464
|
|
|
8327
8465
|
onRootChange(callback) {
|
|
8328
|
-
|
|
8329
|
-
this._rootSubscriptions[id] = {
|
|
8466
|
+
return this._makeSubscription({
|
|
8330
8467
|
callback,
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
return id;
|
|
8468
|
+
method: 'rootSubscribe',
|
|
8469
|
+
unsubscribeMethod: 'rootUnsubscribe'
|
|
8470
|
+
}, []
|
|
8471
|
+
/* args */
|
|
8472
|
+
);
|
|
8337
8473
|
}
|
|
8338
8474
|
/**
|
|
8339
8475
|
* Deregister a root notification callback
|
|
8340
8476
|
*
|
|
8341
|
-
* @param id subscription id to deregister
|
|
8477
|
+
* @param id client subscription id to deregister
|
|
8342
8478
|
*/
|
|
8343
8479
|
|
|
8344
8480
|
|
|
8345
|
-
async removeRootChangeListener(
|
|
8346
|
-
|
|
8347
|
-
const subInfo = this._rootSubscriptions[id];
|
|
8348
|
-
delete this._rootSubscriptions[id];
|
|
8349
|
-
await this._unsubscribe(subInfo, 'rootUnsubscribe');
|
|
8350
|
-
|
|
8351
|
-
this._updateSubscriptions();
|
|
8352
|
-
} else {
|
|
8353
|
-
console.warn(createSubscriptionWarningMessage(id, 'root change'));
|
|
8354
|
-
}
|
|
8481
|
+
async removeRootChangeListener(clientSubscriptionId) {
|
|
8482
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
|
|
8355
8483
|
}
|
|
8356
8484
|
|
|
8357
8485
|
}
|
|
@@ -10055,6 +10183,7 @@ exports.NONCE_ACCOUNT_LENGTH = NONCE_ACCOUNT_LENGTH;
|
|
|
10055
10183
|
exports.NonceAccount = NonceAccount;
|
|
10056
10184
|
exports.PACKET_DATA_SIZE = PACKET_DATA_SIZE;
|
|
10057
10185
|
exports.PublicKey = PublicKey;
|
|
10186
|
+
exports.SIGNATURE_LENGTH_IN_BYTES = SIGNATURE_LENGTH_IN_BYTES;
|
|
10058
10187
|
exports.SOLANA_SCHEMA = SOLANA_SCHEMA;
|
|
10059
10188
|
exports.STAKE_CONFIG_ID = STAKE_CONFIG_ID;
|
|
10060
10189
|
exports.STAKE_INSTRUCTION_LAYOUTS = STAKE_INSTRUCTION_LAYOUTS;
|