@solana/web3.js 1.41.1 → 1.41.4
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 +593 -375
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +639 -422
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +610 -378
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +77 -26
- package/lib/index.esm.js +657 -426
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +12157 -12148
- 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 +9 -5
- package/src/connection.ts +657 -486
- package/src/index.ts +1 -0
- package/src/system-program.ts +39 -10
package/lib/index.browser.cjs.js
CHANGED
|
@@ -3099,6 +3099,92 @@ function sleep(ms) {
|
|
|
3099
3099
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
3100
3100
|
}
|
|
3101
3101
|
|
|
3102
|
+
const encodeDecode = (layout) => {
|
|
3103
|
+
const decode = layout.decode.bind(layout);
|
|
3104
|
+
const encode = layout.encode.bind(layout);
|
|
3105
|
+
return { decode, encode };
|
|
3106
|
+
};
|
|
3107
|
+
|
|
3108
|
+
var browser = {};
|
|
3109
|
+
|
|
3110
|
+
Object.defineProperty(browser, "__esModule", { value: true });
|
|
3111
|
+
/**
|
|
3112
|
+
* Convert a little-endian buffer into a BigInt.
|
|
3113
|
+
* @param buf The little-endian buffer to convert
|
|
3114
|
+
* @returns A BigInt with the little-endian representation of buf.
|
|
3115
|
+
*/
|
|
3116
|
+
function toBigIntLE(buf) {
|
|
3117
|
+
{
|
|
3118
|
+
const reversed = Buffer.from(buf);
|
|
3119
|
+
reversed.reverse();
|
|
3120
|
+
const hex = reversed.toString('hex');
|
|
3121
|
+
if (hex.length === 0) {
|
|
3122
|
+
return BigInt(0);
|
|
3123
|
+
}
|
|
3124
|
+
return BigInt(`0x${hex}`);
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
var toBigIntLE_1 = browser.toBigIntLE = toBigIntLE;
|
|
3128
|
+
/**
|
|
3129
|
+
* Convert a big-endian buffer into a BigInt
|
|
3130
|
+
* @param buf The big-endian buffer to convert.
|
|
3131
|
+
* @returns A BigInt with the big-endian representation of buf.
|
|
3132
|
+
*/
|
|
3133
|
+
function toBigIntBE(buf) {
|
|
3134
|
+
{
|
|
3135
|
+
const hex = buf.toString('hex');
|
|
3136
|
+
if (hex.length === 0) {
|
|
3137
|
+
return BigInt(0);
|
|
3138
|
+
}
|
|
3139
|
+
return BigInt(`0x${hex}`);
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
browser.toBigIntBE = toBigIntBE;
|
|
3143
|
+
/**
|
|
3144
|
+
* Convert a BigInt to a little-endian buffer.
|
|
3145
|
+
* @param num The BigInt to convert.
|
|
3146
|
+
* @param width The number of bytes that the resulting buffer should be.
|
|
3147
|
+
* @returns A little-endian buffer representation of num.
|
|
3148
|
+
*/
|
|
3149
|
+
function toBufferLE(num, width) {
|
|
3150
|
+
{
|
|
3151
|
+
const hex = num.toString(16);
|
|
3152
|
+
const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex');
|
|
3153
|
+
buffer.reverse();
|
|
3154
|
+
return buffer;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
var toBufferLE_1 = browser.toBufferLE = toBufferLE;
|
|
3158
|
+
/**
|
|
3159
|
+
* Convert a BigInt to a big-endian buffer.
|
|
3160
|
+
* @param num The BigInt to convert.
|
|
3161
|
+
* @param width The number of bytes that the resulting buffer should be.
|
|
3162
|
+
* @returns A big-endian buffer representation of num.
|
|
3163
|
+
*/
|
|
3164
|
+
function toBufferBE(num, width) {
|
|
3165
|
+
{
|
|
3166
|
+
const hex = num.toString(16);
|
|
3167
|
+
return Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex');
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
browser.toBufferBE = toBufferBE;
|
|
3171
|
+
|
|
3172
|
+
const bigInt = (length) => (property) => {
|
|
3173
|
+
const layout = BufferLayout.blob(length, property);
|
|
3174
|
+
const { encode, decode } = encodeDecode(layout);
|
|
3175
|
+
const bigIntLayout = layout;
|
|
3176
|
+
bigIntLayout.decode = (buffer, offset) => {
|
|
3177
|
+
const src = decode(buffer, offset);
|
|
3178
|
+
return toBigIntLE_1(Buffer.from(src));
|
|
3179
|
+
};
|
|
3180
|
+
bigIntLayout.encode = (bigInt, buffer, offset) => {
|
|
3181
|
+
const src = toBufferLE_1(bigInt, length);
|
|
3182
|
+
return encode(src, buffer, offset);
|
|
3183
|
+
};
|
|
3184
|
+
return bigIntLayout;
|
|
3185
|
+
};
|
|
3186
|
+
const u64 = bigInt(8);
|
|
3187
|
+
|
|
3102
3188
|
/**
|
|
3103
3189
|
* Populate a buffer of instruction data using an InstructionType
|
|
3104
3190
|
* @internal
|
|
@@ -3488,7 +3574,7 @@ const SYSTEM_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
3488
3574
|
},
|
|
3489
3575
|
Transfer: {
|
|
3490
3576
|
index: 2,
|
|
3491
|
-
layout: BufferLayout__namespace.struct([BufferLayout__namespace.u32('instruction'),
|
|
3577
|
+
layout: BufferLayout__namespace.struct([BufferLayout__namespace.u32('instruction'), u64('lamports')])
|
|
3492
3578
|
},
|
|
3493
3579
|
CreateWithSeed: {
|
|
3494
3580
|
index: 3,
|
|
@@ -3524,7 +3610,7 @@ const SYSTEM_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
3524
3610
|
},
|
|
3525
3611
|
TransferWithSeed: {
|
|
3526
3612
|
index: 11,
|
|
3527
|
-
layout: BufferLayout__namespace.struct([BufferLayout__namespace.u32('instruction'),
|
|
3613
|
+
layout: BufferLayout__namespace.struct([BufferLayout__namespace.u32('instruction'), u64('lamports'), rustString('seed'), publicKey('programId')])
|
|
3528
3614
|
}
|
|
3529
3615
|
});
|
|
3530
3616
|
/**
|
|
@@ -3577,7 +3663,7 @@ class SystemProgram {
|
|
|
3577
3663
|
if ('basePubkey' in params) {
|
|
3578
3664
|
const type = SYSTEM_INSTRUCTION_LAYOUTS.TransferWithSeed;
|
|
3579
3665
|
data = encodeData(type, {
|
|
3580
|
-
lamports: params.lamports,
|
|
3666
|
+
lamports: BigInt(params.lamports),
|
|
3581
3667
|
seed: params.seed,
|
|
3582
3668
|
programId: toBuffer(params.programId.toBuffer())
|
|
3583
3669
|
});
|
|
@@ -3597,7 +3683,7 @@ class SystemProgram {
|
|
|
3597
3683
|
} else {
|
|
3598
3684
|
const type = SYSTEM_INSTRUCTION_LAYOUTS.Transfer;
|
|
3599
3685
|
data = encodeData(type, {
|
|
3600
|
-
lamports: params.lamports
|
|
3686
|
+
lamports: BigInt(params.lamports)
|
|
3601
3687
|
});
|
|
3602
3688
|
keys = [{
|
|
3603
3689
|
pubkey: params.fromPubkey,
|
|
@@ -4793,6 +4879,82 @@ module.exports = exports;
|
|
|
4793
4879
|
|
|
4794
4880
|
var crossFetch = /*@__PURE__*/getDefaultExportFromCjs(browserPonyfill.exports);
|
|
4795
4881
|
|
|
4882
|
+
var objToString = Object.prototype.toString;
|
|
4883
|
+
var objKeys = Object.keys || function(obj) {
|
|
4884
|
+
var keys = [];
|
|
4885
|
+
for (var name in obj) {
|
|
4886
|
+
keys.push(name);
|
|
4887
|
+
}
|
|
4888
|
+
return keys;
|
|
4889
|
+
};
|
|
4890
|
+
|
|
4891
|
+
function stringify(val, isArrayProp) {
|
|
4892
|
+
var i, max, str, keys, key, propVal, toStr;
|
|
4893
|
+
if (val === true) {
|
|
4894
|
+
return "true";
|
|
4895
|
+
}
|
|
4896
|
+
if (val === false) {
|
|
4897
|
+
return "false";
|
|
4898
|
+
}
|
|
4899
|
+
switch (typeof val) {
|
|
4900
|
+
case "object":
|
|
4901
|
+
if (val === null) {
|
|
4902
|
+
return null;
|
|
4903
|
+
} else if (val.toJSON && typeof val.toJSON === "function") {
|
|
4904
|
+
return stringify(val.toJSON(), isArrayProp);
|
|
4905
|
+
} else {
|
|
4906
|
+
toStr = objToString.call(val);
|
|
4907
|
+
if (toStr === "[object Array]") {
|
|
4908
|
+
str = '[';
|
|
4909
|
+
max = val.length - 1;
|
|
4910
|
+
for(i = 0; i < max; i++) {
|
|
4911
|
+
str += stringify(val[i], true) + ',';
|
|
4912
|
+
}
|
|
4913
|
+
if (max > -1) {
|
|
4914
|
+
str += stringify(val[i], true);
|
|
4915
|
+
}
|
|
4916
|
+
return str + ']';
|
|
4917
|
+
} else if (toStr === "[object Object]") {
|
|
4918
|
+
// only object is left
|
|
4919
|
+
keys = objKeys(val).sort();
|
|
4920
|
+
max = keys.length;
|
|
4921
|
+
str = "";
|
|
4922
|
+
i = 0;
|
|
4923
|
+
while (i < max) {
|
|
4924
|
+
key = keys[i];
|
|
4925
|
+
propVal = stringify(val[key], false);
|
|
4926
|
+
if (propVal !== undefined) {
|
|
4927
|
+
if (str) {
|
|
4928
|
+
str += ',';
|
|
4929
|
+
}
|
|
4930
|
+
str += JSON.stringify(key) + ':' + propVal;
|
|
4931
|
+
}
|
|
4932
|
+
i++;
|
|
4933
|
+
}
|
|
4934
|
+
return '{' + str + '}';
|
|
4935
|
+
} else {
|
|
4936
|
+
return JSON.stringify(val);
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
case "function":
|
|
4940
|
+
case "undefined":
|
|
4941
|
+
return isArrayProp ? null : undefined;
|
|
4942
|
+
case "string":
|
|
4943
|
+
return JSON.stringify(val);
|
|
4944
|
+
default:
|
|
4945
|
+
return isFinite(val) ? val : null;
|
|
4946
|
+
}
|
|
4947
|
+
}
|
|
4948
|
+
|
|
4949
|
+
var fastStableStringify = function(val) {
|
|
4950
|
+
var returnVal = stringify(val, false);
|
|
4951
|
+
if (returnVal !== undefined) {
|
|
4952
|
+
return ''+ returnVal;
|
|
4953
|
+
}
|
|
4954
|
+
};
|
|
4955
|
+
|
|
4956
|
+
var fastStableStringify$1 = fastStableStringify;
|
|
4957
|
+
|
|
4796
4958
|
const MINIMUM_SLOT_PER_EPOCH = 32; // Returns the number of trailing zeros in the binary representation of self.
|
|
4797
4959
|
|
|
4798
4960
|
function trailingZeros(n) {
|
|
@@ -4959,6 +5121,12 @@ const BufferFromRawAccountData = superstruct.coerce(superstruct.instance(buffer.
|
|
|
4959
5121
|
*/
|
|
4960
5122
|
|
|
4961
5123
|
const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
|
|
5124
|
+
/**
|
|
5125
|
+
* HACK.
|
|
5126
|
+
* Copied from rpc-websockets/dist/lib/client.
|
|
5127
|
+
* Otherwise, `yarn build` fails with:
|
|
5128
|
+
* https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
|
|
5129
|
+
*/
|
|
4962
5130
|
|
|
4963
5131
|
/**
|
|
4964
5132
|
* @internal
|
|
@@ -5827,14 +5995,9 @@ const LogsNotificationResult = superstruct.type({
|
|
|
5827
5995
|
* Filter for log subscriptions.
|
|
5828
5996
|
*/
|
|
5829
5997
|
|
|
5830
|
-
function createSubscriptionWarningMessage(id, label) {
|
|
5831
|
-
return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
|
|
5832
|
-
}
|
|
5833
5998
|
/**
|
|
5834
5999
|
* A connection to a fullnode JSON RPC endpoint
|
|
5835
6000
|
*/
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
6001
|
class Connection {
|
|
5839
6002
|
/** @internal */
|
|
5840
6003
|
|
|
@@ -5858,21 +6021,13 @@ class Connection {
|
|
|
5858
6021
|
|
|
5859
6022
|
/** @internal */
|
|
5860
6023
|
|
|
5861
|
-
/** @internal
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
/** @internal */
|
|
5870
|
-
|
|
5871
|
-
/** @internal */
|
|
5872
|
-
|
|
5873
|
-
/** @internal */
|
|
5874
|
-
|
|
5875
|
-
/** @internal */
|
|
6024
|
+
/** @internal
|
|
6025
|
+
* A number that we increment every time an active connection closes.
|
|
6026
|
+
* Used to determine whether the same socket connection that was open
|
|
6027
|
+
* when an async operation started is the same one that's active when
|
|
6028
|
+
* its continuation fires.
|
|
6029
|
+
*
|
|
6030
|
+
*/
|
|
5876
6031
|
|
|
5877
6032
|
/** @internal */
|
|
5878
6033
|
|
|
@@ -5888,7 +6043,19 @@ class Connection {
|
|
|
5888
6043
|
|
|
5889
6044
|
/** @internal */
|
|
5890
6045
|
|
|
5891
|
-
/**
|
|
6046
|
+
/**
|
|
6047
|
+
* Special case.
|
|
6048
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
6049
|
+
* subscription on the server side. We need to track which of these
|
|
6050
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
6051
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
6052
|
+
* (in which case we must tear down the server subscription) or an
|
|
6053
|
+
* already-processed signature (in which case the client can simply
|
|
6054
|
+
* clear out the subscription locally without telling the server).
|
|
6055
|
+
*
|
|
6056
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
6057
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
6058
|
+
*/
|
|
5892
6059
|
|
|
5893
6060
|
/** @internal */
|
|
5894
6061
|
|
|
@@ -5910,6 +6077,7 @@ class Connection {
|
|
|
5910
6077
|
this._rpcWebSocketConnected = false;
|
|
5911
6078
|
this._rpcWebSocketHeartbeat = null;
|
|
5912
6079
|
this._rpcWebSocketIdleTimeout = null;
|
|
6080
|
+
this._rpcWebSocketGeneration = 0;
|
|
5913
6081
|
this._disableBlockhashCaching = false;
|
|
5914
6082
|
this._pollingBlockhash = false;
|
|
5915
6083
|
this._blockhashInfo = {
|
|
@@ -5918,20 +6086,11 @@ class Connection {
|
|
|
5918
6086
|
transactionSignatures: [],
|
|
5919
6087
|
simulatedSignatures: []
|
|
5920
6088
|
};
|
|
5921
|
-
this.
|
|
5922
|
-
this.
|
|
5923
|
-
this.
|
|
5924
|
-
this.
|
|
5925
|
-
this.
|
|
5926
|
-
this._rootSubscriptions = {};
|
|
5927
|
-
this._signatureSubscriptionCounter = 0;
|
|
5928
|
-
this._signatureSubscriptions = {};
|
|
5929
|
-
this._slotSubscriptionCounter = 0;
|
|
5930
|
-
this._slotSubscriptions = {};
|
|
5931
|
-
this._logsSubscriptionCounter = 0;
|
|
5932
|
-
this._logsSubscriptions = {};
|
|
5933
|
-
this._slotUpdateSubscriptionCounter = 0;
|
|
5934
|
-
this._slotUpdateSubscriptions = {};
|
|
6089
|
+
this._nextClientSubscriptionId = 0;
|
|
6090
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
6091
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
6092
|
+
this._subscriptionsByHash = {};
|
|
6093
|
+
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
5935
6094
|
let url = new URL(endpoint);
|
|
5936
6095
|
const useHttps = url.protocol === 'https:';
|
|
5937
6096
|
let wsEndpoint;
|
|
@@ -7699,6 +7858,8 @@ class Connection {
|
|
|
7699
7858
|
|
|
7700
7859
|
|
|
7701
7860
|
_wsOnClose(code) {
|
|
7861
|
+
this._rpcWebSocketGeneration++;
|
|
7862
|
+
|
|
7702
7863
|
if (this._rpcWebSocketHeartbeat) {
|
|
7703
7864
|
clearInterval(this._rpcWebSocketHeartbeat);
|
|
7704
7865
|
this._rpcWebSocketHeartbeat = null;
|
|
@@ -7712,85 +7873,20 @@ class Connection {
|
|
|
7712
7873
|
} // implicit close, prepare subscriptions for auto-reconnect
|
|
7713
7874
|
|
|
7714
7875
|
|
|
7715
|
-
this.
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
async _subscribe(sub, rpcMethod, rpcArgs) {
|
|
7723
|
-
if (sub.subscriptionId == null) {
|
|
7724
|
-
sub.subscriptionId = 'subscribing';
|
|
7725
|
-
|
|
7726
|
-
try {
|
|
7727
|
-
const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
|
|
7728
|
-
|
|
7729
|
-
if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
|
|
7730
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7731
|
-
sub.subscriptionId = id;
|
|
7732
|
-
}
|
|
7733
|
-
} catch (err) {
|
|
7734
|
-
if (sub.subscriptionId === 'subscribing') {
|
|
7735
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7736
|
-
sub.subscriptionId = null;
|
|
7737
|
-
}
|
|
7738
|
-
|
|
7739
|
-
if (err instanceof Error) {
|
|
7740
|
-
console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
|
|
7741
|
-
}
|
|
7742
|
-
}
|
|
7743
|
-
}
|
|
7744
|
-
}
|
|
7745
|
-
/**
|
|
7746
|
-
* @internal
|
|
7747
|
-
*/
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
async _unsubscribe(sub, rpcMethod) {
|
|
7751
|
-
const subscriptionId = sub.subscriptionId;
|
|
7752
|
-
|
|
7753
|
-
if (subscriptionId != null && typeof subscriptionId != 'string') {
|
|
7754
|
-
const unsubscribeId = subscriptionId;
|
|
7755
|
-
|
|
7756
|
-
try {
|
|
7757
|
-
await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
|
|
7758
|
-
} catch (err) {
|
|
7759
|
-
if (err instanceof Error) {
|
|
7760
|
-
console.error(`${rpcMethod} error:`, err.message);
|
|
7761
|
-
}
|
|
7762
|
-
}
|
|
7763
|
-
}
|
|
7764
|
-
}
|
|
7765
|
-
/**
|
|
7766
|
-
* @internal
|
|
7767
|
-
*/
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
_resetSubscriptions() {
|
|
7771
|
-
Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7772
|
-
Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7773
|
-
Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7774
|
-
Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7775
|
-
Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7776
|
-
Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7777
|
-
Object.values(this._slotUpdateSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7876
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
7877
|
+
Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
|
|
7878
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7879
|
+
state: 'pending'
|
|
7880
|
+
};
|
|
7881
|
+
});
|
|
7778
7882
|
}
|
|
7779
7883
|
/**
|
|
7780
7884
|
* @internal
|
|
7781
7885
|
*/
|
|
7782
7886
|
|
|
7783
7887
|
|
|
7784
|
-
_updateSubscriptions() {
|
|
7785
|
-
|
|
7786
|
-
const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
|
|
7787
|
-
const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
|
|
7788
|
-
const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
|
|
7789
|
-
const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
|
|
7790
|
-
const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
|
|
7791
|
-
const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
|
|
7792
|
-
|
|
7793
|
-
if (accountKeys.length === 0 && programKeys.length === 0 && slotKeys.length === 0 && slotUpdateKeys.length === 0 && signatureKeys.length === 0 && rootKeys.length === 0 && logsKeys.length === 0) {
|
|
7888
|
+
async _updateSubscriptions() {
|
|
7889
|
+
if (Object.keys(this._subscriptionsByHash).length === 0) {
|
|
7794
7890
|
if (this._rpcWebSocketConnected) {
|
|
7795
7891
|
this._rpcWebSocketConnected = false;
|
|
7796
7892
|
this._rpcWebSocketIdleTimeout = setTimeout(() => {
|
|
@@ -7822,60 +7918,167 @@ class Connection {
|
|
|
7822
7918
|
return;
|
|
7823
7919
|
}
|
|
7824
7920
|
|
|
7825
|
-
|
|
7826
|
-
const sub = this._accountChangeSubscriptions[id];
|
|
7827
|
-
|
|
7828
|
-
this._subscribe(sub, 'accountSubscribe', this._buildArgs([sub.publicKey], sub.commitment, 'base64'));
|
|
7829
|
-
}
|
|
7921
|
+
const activeWebSocketGeneration = this._rpcWebSocketGeneration;
|
|
7830
7922
|
|
|
7831
|
-
|
|
7832
|
-
|
|
7923
|
+
const isCurrentConnectionStillActive = () => {
|
|
7924
|
+
return activeWebSocketGeneration === this._rpcWebSocketGeneration;
|
|
7925
|
+
};
|
|
7833
7926
|
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7927
|
+
await Promise.all( // Don't be tempted to change this to `Object.entries`. We call
|
|
7928
|
+
// `_updateSubscriptions` recursively when processing the state,
|
|
7929
|
+
// so it's important that we look up the *current* version of
|
|
7930
|
+
// each subscription, every time we process a hash.
|
|
7931
|
+
Object.keys(this._subscriptionsByHash).map(async hash => {
|
|
7932
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7838
7933
|
|
|
7839
|
-
|
|
7840
|
-
|
|
7934
|
+
if (subscription === undefined) {
|
|
7935
|
+
// This entry has since been deleted. Skip.
|
|
7936
|
+
return;
|
|
7937
|
+
}
|
|
7841
7938
|
|
|
7842
|
-
|
|
7843
|
-
|
|
7939
|
+
switch (subscription.state) {
|
|
7940
|
+
case 'pending':
|
|
7941
|
+
case 'unsubscribed':
|
|
7942
|
+
if (subscription.callbacks.size === 0) {
|
|
7943
|
+
/**
|
|
7944
|
+
* You can end up here when:
|
|
7945
|
+
*
|
|
7946
|
+
* - a subscription has recently unsubscribed
|
|
7947
|
+
* without having new callbacks added to it
|
|
7948
|
+
* while the unsubscribe was in flight, or
|
|
7949
|
+
* - when a pending subscription has its
|
|
7950
|
+
* listeners removed before a request was
|
|
7951
|
+
* sent to the server.
|
|
7952
|
+
*
|
|
7953
|
+
* Being that nobody is interested in this
|
|
7954
|
+
* subscription any longer, delete it.
|
|
7955
|
+
*/
|
|
7956
|
+
delete this._subscriptionsByHash[hash];
|
|
7957
|
+
|
|
7958
|
+
if (subscription.state === 'unsubscribed') {
|
|
7959
|
+
delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId];
|
|
7960
|
+
}
|
|
7844
7961
|
|
|
7845
|
-
|
|
7846
|
-
|
|
7962
|
+
await this._updateSubscriptions();
|
|
7963
|
+
return;
|
|
7964
|
+
}
|
|
7847
7965
|
|
|
7848
|
-
|
|
7849
|
-
|
|
7966
|
+
await (async () => {
|
|
7967
|
+
const {
|
|
7968
|
+
args,
|
|
7969
|
+
method
|
|
7970
|
+
} = subscription;
|
|
7850
7971
|
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7972
|
+
try {
|
|
7973
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7974
|
+
state: 'subscribing'
|
|
7975
|
+
};
|
|
7976
|
+
const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
|
|
7977
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7978
|
+
serverSubscriptionId,
|
|
7979
|
+
state: 'subscribed'
|
|
7980
|
+
};
|
|
7981
|
+
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
|
|
7982
|
+
await this._updateSubscriptions();
|
|
7983
|
+
} catch (e) {
|
|
7984
|
+
if (e instanceof Error) {
|
|
7985
|
+
console.error(`${method} error for argument`, args, e.message);
|
|
7986
|
+
}
|
|
7987
|
+
|
|
7988
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7989
|
+
return;
|
|
7990
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7855
7991
|
|
|
7856
|
-
this._subscribe(sub, 'signatureSubscribe', args);
|
|
7857
|
-
}
|
|
7858
7992
|
|
|
7859
|
-
|
|
7860
|
-
|
|
7993
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7994
|
+
state: 'pending'
|
|
7995
|
+
};
|
|
7996
|
+
await this._updateSubscriptions();
|
|
7997
|
+
}
|
|
7998
|
+
})();
|
|
7999
|
+
break;
|
|
7861
8000
|
|
|
7862
|
-
|
|
7863
|
-
|
|
8001
|
+
case 'subscribed':
|
|
8002
|
+
if (subscription.callbacks.size === 0) {
|
|
8003
|
+
// By the time we successfully set up a subscription
|
|
8004
|
+
// with the server, the client stopped caring about it.
|
|
8005
|
+
// Tear it down now.
|
|
8006
|
+
await (async () => {
|
|
8007
|
+
const {
|
|
8008
|
+
serverSubscriptionId,
|
|
8009
|
+
unsubscribeMethod
|
|
8010
|
+
} = subscription;
|
|
8011
|
+
|
|
8012
|
+
if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) {
|
|
8013
|
+
/**
|
|
8014
|
+
* Special case.
|
|
8015
|
+
* If we're dealing with a subscription that has been auto-
|
|
8016
|
+
* disposed by the RPC, then we can skip the RPC call to
|
|
8017
|
+
* tear down the subscription here.
|
|
8018
|
+
*
|
|
8019
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
8020
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
8021
|
+
*/
|
|
8022
|
+
this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
|
|
8023
|
+
} else {
|
|
8024
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
8025
|
+
state: 'unsubscribing'
|
|
8026
|
+
};
|
|
8027
|
+
|
|
8028
|
+
try {
|
|
8029
|
+
await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
|
|
8030
|
+
} catch (e) {
|
|
8031
|
+
if (e instanceof Error) {
|
|
8032
|
+
console.error(`${unsubscribeMethod} error:`, e.message);
|
|
8033
|
+
}
|
|
8034
|
+
|
|
8035
|
+
if (!isCurrentConnectionStillActive()) {
|
|
8036
|
+
return;
|
|
8037
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
8038
|
+
|
|
8039
|
+
|
|
8040
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
8041
|
+
state: 'subscribed'
|
|
8042
|
+
};
|
|
8043
|
+
await this._updateSubscriptions();
|
|
8044
|
+
return;
|
|
8045
|
+
}
|
|
8046
|
+
}
|
|
7864
8047
|
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
8048
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
8049
|
+
state: 'unsubscribed'
|
|
8050
|
+
};
|
|
8051
|
+
await this._updateSubscriptions();
|
|
8052
|
+
})();
|
|
8053
|
+
}
|
|
7868
8054
|
|
|
7869
|
-
|
|
7870
|
-
filter = {
|
|
7871
|
-
mentions: [sub.filter.toString()]
|
|
7872
|
-
};
|
|
7873
|
-
} else {
|
|
7874
|
-
filter = sub.filter;
|
|
8055
|
+
break;
|
|
7875
8056
|
}
|
|
8057
|
+
}));
|
|
8058
|
+
}
|
|
8059
|
+
/**
|
|
8060
|
+
* @internal
|
|
8061
|
+
*/
|
|
8062
|
+
|
|
7876
8063
|
|
|
7877
|
-
|
|
8064
|
+
_handleServerNotification(serverSubscriptionId, callbackArgs) {
|
|
8065
|
+
const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
|
|
8066
|
+
|
|
8067
|
+
if (callbacks === undefined) {
|
|
8068
|
+
return;
|
|
7878
8069
|
}
|
|
8070
|
+
|
|
8071
|
+
callbacks.forEach(cb => {
|
|
8072
|
+
try {
|
|
8073
|
+
cb( // I failed to find a way to convince TypeScript that `cb` is of type
|
|
8074
|
+
// `TCallback` which is certainly compatible with `Parameters<TCallback>`.
|
|
8075
|
+
// See https://github.com/microsoft/TypeScript/issues/47615
|
|
8076
|
+
// @ts-ignore
|
|
8077
|
+
...callbackArgs);
|
|
8078
|
+
} catch (e) {
|
|
8079
|
+
console.error(e);
|
|
8080
|
+
}
|
|
8081
|
+
});
|
|
7879
8082
|
}
|
|
7880
8083
|
/**
|
|
7881
8084
|
* @internal
|
|
@@ -7883,14 +8086,71 @@ class Connection {
|
|
|
7883
8086
|
|
|
7884
8087
|
|
|
7885
8088
|
_wsOnAccountNotification(notification) {
|
|
7886
|
-
const
|
|
8089
|
+
const {
|
|
8090
|
+
result,
|
|
8091
|
+
subscription
|
|
8092
|
+
} = superstruct.create(notification, AccountNotificationResult);
|
|
7887
8093
|
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
8094
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
8095
|
+
}
|
|
8096
|
+
/**
|
|
8097
|
+
* @internal
|
|
8098
|
+
*/
|
|
8099
|
+
|
|
8100
|
+
|
|
8101
|
+
_makeSubscription(subscriptionConfig,
|
|
8102
|
+
/**
|
|
8103
|
+
* When preparing `args` for a call to `_makeSubscription`, be sure
|
|
8104
|
+
* to carefully apply a default `commitment` property, if necessary.
|
|
8105
|
+
*
|
|
8106
|
+
* - If the user supplied a `commitment` use that.
|
|
8107
|
+
* - Otherwise, if the `Connection::commitment` is set, use that.
|
|
8108
|
+
* - Otherwise, set it to the RPC server default: `finalized`.
|
|
8109
|
+
*
|
|
8110
|
+
* This is extremely important to ensure that these two fundamentally
|
|
8111
|
+
* identical subscriptions produce the same identifying hash:
|
|
8112
|
+
*
|
|
8113
|
+
* - A subscription made without specifying a commitment.
|
|
8114
|
+
* - A subscription made where the commitment specified is the same
|
|
8115
|
+
* as the default applied to the subscription above.
|
|
8116
|
+
*
|
|
8117
|
+
* Example; these two subscriptions must produce the same hash:
|
|
8118
|
+
*
|
|
8119
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'`
|
|
8120
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'` with commitment
|
|
8121
|
+
* `'finalized'`.
|
|
8122
|
+
*
|
|
8123
|
+
* See the 'making a subscription with defaulted params omitted' test
|
|
8124
|
+
* in `connection-subscriptions.ts` for more.
|
|
8125
|
+
*/
|
|
8126
|
+
args) {
|
|
8127
|
+
const clientSubscriptionId = this._nextClientSubscriptionId++;
|
|
8128
|
+
const hash = fastStableStringify$1([subscriptionConfig.method, args], true
|
|
8129
|
+
/* isArrayProp */
|
|
8130
|
+
);
|
|
8131
|
+
const existingSubscription = this._subscriptionsByHash[hash];
|
|
8132
|
+
|
|
8133
|
+
if (existingSubscription === undefined) {
|
|
8134
|
+
this._subscriptionsByHash[hash] = { ...subscriptionConfig,
|
|
8135
|
+
args,
|
|
8136
|
+
callbacks: new Set([subscriptionConfig.callback]),
|
|
8137
|
+
state: 'pending'
|
|
8138
|
+
};
|
|
8139
|
+
} else {
|
|
8140
|
+
existingSubscription.callbacks.add(subscriptionConfig.callback);
|
|
7893
8141
|
}
|
|
8142
|
+
|
|
8143
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
|
|
8144
|
+
delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
8145
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
8146
|
+
assert(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
|
|
8147
|
+
subscription.callbacks.delete(subscriptionConfig.callback);
|
|
8148
|
+
await this._updateSubscriptions();
|
|
8149
|
+
};
|
|
8150
|
+
|
|
8151
|
+
this._updateSubscriptions();
|
|
8152
|
+
|
|
8153
|
+
return clientSubscriptionId;
|
|
7894
8154
|
}
|
|
7895
8155
|
/**
|
|
7896
8156
|
* Register a callback to be invoked whenever the specified account changes
|
|
@@ -7903,35 +8163,24 @@ class Connection {
|
|
|
7903
8163
|
|
|
7904
8164
|
|
|
7905
8165
|
onAccountChange(publicKey, callback, commitment) {
|
|
7906
|
-
const
|
|
7907
|
-
|
|
7908
|
-
publicKey: publicKey.toBase58(),
|
|
7909
|
-
callback,
|
|
7910
|
-
commitment,
|
|
7911
|
-
subscriptionId: null
|
|
7912
|
-
};
|
|
8166
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
8167
|
+
'base64');
|
|
7913
8168
|
|
|
7914
|
-
this.
|
|
7915
|
-
|
|
7916
|
-
|
|
8169
|
+
return this._makeSubscription({
|
|
8170
|
+
callback,
|
|
8171
|
+
method: 'accountSubscribe',
|
|
8172
|
+
unsubscribeMethod: 'accountUnsubscribe'
|
|
8173
|
+
}, args);
|
|
7917
8174
|
}
|
|
7918
8175
|
/**
|
|
7919
8176
|
* Deregister an account notification callback
|
|
7920
8177
|
*
|
|
7921
|
-
* @param id subscription id to deregister
|
|
8178
|
+
* @param id client subscription id to deregister
|
|
7922
8179
|
*/
|
|
7923
8180
|
|
|
7924
8181
|
|
|
7925
|
-
async removeAccountChangeListener(
|
|
7926
|
-
|
|
7927
|
-
const subInfo = this._accountChangeSubscriptions[id];
|
|
7928
|
-
delete this._accountChangeSubscriptions[id];
|
|
7929
|
-
await this._unsubscribe(subInfo, 'accountUnsubscribe');
|
|
7930
|
-
|
|
7931
|
-
this._updateSubscriptions();
|
|
7932
|
-
} else {
|
|
7933
|
-
console.warn(createSubscriptionWarningMessage(id, 'account change'));
|
|
7934
|
-
}
|
|
8182
|
+
async removeAccountChangeListener(clientSubscriptionId) {
|
|
8183
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
|
|
7935
8184
|
}
|
|
7936
8185
|
/**
|
|
7937
8186
|
* @internal
|
|
@@ -7939,21 +8188,15 @@ class Connection {
|
|
|
7939
8188
|
|
|
7940
8189
|
|
|
7941
8190
|
_wsOnProgramAccountNotification(notification) {
|
|
7942
|
-
const
|
|
8191
|
+
const {
|
|
8192
|
+
result,
|
|
8193
|
+
subscription
|
|
8194
|
+
} = superstruct.create(notification, ProgramAccountNotificationResult);
|
|
7943
8195
|
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
context
|
|
7949
|
-
} = res.result;
|
|
7950
|
-
sub.callback({
|
|
7951
|
-
accountId: value.pubkey,
|
|
7952
|
-
accountInfo: value.account
|
|
7953
|
-
}, context);
|
|
7954
|
-
return;
|
|
7955
|
-
}
|
|
7956
|
-
}
|
|
8196
|
+
this._handleServerNotification(subscription, [{
|
|
8197
|
+
accountId: result.value.pubkey,
|
|
8198
|
+
accountInfo: result.value.account
|
|
8199
|
+
}, result.context]);
|
|
7957
8200
|
}
|
|
7958
8201
|
/**
|
|
7959
8202
|
* Register a callback to be invoked whenever accounts owned by the
|
|
@@ -7968,36 +8211,30 @@ class Connection {
|
|
|
7968
8211
|
|
|
7969
8212
|
|
|
7970
8213
|
onProgramAccountChange(programId, callback, commitment, filters) {
|
|
7971
|
-
const
|
|
7972
|
-
|
|
7973
|
-
|
|
8214
|
+
const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
8215
|
+
'base64'
|
|
8216
|
+
/* encoding */
|
|
8217
|
+
, filters ? {
|
|
8218
|
+
filters: filters
|
|
8219
|
+
} : undefined
|
|
8220
|
+
/* extra */
|
|
8221
|
+
);
|
|
8222
|
+
|
|
8223
|
+
return this._makeSubscription({
|
|
7974
8224
|
callback,
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
};
|
|
7979
|
-
|
|
7980
|
-
this._updateSubscriptions();
|
|
7981
|
-
|
|
7982
|
-
return id;
|
|
8225
|
+
method: 'programSubscribe',
|
|
8226
|
+
unsubscribeMethod: 'programUnsubscribe'
|
|
8227
|
+
}, args);
|
|
7983
8228
|
}
|
|
7984
8229
|
/**
|
|
7985
8230
|
* Deregister an account notification callback
|
|
7986
8231
|
*
|
|
7987
|
-
* @param id subscription id to deregister
|
|
8232
|
+
* @param id client subscription id to deregister
|
|
7988
8233
|
*/
|
|
7989
8234
|
|
|
7990
8235
|
|
|
7991
|
-
async removeProgramAccountChangeListener(
|
|
7992
|
-
|
|
7993
|
-
const subInfo = this._programAccountChangeSubscriptions[id];
|
|
7994
|
-
delete this._programAccountChangeSubscriptions[id];
|
|
7995
|
-
await this._unsubscribe(subInfo, 'programUnsubscribe');
|
|
7996
|
-
|
|
7997
|
-
this._updateSubscriptions();
|
|
7998
|
-
} else {
|
|
7999
|
-
console.warn(createSubscriptionWarningMessage(id, 'program account change'));
|
|
8000
|
-
}
|
|
8236
|
+
async removeProgramAccountChangeListener(clientSubscriptionId) {
|
|
8237
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
|
|
8001
8238
|
}
|
|
8002
8239
|
/**
|
|
8003
8240
|
* Registers a callback to be invoked whenever logs are emitted.
|
|
@@ -8005,35 +8242,26 @@ class Connection {
|
|
|
8005
8242
|
|
|
8006
8243
|
|
|
8007
8244
|
onLogs(filter, callback, commitment) {
|
|
8008
|
-
const
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
commitment,
|
|
8013
|
-
subscriptionId: null
|
|
8014
|
-
};
|
|
8015
|
-
|
|
8016
|
-
this._updateSubscriptions();
|
|
8245
|
+
const args = this._buildArgs([typeof filter === 'object' ? {
|
|
8246
|
+
mentions: [filter.toString()]
|
|
8247
|
+
} : filter], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8248
|
+
);
|
|
8017
8249
|
|
|
8018
|
-
return
|
|
8250
|
+
return this._makeSubscription({
|
|
8251
|
+
callback,
|
|
8252
|
+
method: 'logsSubscribe',
|
|
8253
|
+
unsubscribeMethod: 'logsUnsubscribe'
|
|
8254
|
+
}, args);
|
|
8019
8255
|
}
|
|
8020
8256
|
/**
|
|
8021
8257
|
* Deregister a logs callback.
|
|
8022
8258
|
*
|
|
8023
|
-
* @param id subscription id to deregister.
|
|
8259
|
+
* @param id client subscription id to deregister.
|
|
8024
8260
|
*/
|
|
8025
8261
|
|
|
8026
8262
|
|
|
8027
|
-
async removeOnLogsListener(
|
|
8028
|
-
|
|
8029
|
-
const subInfo = this._logsSubscriptions[id];
|
|
8030
|
-
delete this._logsSubscriptions[id];
|
|
8031
|
-
await this._unsubscribe(subInfo, 'logsUnsubscribe');
|
|
8032
|
-
|
|
8033
|
-
this._updateSubscriptions();
|
|
8034
|
-
} else {
|
|
8035
|
-
console.warn(createSubscriptionWarningMessage(id, 'logs'));
|
|
8036
|
-
}
|
|
8263
|
+
async removeOnLogsListener(clientSubscriptionId) {
|
|
8264
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
|
|
8037
8265
|
}
|
|
8038
8266
|
/**
|
|
8039
8267
|
* @internal
|
|
@@ -8041,17 +8269,12 @@ class Connection {
|
|
|
8041
8269
|
|
|
8042
8270
|
|
|
8043
8271
|
_wsOnLogsNotification(notification) {
|
|
8044
|
-
const
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
const sub = this._logsSubscriptions[id];
|
|
8272
|
+
const {
|
|
8273
|
+
result,
|
|
8274
|
+
subscription
|
|
8275
|
+
} = superstruct.create(notification, LogsNotificationResult);
|
|
8049
8276
|
|
|
8050
|
-
|
|
8051
|
-
sub.callback(res.result.value, res.result.context);
|
|
8052
|
-
return;
|
|
8053
|
-
}
|
|
8054
|
-
}
|
|
8277
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
8055
8278
|
}
|
|
8056
8279
|
/**
|
|
8057
8280
|
* @internal
|
|
@@ -8059,14 +8282,12 @@ class Connection {
|
|
|
8059
8282
|
|
|
8060
8283
|
|
|
8061
8284
|
_wsOnSlotNotification(notification) {
|
|
8062
|
-
const
|
|
8285
|
+
const {
|
|
8286
|
+
result,
|
|
8287
|
+
subscription
|
|
8288
|
+
} = superstruct.create(notification, SlotNotificationResult);
|
|
8063
8289
|
|
|
8064
|
-
|
|
8065
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8066
|
-
sub.callback(res.result);
|
|
8067
|
-
return;
|
|
8068
|
-
}
|
|
8069
|
-
}
|
|
8290
|
+
this._handleServerNotification(subscription, [result]);
|
|
8070
8291
|
}
|
|
8071
8292
|
/**
|
|
8072
8293
|
* Register a callback to be invoked upon slot changes
|
|
@@ -8077,33 +8298,23 @@ class Connection {
|
|
|
8077
8298
|
|
|
8078
8299
|
|
|
8079
8300
|
onSlotChange(callback) {
|
|
8080
|
-
|
|
8081
|
-
this._slotSubscriptions[id] = {
|
|
8301
|
+
return this._makeSubscription({
|
|
8082
8302
|
callback,
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
return id;
|
|
8303
|
+
method: 'slotSubscribe',
|
|
8304
|
+
unsubscribeMethod: 'slotUnsubscribe'
|
|
8305
|
+
}, []
|
|
8306
|
+
/* args */
|
|
8307
|
+
);
|
|
8089
8308
|
}
|
|
8090
8309
|
/**
|
|
8091
8310
|
* Deregister a slot notification callback
|
|
8092
8311
|
*
|
|
8093
|
-
* @param id subscription id to deregister
|
|
8312
|
+
* @param id client subscription id to deregister
|
|
8094
8313
|
*/
|
|
8095
8314
|
|
|
8096
8315
|
|
|
8097
|
-
async removeSlotChangeListener(
|
|
8098
|
-
|
|
8099
|
-
const subInfo = this._slotSubscriptions[id];
|
|
8100
|
-
delete this._slotSubscriptions[id];
|
|
8101
|
-
await this._unsubscribe(subInfo, 'slotUnsubscribe');
|
|
8102
|
-
|
|
8103
|
-
this._updateSubscriptions();
|
|
8104
|
-
} else {
|
|
8105
|
-
console.warn(createSubscriptionWarningMessage(id, 'slot change'));
|
|
8106
|
-
}
|
|
8316
|
+
async removeSlotChangeListener(clientSubscriptionId) {
|
|
8317
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
|
|
8107
8318
|
}
|
|
8108
8319
|
/**
|
|
8109
8320
|
* @internal
|
|
@@ -8111,14 +8322,12 @@ class Connection {
|
|
|
8111
8322
|
|
|
8112
8323
|
|
|
8113
8324
|
_wsOnSlotUpdatesNotification(notification) {
|
|
8114
|
-
const
|
|
8325
|
+
const {
|
|
8326
|
+
result,
|
|
8327
|
+
subscription
|
|
8328
|
+
} = superstruct.create(notification, SlotUpdateNotificationResult);
|
|
8115
8329
|
|
|
8116
|
-
|
|
8117
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8118
|
-
sub.callback(res.result);
|
|
8119
|
-
return;
|
|
8120
|
-
}
|
|
8121
|
-
}
|
|
8330
|
+
this._handleServerNotification(subscription, [result]);
|
|
8122
8331
|
}
|
|
8123
8332
|
/**
|
|
8124
8333
|
* Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
|
|
@@ -8130,32 +8339,36 @@ class Connection {
|
|
|
8130
8339
|
|
|
8131
8340
|
|
|
8132
8341
|
onSlotUpdate(callback) {
|
|
8133
|
-
|
|
8134
|
-
this._slotUpdateSubscriptions[id] = {
|
|
8342
|
+
return this._makeSubscription({
|
|
8135
8343
|
callback,
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
return id;
|
|
8344
|
+
method: 'slotsUpdatesSubscribe',
|
|
8345
|
+
unsubscribeMethod: 'slotsUpdatesUnsubscribe'
|
|
8346
|
+
}, []
|
|
8347
|
+
/* args */
|
|
8348
|
+
);
|
|
8142
8349
|
}
|
|
8143
8350
|
/**
|
|
8144
8351
|
* Deregister a slot update notification callback
|
|
8145
8352
|
*
|
|
8146
|
-
* @param id subscription id to deregister
|
|
8353
|
+
* @param id client subscription id to deregister
|
|
8354
|
+
*/
|
|
8355
|
+
|
|
8356
|
+
|
|
8357
|
+
async removeSlotUpdateListener(clientSubscriptionId) {
|
|
8358
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
|
|
8359
|
+
}
|
|
8360
|
+
/**
|
|
8361
|
+
* @internal
|
|
8147
8362
|
*/
|
|
8148
8363
|
|
|
8149
8364
|
|
|
8150
|
-
async
|
|
8151
|
-
|
|
8152
|
-
const subInfo = this._slotUpdateSubscriptions[id];
|
|
8153
|
-
delete this._slotUpdateSubscriptions[id];
|
|
8154
|
-
await this._unsubscribe(subInfo, 'slotsUpdatesUnsubscribe');
|
|
8365
|
+
async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
|
|
8366
|
+
const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
8155
8367
|
|
|
8156
|
-
|
|
8368
|
+
if (dispose) {
|
|
8369
|
+
await dispose();
|
|
8157
8370
|
} else {
|
|
8158
|
-
console.warn(
|
|
8371
|
+
console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
|
|
8159
8372
|
}
|
|
8160
8373
|
}
|
|
8161
8374
|
|
|
@@ -8202,30 +8415,34 @@ class Connection {
|
|
|
8202
8415
|
|
|
8203
8416
|
|
|
8204
8417
|
_wsOnSignatureNotification(notification) {
|
|
8205
|
-
const
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8418
|
+
const {
|
|
8419
|
+
result,
|
|
8420
|
+
subscription
|
|
8421
|
+
} = superstruct.create(notification, SignatureNotificationResult);
|
|
8422
|
+
|
|
8423
|
+
if (result.value !== 'receivedSignature') {
|
|
8424
|
+
/**
|
|
8425
|
+
* Special case.
|
|
8426
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
8427
|
+
* subscription on the server side. We need to track which of these
|
|
8428
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
8429
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
8430
|
+
* (in which case we must tear down the server subscription) or an
|
|
8431
|
+
* already-processed signature (in which case the client can simply
|
|
8432
|
+
* clear out the subscription locally without telling the server).
|
|
8433
|
+
*
|
|
8434
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
8435
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
8436
|
+
*/
|
|
8437
|
+
this._subscriptionsAutoDisposedByRpc.add(subscription);
|
|
8438
|
+
}
|
|
8439
|
+
|
|
8440
|
+
this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{
|
|
8441
|
+
type: 'received'
|
|
8442
|
+
}, result.context] : [{
|
|
8443
|
+
type: 'status',
|
|
8444
|
+
result: result.value
|
|
8445
|
+
}, result.context]);
|
|
8229
8446
|
}
|
|
8230
8447
|
/**
|
|
8231
8448
|
* Register a callback to be invoked upon signature updates
|
|
@@ -8238,23 +8455,26 @@ class Connection {
|
|
|
8238
8455
|
|
|
8239
8456
|
|
|
8240
8457
|
onSignature(signature, callback, commitment) {
|
|
8241
|
-
const
|
|
8242
|
-
|
|
8243
|
-
|
|
8458
|
+
const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8459
|
+
);
|
|
8460
|
+
|
|
8461
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
8244
8462
|
callback: (notification, context) => {
|
|
8245
8463
|
if (notification.type === 'status') {
|
|
8246
|
-
callback(notification.result, context);
|
|
8464
|
+
callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
8465
|
+
// so no need to explicitly send an unsubscribe message.
|
|
8466
|
+
|
|
8467
|
+
try {
|
|
8468
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
8469
|
+
} catch {// Already removed.
|
|
8470
|
+
}
|
|
8247
8471
|
}
|
|
8248
8472
|
},
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
subscriptionId: null
|
|
8253
|
-
};
|
|
8254
|
-
|
|
8255
|
-
this._updateSubscriptions();
|
|
8473
|
+
method: 'signatureSubscribe',
|
|
8474
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
8475
|
+
}, args);
|
|
8256
8476
|
|
|
8257
|
-
return
|
|
8477
|
+
return clientSubscriptionId;
|
|
8258
8478
|
}
|
|
8259
8479
|
/**
|
|
8260
8480
|
* Register a callback to be invoked when a transaction is
|
|
@@ -8269,35 +8489,43 @@ class Connection {
|
|
|
8269
8489
|
|
|
8270
8490
|
|
|
8271
8491
|
onSignatureWithOptions(signature, callback, options) {
|
|
8272
|
-
const
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
options
|
|
8277
|
-
|
|
8492
|
+
const {
|
|
8493
|
+
commitment,
|
|
8494
|
+
...extra
|
|
8495
|
+
} = { ...options,
|
|
8496
|
+
commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
8497
|
+
|
|
8278
8498
|
};
|
|
8279
8499
|
|
|
8280
|
-
this.
|
|
8500
|
+
const args = this._buildArgs([signature], commitment, undefined
|
|
8501
|
+
/* encoding */
|
|
8502
|
+
, extra);
|
|
8503
|
+
|
|
8504
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
8505
|
+
callback: (notification, context) => {
|
|
8506
|
+
callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
8507
|
+
// so no need to explicitly send an unsubscribe message.
|
|
8508
|
+
|
|
8509
|
+
try {
|
|
8510
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
8511
|
+
} catch {// Already removed.
|
|
8512
|
+
}
|
|
8513
|
+
},
|
|
8514
|
+
method: 'signatureSubscribe',
|
|
8515
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
8516
|
+
}, args);
|
|
8281
8517
|
|
|
8282
|
-
return
|
|
8518
|
+
return clientSubscriptionId;
|
|
8283
8519
|
}
|
|
8284
8520
|
/**
|
|
8285
8521
|
* Deregister a signature notification callback
|
|
8286
8522
|
*
|
|
8287
|
-
* @param id subscription id to deregister
|
|
8523
|
+
* @param id client subscription id to deregister
|
|
8288
8524
|
*/
|
|
8289
8525
|
|
|
8290
8526
|
|
|
8291
|
-
async removeSignatureListener(
|
|
8292
|
-
|
|
8293
|
-
const subInfo = this._signatureSubscriptions[id];
|
|
8294
|
-
delete this._signatureSubscriptions[id];
|
|
8295
|
-
await this._unsubscribe(subInfo, 'signatureUnsubscribe');
|
|
8296
|
-
|
|
8297
|
-
this._updateSubscriptions();
|
|
8298
|
-
} else {
|
|
8299
|
-
console.warn(createSubscriptionWarningMessage(id, 'signature result'));
|
|
8300
|
-
}
|
|
8527
|
+
async removeSignatureListener(clientSubscriptionId) {
|
|
8528
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
|
|
8301
8529
|
}
|
|
8302
8530
|
/**
|
|
8303
8531
|
* @internal
|
|
@@ -8305,14 +8533,12 @@ class Connection {
|
|
|
8305
8533
|
|
|
8306
8534
|
|
|
8307
8535
|
_wsOnRootNotification(notification) {
|
|
8308
|
-
const
|
|
8536
|
+
const {
|
|
8537
|
+
result,
|
|
8538
|
+
subscription
|
|
8539
|
+
} = superstruct.create(notification, RootNotificationResult);
|
|
8309
8540
|
|
|
8310
|
-
|
|
8311
|
-
if (sub.subscriptionId === res.subscription) {
|
|
8312
|
-
sub.callback(res.result);
|
|
8313
|
-
return;
|
|
8314
|
-
}
|
|
8315
|
-
}
|
|
8541
|
+
this._handleServerNotification(subscription, [result]);
|
|
8316
8542
|
}
|
|
8317
8543
|
/**
|
|
8318
8544
|
* Register a callback to be invoked upon root changes
|
|
@@ -8323,33 +8549,23 @@ class Connection {
|
|
|
8323
8549
|
|
|
8324
8550
|
|
|
8325
8551
|
onRootChange(callback) {
|
|
8326
|
-
|
|
8327
|
-
this._rootSubscriptions[id] = {
|
|
8552
|
+
return this._makeSubscription({
|
|
8328
8553
|
callback,
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
return id;
|
|
8554
|
+
method: 'rootSubscribe',
|
|
8555
|
+
unsubscribeMethod: 'rootUnsubscribe'
|
|
8556
|
+
}, []
|
|
8557
|
+
/* args */
|
|
8558
|
+
);
|
|
8335
8559
|
}
|
|
8336
8560
|
/**
|
|
8337
8561
|
* Deregister a root notification callback
|
|
8338
8562
|
*
|
|
8339
|
-
* @param id subscription id to deregister
|
|
8563
|
+
* @param id client subscription id to deregister
|
|
8340
8564
|
*/
|
|
8341
8565
|
|
|
8342
8566
|
|
|
8343
|
-
async removeRootChangeListener(
|
|
8344
|
-
|
|
8345
|
-
const subInfo = this._rootSubscriptions[id];
|
|
8346
|
-
delete this._rootSubscriptions[id];
|
|
8347
|
-
await this._unsubscribe(subInfo, 'rootUnsubscribe');
|
|
8348
|
-
|
|
8349
|
-
this._updateSubscriptions();
|
|
8350
|
-
} else {
|
|
8351
|
-
console.warn(createSubscriptionWarningMessage(id, 'root change'));
|
|
8352
|
-
}
|
|
8567
|
+
async removeRootChangeListener(clientSubscriptionId) {
|
|
8568
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
|
|
8353
8569
|
}
|
|
8354
8570
|
|
|
8355
8571
|
}
|
|
@@ -10051,7 +10267,9 @@ exports.MAX_SEED_LENGTH = MAX_SEED_LENGTH;
|
|
|
10051
10267
|
exports.Message = Message;
|
|
10052
10268
|
exports.NONCE_ACCOUNT_LENGTH = NONCE_ACCOUNT_LENGTH;
|
|
10053
10269
|
exports.NonceAccount = NonceAccount;
|
|
10270
|
+
exports.PACKET_DATA_SIZE = PACKET_DATA_SIZE;
|
|
10054
10271
|
exports.PublicKey = PublicKey;
|
|
10272
|
+
exports.SIGNATURE_LENGTH_IN_BYTES = SIGNATURE_LENGTH_IN_BYTES;
|
|
10055
10273
|
exports.SOLANA_SCHEMA = SOLANA_SCHEMA;
|
|
10056
10274
|
exports.STAKE_CONFIG_ID = STAKE_CONFIG_ID;
|
|
10057
10275
|
exports.STAKE_INSTRUCTION_LAYOUTS = STAKE_INSTRUCTION_LAYOUTS;
|