@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.cjs.js
CHANGED
|
@@ -2120,6 +2120,16 @@ class Account {
|
|
|
2120
2120
|
|
|
2121
2121
|
const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader1111111111111111111111111111111111');
|
|
2122
2122
|
|
|
2123
|
+
/**
|
|
2124
|
+
* Maximum over-the-wire size of a Transaction
|
|
2125
|
+
*
|
|
2126
|
+
* 1280 is IPv6 minimum MTU
|
|
2127
|
+
* 40 bytes is the size of the IPv6 header
|
|
2128
|
+
* 8 bytes is the size of the fragment header
|
|
2129
|
+
*/
|
|
2130
|
+
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2131
|
+
const SIGNATURE_LENGTH_IN_BYTES = 64;
|
|
2132
|
+
|
|
2123
2133
|
/**
|
|
2124
2134
|
* Layout for a public key
|
|
2125
2135
|
*/
|
|
@@ -2379,20 +2389,8 @@ function assert (condition, message) {
|
|
|
2379
2389
|
|
|
2380
2390
|
/**
|
|
2381
2391
|
* Default (empty) signature
|
|
2382
|
-
*
|
|
2383
|
-
* Signatures are 64 bytes in length
|
|
2384
2392
|
*/
|
|
2385
|
-
const DEFAULT_SIGNATURE = buffer.Buffer.alloc(
|
|
2386
|
-
/**
|
|
2387
|
-
* Maximum over-the-wire size of a Transaction
|
|
2388
|
-
*
|
|
2389
|
-
* 1280 is IPv6 minimum MTU
|
|
2390
|
-
* 40 bytes is the size of the IPv6 header
|
|
2391
|
-
* 8 bytes is the size of the fragment header
|
|
2392
|
-
*/
|
|
2393
|
-
|
|
2394
|
-
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2395
|
-
const SIGNATURE_LENGTH = 64;
|
|
2393
|
+
const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
|
|
2396
2394
|
/**
|
|
2397
2395
|
* Account metadata used to define instructions
|
|
2398
2396
|
*/
|
|
@@ -3022,8 +3020,8 @@ class Transaction {
|
|
|
3022
3020
|
let signatures = [];
|
|
3023
3021
|
|
|
3024
3022
|
for (let i = 0; i < signatureCount; i++) {
|
|
3025
|
-
const signature = byteArray.slice(0,
|
|
3026
|
-
byteArray = byteArray.slice(
|
|
3023
|
+
const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
|
|
3024
|
+
byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
|
|
3027
3025
|
signatures.push(bs58__default["default"].encode(buffer.Buffer.from(signature)));
|
|
3028
3026
|
}
|
|
3029
3027
|
|
|
@@ -3912,11 +3910,11 @@ class SystemProgram {
|
|
|
3912
3910
|
}
|
|
3913
3911
|
SystemProgram.programId = new PublicKey('11111111111111111111111111111111');
|
|
3914
3912
|
|
|
3915
|
-
// Keep program chunks under PACKET_DATA_SIZE, leaving enough room for the
|
|
3916
3913
|
// rest of the Transaction fields
|
|
3917
3914
|
//
|
|
3918
3915
|
// TODO: replace 300 with a proper constant for the size of the other
|
|
3919
3916
|
// Transaction fields
|
|
3917
|
+
|
|
3920
3918
|
const CHUNK_SIZE = PACKET_DATA_SIZE - 300;
|
|
3921
3919
|
/**
|
|
3922
3920
|
* Program loader interface
|
|
@@ -4246,6 +4244,82 @@ class ComputeBudgetProgram {
|
|
|
4246
4244
|
}
|
|
4247
4245
|
ComputeBudgetProgram.programId = new PublicKey('ComputeBudget111111111111111111111111111111');
|
|
4248
4246
|
|
|
4247
|
+
var objToString = Object.prototype.toString;
|
|
4248
|
+
var objKeys = Object.keys || function(obj) {
|
|
4249
|
+
var keys = [];
|
|
4250
|
+
for (var name in obj) {
|
|
4251
|
+
keys.push(name);
|
|
4252
|
+
}
|
|
4253
|
+
return keys;
|
|
4254
|
+
};
|
|
4255
|
+
|
|
4256
|
+
function stringify(val, isArrayProp) {
|
|
4257
|
+
var i, max, str, keys, key, propVal, toStr;
|
|
4258
|
+
if (val === true) {
|
|
4259
|
+
return "true";
|
|
4260
|
+
}
|
|
4261
|
+
if (val === false) {
|
|
4262
|
+
return "false";
|
|
4263
|
+
}
|
|
4264
|
+
switch (typeof val) {
|
|
4265
|
+
case "object":
|
|
4266
|
+
if (val === null) {
|
|
4267
|
+
return null;
|
|
4268
|
+
} else if (val.toJSON && typeof val.toJSON === "function") {
|
|
4269
|
+
return stringify(val.toJSON(), isArrayProp);
|
|
4270
|
+
} else {
|
|
4271
|
+
toStr = objToString.call(val);
|
|
4272
|
+
if (toStr === "[object Array]") {
|
|
4273
|
+
str = '[';
|
|
4274
|
+
max = val.length - 1;
|
|
4275
|
+
for(i = 0; i < max; i++) {
|
|
4276
|
+
str += stringify(val[i], true) + ',';
|
|
4277
|
+
}
|
|
4278
|
+
if (max > -1) {
|
|
4279
|
+
str += stringify(val[i], true);
|
|
4280
|
+
}
|
|
4281
|
+
return str + ']';
|
|
4282
|
+
} else if (toStr === "[object Object]") {
|
|
4283
|
+
// only object is left
|
|
4284
|
+
keys = objKeys(val).sort();
|
|
4285
|
+
max = keys.length;
|
|
4286
|
+
str = "";
|
|
4287
|
+
i = 0;
|
|
4288
|
+
while (i < max) {
|
|
4289
|
+
key = keys[i];
|
|
4290
|
+
propVal = stringify(val[key], false);
|
|
4291
|
+
if (propVal !== undefined) {
|
|
4292
|
+
if (str) {
|
|
4293
|
+
str += ',';
|
|
4294
|
+
}
|
|
4295
|
+
str += JSON.stringify(key) + ':' + propVal;
|
|
4296
|
+
}
|
|
4297
|
+
i++;
|
|
4298
|
+
}
|
|
4299
|
+
return '{' + str + '}';
|
|
4300
|
+
} else {
|
|
4301
|
+
return JSON.stringify(val);
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
case "function":
|
|
4305
|
+
case "undefined":
|
|
4306
|
+
return isArrayProp ? null : undefined;
|
|
4307
|
+
case "string":
|
|
4308
|
+
return JSON.stringify(val);
|
|
4309
|
+
default:
|
|
4310
|
+
return isFinite(val) ? val : null;
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4314
|
+
var fastStableStringify = function(val) {
|
|
4315
|
+
var returnVal = stringify(val, false);
|
|
4316
|
+
if (returnVal !== undefined) {
|
|
4317
|
+
return ''+ returnVal;
|
|
4318
|
+
}
|
|
4319
|
+
};
|
|
4320
|
+
|
|
4321
|
+
var fastStableStringify$1 = fastStableStringify;
|
|
4322
|
+
|
|
4249
4323
|
const DESTROY_TIMEOUT_MS = 5000;
|
|
4250
4324
|
class AgentManager {
|
|
4251
4325
|
static _newAgent(useHttps) {
|
|
@@ -4461,6 +4535,12 @@ const BufferFromRawAccountData = superstruct.coerce(superstruct.instance(buffer.
|
|
|
4461
4535
|
*/
|
|
4462
4536
|
|
|
4463
4537
|
const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
|
|
4538
|
+
/**
|
|
4539
|
+
* HACK.
|
|
4540
|
+
* Copied from rpc-websockets/dist/lib/client.
|
|
4541
|
+
* Otherwise, `yarn build` fails with:
|
|
4542
|
+
* https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
|
|
4543
|
+
*/
|
|
4464
4544
|
|
|
4465
4545
|
/**
|
|
4466
4546
|
* @internal
|
|
@@ -5335,14 +5415,9 @@ const LogsNotificationResult = superstruct.type({
|
|
|
5335
5415
|
* Filter for log subscriptions.
|
|
5336
5416
|
*/
|
|
5337
5417
|
|
|
5338
|
-
function createSubscriptionWarningMessage(id, label) {
|
|
5339
|
-
return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
|
|
5340
|
-
}
|
|
5341
5418
|
/**
|
|
5342
5419
|
* A connection to a fullnode JSON RPC endpoint
|
|
5343
5420
|
*/
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
5421
|
class Connection {
|
|
5347
5422
|
/** @internal */
|
|
5348
5423
|
|
|
@@ -5366,21 +5441,13 @@ class Connection {
|
|
|
5366
5441
|
|
|
5367
5442
|
/** @internal */
|
|
5368
5443
|
|
|
5369
|
-
/** @internal
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
/** @internal */
|
|
5378
|
-
|
|
5379
|
-
/** @internal */
|
|
5380
|
-
|
|
5381
|
-
/** @internal */
|
|
5382
|
-
|
|
5383
|
-
/** @internal */
|
|
5444
|
+
/** @internal
|
|
5445
|
+
* A number that we increment every time an active connection closes.
|
|
5446
|
+
* Used to determine whether the same socket connection that was open
|
|
5447
|
+
* when an async operation started is the same one that's active when
|
|
5448
|
+
* its continuation fires.
|
|
5449
|
+
*
|
|
5450
|
+
*/
|
|
5384
5451
|
|
|
5385
5452
|
/** @internal */
|
|
5386
5453
|
|
|
@@ -5396,7 +5463,19 @@ class Connection {
|
|
|
5396
5463
|
|
|
5397
5464
|
/** @internal */
|
|
5398
5465
|
|
|
5399
|
-
/**
|
|
5466
|
+
/**
|
|
5467
|
+
* Special case.
|
|
5468
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
5469
|
+
* subscription on the server side. We need to track which of these
|
|
5470
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
5471
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
5472
|
+
* (in which case we must tear down the server subscription) or an
|
|
5473
|
+
* already-processed signature (in which case the client can simply
|
|
5474
|
+
* clear out the subscription locally without telling the server).
|
|
5475
|
+
*
|
|
5476
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
5477
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
5478
|
+
*/
|
|
5400
5479
|
|
|
5401
5480
|
/** @internal */
|
|
5402
5481
|
|
|
@@ -5418,6 +5497,7 @@ class Connection {
|
|
|
5418
5497
|
this._rpcWebSocketConnected = false;
|
|
5419
5498
|
this._rpcWebSocketHeartbeat = null;
|
|
5420
5499
|
this._rpcWebSocketIdleTimeout = null;
|
|
5500
|
+
this._rpcWebSocketGeneration = 0;
|
|
5421
5501
|
this._disableBlockhashCaching = false;
|
|
5422
5502
|
this._pollingBlockhash = false;
|
|
5423
5503
|
this._blockhashInfo = {
|
|
@@ -5426,20 +5506,11 @@ class Connection {
|
|
|
5426
5506
|
transactionSignatures: [],
|
|
5427
5507
|
simulatedSignatures: []
|
|
5428
5508
|
};
|
|
5429
|
-
this.
|
|
5430
|
-
this.
|
|
5431
|
-
this.
|
|
5432
|
-
this.
|
|
5433
|
-
this.
|
|
5434
|
-
this._rootSubscriptions = {};
|
|
5435
|
-
this._signatureSubscriptionCounter = 0;
|
|
5436
|
-
this._signatureSubscriptions = {};
|
|
5437
|
-
this._slotSubscriptionCounter = 0;
|
|
5438
|
-
this._slotSubscriptions = {};
|
|
5439
|
-
this._logsSubscriptionCounter = 0;
|
|
5440
|
-
this._logsSubscriptions = {};
|
|
5441
|
-
this._slotUpdateSubscriptionCounter = 0;
|
|
5442
|
-
this._slotUpdateSubscriptions = {};
|
|
5509
|
+
this._nextClientSubscriptionId = 0;
|
|
5510
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
5511
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
5512
|
+
this._subscriptionsByHash = {};
|
|
5513
|
+
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
5443
5514
|
let url = new URL(endpoint);
|
|
5444
5515
|
const useHttps = url.protocol === 'https:';
|
|
5445
5516
|
let wsEndpoint;
|
|
@@ -7207,6 +7278,8 @@ class Connection {
|
|
|
7207
7278
|
|
|
7208
7279
|
|
|
7209
7280
|
_wsOnClose(code) {
|
|
7281
|
+
this._rpcWebSocketGeneration++;
|
|
7282
|
+
|
|
7210
7283
|
if (this._rpcWebSocketHeartbeat) {
|
|
7211
7284
|
clearInterval(this._rpcWebSocketHeartbeat);
|
|
7212
7285
|
this._rpcWebSocketHeartbeat = null;
|
|
@@ -7220,85 +7293,20 @@ class Connection {
|
|
|
7220
7293
|
} // implicit close, prepare subscriptions for auto-reconnect
|
|
7221
7294
|
|
|
7222
7295
|
|
|
7223
|
-
this.
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
async _subscribe(sub, rpcMethod, rpcArgs) {
|
|
7231
|
-
if (sub.subscriptionId == null) {
|
|
7232
|
-
sub.subscriptionId = 'subscribing';
|
|
7233
|
-
|
|
7234
|
-
try {
|
|
7235
|
-
const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
|
|
7236
|
-
|
|
7237
|
-
if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
|
|
7238
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7239
|
-
sub.subscriptionId = id;
|
|
7240
|
-
}
|
|
7241
|
-
} catch (err) {
|
|
7242
|
-
if (sub.subscriptionId === 'subscribing') {
|
|
7243
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7244
|
-
sub.subscriptionId = null;
|
|
7245
|
-
}
|
|
7246
|
-
|
|
7247
|
-
if (err instanceof Error) {
|
|
7248
|
-
console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
|
|
7249
|
-
}
|
|
7250
|
-
}
|
|
7251
|
-
}
|
|
7252
|
-
}
|
|
7253
|
-
/**
|
|
7254
|
-
* @internal
|
|
7255
|
-
*/
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
async _unsubscribe(sub, rpcMethod) {
|
|
7259
|
-
const subscriptionId = sub.subscriptionId;
|
|
7260
|
-
|
|
7261
|
-
if (subscriptionId != null && typeof subscriptionId != 'string') {
|
|
7262
|
-
const unsubscribeId = subscriptionId;
|
|
7263
|
-
|
|
7264
|
-
try {
|
|
7265
|
-
await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
|
|
7266
|
-
} catch (err) {
|
|
7267
|
-
if (err instanceof Error) {
|
|
7268
|
-
console.error(`${rpcMethod} error:`, err.message);
|
|
7269
|
-
}
|
|
7270
|
-
}
|
|
7271
|
-
}
|
|
7272
|
-
}
|
|
7273
|
-
/**
|
|
7274
|
-
* @internal
|
|
7275
|
-
*/
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
_resetSubscriptions() {
|
|
7279
|
-
Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7280
|
-
Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7281
|
-
Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7282
|
-
Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7283
|
-
Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7284
|
-
Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7285
|
-
Object.values(this._slotUpdateSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7296
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
7297
|
+
Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
|
|
7298
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7299
|
+
state: 'pending'
|
|
7300
|
+
};
|
|
7301
|
+
});
|
|
7286
7302
|
}
|
|
7287
7303
|
/**
|
|
7288
7304
|
* @internal
|
|
7289
7305
|
*/
|
|
7290
7306
|
|
|
7291
7307
|
|
|
7292
|
-
_updateSubscriptions() {
|
|
7293
|
-
|
|
7294
|
-
const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
|
|
7295
|
-
const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
|
|
7296
|
-
const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
|
|
7297
|
-
const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
|
|
7298
|
-
const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
|
|
7299
|
-
const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
|
|
7300
|
-
|
|
7301
|
-
if (accountKeys.length === 0 && programKeys.length === 0 && slotKeys.length === 0 && slotUpdateKeys.length === 0 && signatureKeys.length === 0 && rootKeys.length === 0 && logsKeys.length === 0) {
|
|
7308
|
+
async _updateSubscriptions() {
|
|
7309
|
+
if (Object.keys(this._subscriptionsByHash).length === 0) {
|
|
7302
7310
|
if (this._rpcWebSocketConnected) {
|
|
7303
7311
|
this._rpcWebSocketConnected = false;
|
|
7304
7312
|
this._rpcWebSocketIdleTimeout = setTimeout(() => {
|
|
@@ -7330,60 +7338,167 @@ class Connection {
|
|
|
7330
7338
|
return;
|
|
7331
7339
|
}
|
|
7332
7340
|
|
|
7333
|
-
|
|
7334
|
-
const sub = this._accountChangeSubscriptions[id];
|
|
7341
|
+
const activeWebSocketGeneration = this._rpcWebSocketGeneration;
|
|
7335
7342
|
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
for (let id of programKeys) {
|
|
7340
|
-
const sub = this._programAccountChangeSubscriptions[id];
|
|
7343
|
+
const isCurrentConnectionStillActive = () => {
|
|
7344
|
+
return activeWebSocketGeneration === this._rpcWebSocketGeneration;
|
|
7345
|
+
};
|
|
7341
7346
|
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7347
|
+
await Promise.all( // Don't be tempted to change this to `Object.entries`. We call
|
|
7348
|
+
// `_updateSubscriptions` recursively when processing the state,
|
|
7349
|
+
// so it's important that we look up the *current* version of
|
|
7350
|
+
// each subscription, every time we process a hash.
|
|
7351
|
+
Object.keys(this._subscriptionsByHash).map(async hash => {
|
|
7352
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7346
7353
|
|
|
7347
|
-
|
|
7348
|
-
|
|
7354
|
+
if (subscription === undefined) {
|
|
7355
|
+
// This entry has since been deleted. Skip.
|
|
7356
|
+
return;
|
|
7357
|
+
}
|
|
7349
7358
|
|
|
7350
|
-
|
|
7351
|
-
|
|
7359
|
+
switch (subscription.state) {
|
|
7360
|
+
case 'pending':
|
|
7361
|
+
case 'unsubscribed':
|
|
7362
|
+
if (subscription.callbacks.size === 0) {
|
|
7363
|
+
/**
|
|
7364
|
+
* You can end up here when:
|
|
7365
|
+
*
|
|
7366
|
+
* - a subscription has recently unsubscribed
|
|
7367
|
+
* without having new callbacks added to it
|
|
7368
|
+
* while the unsubscribe was in flight, or
|
|
7369
|
+
* - when a pending subscription has its
|
|
7370
|
+
* listeners removed before a request was
|
|
7371
|
+
* sent to the server.
|
|
7372
|
+
*
|
|
7373
|
+
* Being that nobody is interested in this
|
|
7374
|
+
* subscription any longer, delete it.
|
|
7375
|
+
*/
|
|
7376
|
+
delete this._subscriptionsByHash[hash];
|
|
7377
|
+
|
|
7378
|
+
if (subscription.state === 'unsubscribed') {
|
|
7379
|
+
delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId];
|
|
7380
|
+
}
|
|
7352
7381
|
|
|
7353
|
-
|
|
7354
|
-
|
|
7382
|
+
await this._updateSubscriptions();
|
|
7383
|
+
return;
|
|
7384
|
+
}
|
|
7355
7385
|
|
|
7356
|
-
|
|
7357
|
-
|
|
7386
|
+
await (async () => {
|
|
7387
|
+
const {
|
|
7388
|
+
args,
|
|
7389
|
+
method
|
|
7390
|
+
} = subscription;
|
|
7358
7391
|
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7392
|
+
try {
|
|
7393
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7394
|
+
state: 'subscribing'
|
|
7395
|
+
};
|
|
7396
|
+
const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
|
|
7397
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7398
|
+
serverSubscriptionId,
|
|
7399
|
+
state: 'subscribed'
|
|
7400
|
+
};
|
|
7401
|
+
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
|
|
7402
|
+
await this._updateSubscriptions();
|
|
7403
|
+
} catch (e) {
|
|
7404
|
+
if (e instanceof Error) {
|
|
7405
|
+
console.error(`${method} error for argument`, args, e.message);
|
|
7406
|
+
}
|
|
7407
|
+
|
|
7408
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7409
|
+
return;
|
|
7410
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7363
7411
|
|
|
7364
|
-
this._subscribe(sub, 'signatureSubscribe', args);
|
|
7365
|
-
}
|
|
7366
7412
|
|
|
7367
|
-
|
|
7368
|
-
|
|
7413
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7414
|
+
state: 'pending'
|
|
7415
|
+
};
|
|
7416
|
+
await this._updateSubscriptions();
|
|
7417
|
+
}
|
|
7418
|
+
})();
|
|
7419
|
+
break;
|
|
7369
7420
|
|
|
7370
|
-
|
|
7371
|
-
|
|
7421
|
+
case 'subscribed':
|
|
7422
|
+
if (subscription.callbacks.size === 0) {
|
|
7423
|
+
// By the time we successfully set up a subscription
|
|
7424
|
+
// with the server, the client stopped caring about it.
|
|
7425
|
+
// Tear it down now.
|
|
7426
|
+
await (async () => {
|
|
7427
|
+
const {
|
|
7428
|
+
serverSubscriptionId,
|
|
7429
|
+
unsubscribeMethod
|
|
7430
|
+
} = subscription;
|
|
7431
|
+
|
|
7432
|
+
if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) {
|
|
7433
|
+
/**
|
|
7434
|
+
* Special case.
|
|
7435
|
+
* If we're dealing with a subscription that has been auto-
|
|
7436
|
+
* disposed by the RPC, then we can skip the RPC call to
|
|
7437
|
+
* tear down the subscription here.
|
|
7438
|
+
*
|
|
7439
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
7440
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
7441
|
+
*/
|
|
7442
|
+
this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
|
|
7443
|
+
} else {
|
|
7444
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7445
|
+
state: 'unsubscribing'
|
|
7446
|
+
};
|
|
7447
|
+
|
|
7448
|
+
try {
|
|
7449
|
+
await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
|
|
7450
|
+
} catch (e) {
|
|
7451
|
+
if (e instanceof Error) {
|
|
7452
|
+
console.error(`${unsubscribeMethod} error:`, e.message);
|
|
7453
|
+
}
|
|
7454
|
+
|
|
7455
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7456
|
+
return;
|
|
7457
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7458
|
+
|
|
7459
|
+
|
|
7460
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7461
|
+
state: 'subscribed'
|
|
7462
|
+
};
|
|
7463
|
+
await this._updateSubscriptions();
|
|
7464
|
+
return;
|
|
7465
|
+
}
|
|
7466
|
+
}
|
|
7372
7467
|
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7468
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7469
|
+
state: 'unsubscribed'
|
|
7470
|
+
};
|
|
7471
|
+
await this._updateSubscriptions();
|
|
7472
|
+
})();
|
|
7473
|
+
}
|
|
7376
7474
|
|
|
7377
|
-
|
|
7378
|
-
filter = {
|
|
7379
|
-
mentions: [sub.filter.toString()]
|
|
7380
|
-
};
|
|
7381
|
-
} else {
|
|
7382
|
-
filter = sub.filter;
|
|
7475
|
+
break;
|
|
7383
7476
|
}
|
|
7477
|
+
}));
|
|
7478
|
+
}
|
|
7479
|
+
/**
|
|
7480
|
+
* @internal
|
|
7481
|
+
*/
|
|
7384
7482
|
|
|
7385
|
-
|
|
7483
|
+
|
|
7484
|
+
_handleServerNotification(serverSubscriptionId, callbackArgs) {
|
|
7485
|
+
const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
|
|
7486
|
+
|
|
7487
|
+
if (callbacks === undefined) {
|
|
7488
|
+
return;
|
|
7386
7489
|
}
|
|
7490
|
+
|
|
7491
|
+
callbacks.forEach(cb => {
|
|
7492
|
+
try {
|
|
7493
|
+
cb( // I failed to find a way to convince TypeScript that `cb` is of type
|
|
7494
|
+
// `TCallback` which is certainly compatible with `Parameters<TCallback>`.
|
|
7495
|
+
// See https://github.com/microsoft/TypeScript/issues/47615
|
|
7496
|
+
// @ts-ignore
|
|
7497
|
+
...callbackArgs);
|
|
7498
|
+
} catch (e) {
|
|
7499
|
+
console.error(e);
|
|
7500
|
+
}
|
|
7501
|
+
});
|
|
7387
7502
|
}
|
|
7388
7503
|
/**
|
|
7389
7504
|
* @internal
|
|
@@ -7391,14 +7506,71 @@ class Connection {
|
|
|
7391
7506
|
|
|
7392
7507
|
|
|
7393
7508
|
_wsOnAccountNotification(notification) {
|
|
7394
|
-
const
|
|
7509
|
+
const {
|
|
7510
|
+
result,
|
|
7511
|
+
subscription
|
|
7512
|
+
} = superstruct.create(notification, AccountNotificationResult);
|
|
7395
7513
|
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7514
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
7515
|
+
}
|
|
7516
|
+
/**
|
|
7517
|
+
* @internal
|
|
7518
|
+
*/
|
|
7519
|
+
|
|
7520
|
+
|
|
7521
|
+
_makeSubscription(subscriptionConfig,
|
|
7522
|
+
/**
|
|
7523
|
+
* When preparing `args` for a call to `_makeSubscription`, be sure
|
|
7524
|
+
* to carefully apply a default `commitment` property, if necessary.
|
|
7525
|
+
*
|
|
7526
|
+
* - If the user supplied a `commitment` use that.
|
|
7527
|
+
* - Otherwise, if the `Connection::commitment` is set, use that.
|
|
7528
|
+
* - Otherwise, set it to the RPC server default: `finalized`.
|
|
7529
|
+
*
|
|
7530
|
+
* This is extremely important to ensure that these two fundamentally
|
|
7531
|
+
* identical subscriptions produce the same identifying hash:
|
|
7532
|
+
*
|
|
7533
|
+
* - A subscription made without specifying a commitment.
|
|
7534
|
+
* - A subscription made where the commitment specified is the same
|
|
7535
|
+
* as the default applied to the subscription above.
|
|
7536
|
+
*
|
|
7537
|
+
* Example; these two subscriptions must produce the same hash:
|
|
7538
|
+
*
|
|
7539
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'`
|
|
7540
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'` with commitment
|
|
7541
|
+
* `'finalized'`.
|
|
7542
|
+
*
|
|
7543
|
+
* See the 'making a subscription with defaulted params omitted' test
|
|
7544
|
+
* in `connection-subscriptions.ts` for more.
|
|
7545
|
+
*/
|
|
7546
|
+
args) {
|
|
7547
|
+
const clientSubscriptionId = this._nextClientSubscriptionId++;
|
|
7548
|
+
const hash = fastStableStringify$1([subscriptionConfig.method, args], true
|
|
7549
|
+
/* isArrayProp */
|
|
7550
|
+
);
|
|
7551
|
+
const existingSubscription = this._subscriptionsByHash[hash];
|
|
7552
|
+
|
|
7553
|
+
if (existingSubscription === undefined) {
|
|
7554
|
+
this._subscriptionsByHash[hash] = { ...subscriptionConfig,
|
|
7555
|
+
args,
|
|
7556
|
+
callbacks: new Set([subscriptionConfig.callback]),
|
|
7557
|
+
state: 'pending'
|
|
7558
|
+
};
|
|
7559
|
+
} else {
|
|
7560
|
+
existingSubscription.callbacks.add(subscriptionConfig.callback);
|
|
7401
7561
|
}
|
|
7562
|
+
|
|
7563
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
|
|
7564
|
+
delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7565
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7566
|
+
assert(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
|
|
7567
|
+
subscription.callbacks.delete(subscriptionConfig.callback);
|
|
7568
|
+
await this._updateSubscriptions();
|
|
7569
|
+
};
|
|
7570
|
+
|
|
7571
|
+
this._updateSubscriptions();
|
|
7572
|
+
|
|
7573
|
+
return clientSubscriptionId;
|
|
7402
7574
|
}
|
|
7403
7575
|
/**
|
|
7404
7576
|
* Register a callback to be invoked whenever the specified account changes
|
|
@@ -7411,35 +7583,24 @@ class Connection {
|
|
|
7411
7583
|
|
|
7412
7584
|
|
|
7413
7585
|
onAccountChange(publicKey, callback, commitment) {
|
|
7414
|
-
const
|
|
7415
|
-
|
|
7416
|
-
publicKey: publicKey.toBase58(),
|
|
7417
|
-
callback,
|
|
7418
|
-
commitment,
|
|
7419
|
-
subscriptionId: null
|
|
7420
|
-
};
|
|
7586
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
7587
|
+
'base64');
|
|
7421
7588
|
|
|
7422
|
-
this.
|
|
7423
|
-
|
|
7424
|
-
|
|
7589
|
+
return this._makeSubscription({
|
|
7590
|
+
callback,
|
|
7591
|
+
method: 'accountSubscribe',
|
|
7592
|
+
unsubscribeMethod: 'accountUnsubscribe'
|
|
7593
|
+
}, args);
|
|
7425
7594
|
}
|
|
7426
7595
|
/**
|
|
7427
7596
|
* Deregister an account notification callback
|
|
7428
7597
|
*
|
|
7429
|
-
* @param id subscription id to deregister
|
|
7598
|
+
* @param id client subscription id to deregister
|
|
7430
7599
|
*/
|
|
7431
7600
|
|
|
7432
7601
|
|
|
7433
|
-
async removeAccountChangeListener(
|
|
7434
|
-
|
|
7435
|
-
const subInfo = this._accountChangeSubscriptions[id];
|
|
7436
|
-
delete this._accountChangeSubscriptions[id];
|
|
7437
|
-
await this._unsubscribe(subInfo, 'accountUnsubscribe');
|
|
7438
|
-
|
|
7439
|
-
this._updateSubscriptions();
|
|
7440
|
-
} else {
|
|
7441
|
-
console.warn(createSubscriptionWarningMessage(id, 'account change'));
|
|
7442
|
-
}
|
|
7602
|
+
async removeAccountChangeListener(clientSubscriptionId) {
|
|
7603
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
|
|
7443
7604
|
}
|
|
7444
7605
|
/**
|
|
7445
7606
|
* @internal
|
|
@@ -7447,21 +7608,15 @@ class Connection {
|
|
|
7447
7608
|
|
|
7448
7609
|
|
|
7449
7610
|
_wsOnProgramAccountNotification(notification) {
|
|
7450
|
-
const
|
|
7611
|
+
const {
|
|
7612
|
+
result,
|
|
7613
|
+
subscription
|
|
7614
|
+
} = superstruct.create(notification, ProgramAccountNotificationResult);
|
|
7451
7615
|
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
context
|
|
7457
|
-
} = res.result;
|
|
7458
|
-
sub.callback({
|
|
7459
|
-
accountId: value.pubkey,
|
|
7460
|
-
accountInfo: value.account
|
|
7461
|
-
}, context);
|
|
7462
|
-
return;
|
|
7463
|
-
}
|
|
7464
|
-
}
|
|
7616
|
+
this._handleServerNotification(subscription, [{
|
|
7617
|
+
accountId: result.value.pubkey,
|
|
7618
|
+
accountInfo: result.value.account
|
|
7619
|
+
}, result.context]);
|
|
7465
7620
|
}
|
|
7466
7621
|
/**
|
|
7467
7622
|
* Register a callback to be invoked whenever accounts owned by the
|
|
@@ -7476,36 +7631,30 @@ class Connection {
|
|
|
7476
7631
|
|
|
7477
7632
|
|
|
7478
7633
|
onProgramAccountChange(programId, callback, commitment, filters) {
|
|
7479
|
-
const
|
|
7480
|
-
|
|
7481
|
-
|
|
7634
|
+
const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
7635
|
+
'base64'
|
|
7636
|
+
/* encoding */
|
|
7637
|
+
, filters ? {
|
|
7638
|
+
filters: filters
|
|
7639
|
+
} : undefined
|
|
7640
|
+
/* extra */
|
|
7641
|
+
);
|
|
7642
|
+
|
|
7643
|
+
return this._makeSubscription({
|
|
7482
7644
|
callback,
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
};
|
|
7487
|
-
|
|
7488
|
-
this._updateSubscriptions();
|
|
7489
|
-
|
|
7490
|
-
return id;
|
|
7645
|
+
method: 'programSubscribe',
|
|
7646
|
+
unsubscribeMethod: 'programUnsubscribe'
|
|
7647
|
+
}, args);
|
|
7491
7648
|
}
|
|
7492
7649
|
/**
|
|
7493
7650
|
* Deregister an account notification callback
|
|
7494
7651
|
*
|
|
7495
|
-
* @param id subscription id to deregister
|
|
7652
|
+
* @param id client subscription id to deregister
|
|
7496
7653
|
*/
|
|
7497
7654
|
|
|
7498
7655
|
|
|
7499
|
-
async removeProgramAccountChangeListener(
|
|
7500
|
-
|
|
7501
|
-
const subInfo = this._programAccountChangeSubscriptions[id];
|
|
7502
|
-
delete this._programAccountChangeSubscriptions[id];
|
|
7503
|
-
await this._unsubscribe(subInfo, 'programUnsubscribe');
|
|
7504
|
-
|
|
7505
|
-
this._updateSubscriptions();
|
|
7506
|
-
} else {
|
|
7507
|
-
console.warn(createSubscriptionWarningMessage(id, 'program account change'));
|
|
7508
|
-
}
|
|
7656
|
+
async removeProgramAccountChangeListener(clientSubscriptionId) {
|
|
7657
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
|
|
7509
7658
|
}
|
|
7510
7659
|
/**
|
|
7511
7660
|
* Registers a callback to be invoked whenever logs are emitted.
|
|
@@ -7513,35 +7662,26 @@ class Connection {
|
|
|
7513
7662
|
|
|
7514
7663
|
|
|
7515
7664
|
onLogs(filter, callback, commitment) {
|
|
7516
|
-
const
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
commitment,
|
|
7521
|
-
subscriptionId: null
|
|
7522
|
-
};
|
|
7665
|
+
const args = this._buildArgs([typeof filter === 'object' ? {
|
|
7666
|
+
mentions: [filter.toString()]
|
|
7667
|
+
} : filter], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7668
|
+
);
|
|
7523
7669
|
|
|
7524
|
-
this.
|
|
7525
|
-
|
|
7526
|
-
|
|
7670
|
+
return this._makeSubscription({
|
|
7671
|
+
callback,
|
|
7672
|
+
method: 'logsSubscribe',
|
|
7673
|
+
unsubscribeMethod: 'logsUnsubscribe'
|
|
7674
|
+
}, args);
|
|
7527
7675
|
}
|
|
7528
7676
|
/**
|
|
7529
7677
|
* Deregister a logs callback.
|
|
7530
7678
|
*
|
|
7531
|
-
* @param id subscription id to deregister.
|
|
7679
|
+
* @param id client subscription id to deregister.
|
|
7532
7680
|
*/
|
|
7533
7681
|
|
|
7534
7682
|
|
|
7535
|
-
async removeOnLogsListener(
|
|
7536
|
-
|
|
7537
|
-
const subInfo = this._logsSubscriptions[id];
|
|
7538
|
-
delete this._logsSubscriptions[id];
|
|
7539
|
-
await this._unsubscribe(subInfo, 'logsUnsubscribe');
|
|
7540
|
-
|
|
7541
|
-
this._updateSubscriptions();
|
|
7542
|
-
} else {
|
|
7543
|
-
console.warn(createSubscriptionWarningMessage(id, 'logs'));
|
|
7544
|
-
}
|
|
7683
|
+
async removeOnLogsListener(clientSubscriptionId) {
|
|
7684
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
|
|
7545
7685
|
}
|
|
7546
7686
|
/**
|
|
7547
7687
|
* @internal
|
|
@@ -7549,17 +7689,12 @@ class Connection {
|
|
|
7549
7689
|
|
|
7550
7690
|
|
|
7551
7691
|
_wsOnLogsNotification(notification) {
|
|
7552
|
-
const
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
const sub = this._logsSubscriptions[id];
|
|
7692
|
+
const {
|
|
7693
|
+
result,
|
|
7694
|
+
subscription
|
|
7695
|
+
} = superstruct.create(notification, LogsNotificationResult);
|
|
7557
7696
|
|
|
7558
|
-
|
|
7559
|
-
sub.callback(res.result.value, res.result.context);
|
|
7560
|
-
return;
|
|
7561
|
-
}
|
|
7562
|
-
}
|
|
7697
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
7563
7698
|
}
|
|
7564
7699
|
/**
|
|
7565
7700
|
* @internal
|
|
@@ -7567,14 +7702,12 @@ class Connection {
|
|
|
7567
7702
|
|
|
7568
7703
|
|
|
7569
7704
|
_wsOnSlotNotification(notification) {
|
|
7570
|
-
const
|
|
7705
|
+
const {
|
|
7706
|
+
result,
|
|
7707
|
+
subscription
|
|
7708
|
+
} = superstruct.create(notification, SlotNotificationResult);
|
|
7571
7709
|
|
|
7572
|
-
|
|
7573
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7574
|
-
sub.callback(res.result);
|
|
7575
|
-
return;
|
|
7576
|
-
}
|
|
7577
|
-
}
|
|
7710
|
+
this._handleServerNotification(subscription, [result]);
|
|
7578
7711
|
}
|
|
7579
7712
|
/**
|
|
7580
7713
|
* Register a callback to be invoked upon slot changes
|
|
@@ -7585,33 +7718,23 @@ class Connection {
|
|
|
7585
7718
|
|
|
7586
7719
|
|
|
7587
7720
|
onSlotChange(callback) {
|
|
7588
|
-
|
|
7589
|
-
this._slotSubscriptions[id] = {
|
|
7721
|
+
return this._makeSubscription({
|
|
7590
7722
|
callback,
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
return id;
|
|
7723
|
+
method: 'slotSubscribe',
|
|
7724
|
+
unsubscribeMethod: 'slotUnsubscribe'
|
|
7725
|
+
}, []
|
|
7726
|
+
/* args */
|
|
7727
|
+
);
|
|
7597
7728
|
}
|
|
7598
7729
|
/**
|
|
7599
7730
|
* Deregister a slot notification callback
|
|
7600
7731
|
*
|
|
7601
|
-
* @param id subscription id to deregister
|
|
7732
|
+
* @param id client subscription id to deregister
|
|
7602
7733
|
*/
|
|
7603
7734
|
|
|
7604
7735
|
|
|
7605
|
-
async removeSlotChangeListener(
|
|
7606
|
-
|
|
7607
|
-
const subInfo = this._slotSubscriptions[id];
|
|
7608
|
-
delete this._slotSubscriptions[id];
|
|
7609
|
-
await this._unsubscribe(subInfo, 'slotUnsubscribe');
|
|
7610
|
-
|
|
7611
|
-
this._updateSubscriptions();
|
|
7612
|
-
} else {
|
|
7613
|
-
console.warn(createSubscriptionWarningMessage(id, 'slot change'));
|
|
7614
|
-
}
|
|
7736
|
+
async removeSlotChangeListener(clientSubscriptionId) {
|
|
7737
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
|
|
7615
7738
|
}
|
|
7616
7739
|
/**
|
|
7617
7740
|
* @internal
|
|
@@ -7619,14 +7742,12 @@ class Connection {
|
|
|
7619
7742
|
|
|
7620
7743
|
|
|
7621
7744
|
_wsOnSlotUpdatesNotification(notification) {
|
|
7622
|
-
const
|
|
7745
|
+
const {
|
|
7746
|
+
result,
|
|
7747
|
+
subscription
|
|
7748
|
+
} = superstruct.create(notification, SlotUpdateNotificationResult);
|
|
7623
7749
|
|
|
7624
|
-
|
|
7625
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7626
|
-
sub.callback(res.result);
|
|
7627
|
-
return;
|
|
7628
|
-
}
|
|
7629
|
-
}
|
|
7750
|
+
this._handleServerNotification(subscription, [result]);
|
|
7630
7751
|
}
|
|
7631
7752
|
/**
|
|
7632
7753
|
* Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
|
|
@@ -7638,32 +7759,36 @@ class Connection {
|
|
|
7638
7759
|
|
|
7639
7760
|
|
|
7640
7761
|
onSlotUpdate(callback) {
|
|
7641
|
-
|
|
7642
|
-
this._slotUpdateSubscriptions[id] = {
|
|
7762
|
+
return this._makeSubscription({
|
|
7643
7763
|
callback,
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
return id;
|
|
7764
|
+
method: 'slotsUpdatesSubscribe',
|
|
7765
|
+
unsubscribeMethod: 'slotsUpdatesUnsubscribe'
|
|
7766
|
+
}, []
|
|
7767
|
+
/* args */
|
|
7768
|
+
);
|
|
7650
7769
|
}
|
|
7651
7770
|
/**
|
|
7652
7771
|
* Deregister a slot update notification callback
|
|
7653
7772
|
*
|
|
7654
|
-
* @param id subscription id to deregister
|
|
7773
|
+
* @param id client subscription id to deregister
|
|
7655
7774
|
*/
|
|
7656
7775
|
|
|
7657
7776
|
|
|
7658
|
-
async removeSlotUpdateListener(
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7777
|
+
async removeSlotUpdateListener(clientSubscriptionId) {
|
|
7778
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
|
|
7779
|
+
}
|
|
7780
|
+
/**
|
|
7781
|
+
* @internal
|
|
7782
|
+
*/
|
|
7663
7783
|
|
|
7664
|
-
|
|
7784
|
+
|
|
7785
|
+
async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
|
|
7786
|
+
const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7787
|
+
|
|
7788
|
+
if (dispose) {
|
|
7789
|
+
await dispose();
|
|
7665
7790
|
} else {
|
|
7666
|
-
console.warn(
|
|
7791
|
+
console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
|
|
7667
7792
|
}
|
|
7668
7793
|
}
|
|
7669
7794
|
|
|
@@ -7710,30 +7835,34 @@ class Connection {
|
|
|
7710
7835
|
|
|
7711
7836
|
|
|
7712
7837
|
_wsOnSignatureNotification(notification) {
|
|
7713
|
-
const
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7838
|
+
const {
|
|
7839
|
+
result,
|
|
7840
|
+
subscription
|
|
7841
|
+
} = superstruct.create(notification, SignatureNotificationResult);
|
|
7842
|
+
|
|
7843
|
+
if (result.value !== 'receivedSignature') {
|
|
7844
|
+
/**
|
|
7845
|
+
* Special case.
|
|
7846
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
7847
|
+
* subscription on the server side. We need to track which of these
|
|
7848
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
7849
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
7850
|
+
* (in which case we must tear down the server subscription) or an
|
|
7851
|
+
* already-processed signature (in which case the client can simply
|
|
7852
|
+
* clear out the subscription locally without telling the server).
|
|
7853
|
+
*
|
|
7854
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
7855
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
7856
|
+
*/
|
|
7857
|
+
this._subscriptionsAutoDisposedByRpc.add(subscription);
|
|
7858
|
+
}
|
|
7859
|
+
|
|
7860
|
+
this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{
|
|
7861
|
+
type: 'received'
|
|
7862
|
+
}, result.context] : [{
|
|
7863
|
+
type: 'status',
|
|
7864
|
+
result: result.value
|
|
7865
|
+
}, result.context]);
|
|
7737
7866
|
}
|
|
7738
7867
|
/**
|
|
7739
7868
|
* Register a callback to be invoked upon signature updates
|
|
@@ -7746,23 +7875,26 @@ class Connection {
|
|
|
7746
7875
|
|
|
7747
7876
|
|
|
7748
7877
|
onSignature(signature, callback, commitment) {
|
|
7749
|
-
const
|
|
7750
|
-
|
|
7751
|
-
|
|
7878
|
+
const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7879
|
+
);
|
|
7880
|
+
|
|
7881
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
7752
7882
|
callback: (notification, context) => {
|
|
7753
7883
|
if (notification.type === 'status') {
|
|
7754
|
-
callback(notification.result, context);
|
|
7884
|
+
callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
7885
|
+
// so no need to explicitly send an unsubscribe message.
|
|
7886
|
+
|
|
7887
|
+
try {
|
|
7888
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
7889
|
+
} catch {// Already removed.
|
|
7890
|
+
}
|
|
7755
7891
|
}
|
|
7756
7892
|
},
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
subscriptionId: null
|
|
7761
|
-
};
|
|
7762
|
-
|
|
7763
|
-
this._updateSubscriptions();
|
|
7893
|
+
method: 'signatureSubscribe',
|
|
7894
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
7895
|
+
}, args);
|
|
7764
7896
|
|
|
7765
|
-
return
|
|
7897
|
+
return clientSubscriptionId;
|
|
7766
7898
|
}
|
|
7767
7899
|
/**
|
|
7768
7900
|
* Register a callback to be invoked when a transaction is
|
|
@@ -7777,35 +7909,43 @@ class Connection {
|
|
|
7777
7909
|
|
|
7778
7910
|
|
|
7779
7911
|
onSignatureWithOptions(signature, callback, options) {
|
|
7780
|
-
const
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
options
|
|
7785
|
-
|
|
7912
|
+
const {
|
|
7913
|
+
commitment,
|
|
7914
|
+
...extra
|
|
7915
|
+
} = { ...options,
|
|
7916
|
+
commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7917
|
+
|
|
7786
7918
|
};
|
|
7787
7919
|
|
|
7788
|
-
this.
|
|
7920
|
+
const args = this._buildArgs([signature], commitment, undefined
|
|
7921
|
+
/* encoding */
|
|
7922
|
+
, extra);
|
|
7923
|
+
|
|
7924
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
7925
|
+
callback: (notification, context) => {
|
|
7926
|
+
callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
7927
|
+
// so no need to explicitly send an unsubscribe message.
|
|
7928
|
+
|
|
7929
|
+
try {
|
|
7930
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
7931
|
+
} catch {// Already removed.
|
|
7932
|
+
}
|
|
7933
|
+
},
|
|
7934
|
+
method: 'signatureSubscribe',
|
|
7935
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
7936
|
+
}, args);
|
|
7789
7937
|
|
|
7790
|
-
return
|
|
7938
|
+
return clientSubscriptionId;
|
|
7791
7939
|
}
|
|
7792
7940
|
/**
|
|
7793
7941
|
* Deregister a signature notification callback
|
|
7794
7942
|
*
|
|
7795
|
-
* @param id subscription id to deregister
|
|
7943
|
+
* @param id client subscription id to deregister
|
|
7796
7944
|
*/
|
|
7797
7945
|
|
|
7798
7946
|
|
|
7799
|
-
async removeSignatureListener(
|
|
7800
|
-
|
|
7801
|
-
const subInfo = this._signatureSubscriptions[id];
|
|
7802
|
-
delete this._signatureSubscriptions[id];
|
|
7803
|
-
await this._unsubscribe(subInfo, 'signatureUnsubscribe');
|
|
7804
|
-
|
|
7805
|
-
this._updateSubscriptions();
|
|
7806
|
-
} else {
|
|
7807
|
-
console.warn(createSubscriptionWarningMessage(id, 'signature result'));
|
|
7808
|
-
}
|
|
7947
|
+
async removeSignatureListener(clientSubscriptionId) {
|
|
7948
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
|
|
7809
7949
|
}
|
|
7810
7950
|
/**
|
|
7811
7951
|
* @internal
|
|
@@ -7813,14 +7953,12 @@ class Connection {
|
|
|
7813
7953
|
|
|
7814
7954
|
|
|
7815
7955
|
_wsOnRootNotification(notification) {
|
|
7816
|
-
const
|
|
7956
|
+
const {
|
|
7957
|
+
result,
|
|
7958
|
+
subscription
|
|
7959
|
+
} = superstruct.create(notification, RootNotificationResult);
|
|
7817
7960
|
|
|
7818
|
-
|
|
7819
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7820
|
-
sub.callback(res.result);
|
|
7821
|
-
return;
|
|
7822
|
-
}
|
|
7823
|
-
}
|
|
7961
|
+
this._handleServerNotification(subscription, [result]);
|
|
7824
7962
|
}
|
|
7825
7963
|
/**
|
|
7826
7964
|
* Register a callback to be invoked upon root changes
|
|
@@ -7831,33 +7969,23 @@ class Connection {
|
|
|
7831
7969
|
|
|
7832
7970
|
|
|
7833
7971
|
onRootChange(callback) {
|
|
7834
|
-
|
|
7835
|
-
this._rootSubscriptions[id] = {
|
|
7972
|
+
return this._makeSubscription({
|
|
7836
7973
|
callback,
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
return id;
|
|
7974
|
+
method: 'rootSubscribe',
|
|
7975
|
+
unsubscribeMethod: 'rootUnsubscribe'
|
|
7976
|
+
}, []
|
|
7977
|
+
/* args */
|
|
7978
|
+
);
|
|
7843
7979
|
}
|
|
7844
7980
|
/**
|
|
7845
7981
|
* Deregister a root notification callback
|
|
7846
7982
|
*
|
|
7847
|
-
* @param id subscription id to deregister
|
|
7983
|
+
* @param id client subscription id to deregister
|
|
7848
7984
|
*/
|
|
7849
7985
|
|
|
7850
7986
|
|
|
7851
|
-
async removeRootChangeListener(
|
|
7852
|
-
|
|
7853
|
-
const subInfo = this._rootSubscriptions[id];
|
|
7854
|
-
delete this._rootSubscriptions[id];
|
|
7855
|
-
await this._unsubscribe(subInfo, 'rootUnsubscribe');
|
|
7856
|
-
|
|
7857
|
-
this._updateSubscriptions();
|
|
7858
|
-
} else {
|
|
7859
|
-
console.warn(createSubscriptionWarningMessage(id, 'root change'));
|
|
7860
|
-
}
|
|
7987
|
+
async removeRootChangeListener(clientSubscriptionId) {
|
|
7988
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
|
|
7861
7989
|
}
|
|
7862
7990
|
|
|
7863
7991
|
}
|
|
@@ -9561,6 +9689,7 @@ exports.NONCE_ACCOUNT_LENGTH = NONCE_ACCOUNT_LENGTH;
|
|
|
9561
9689
|
exports.NonceAccount = NonceAccount;
|
|
9562
9690
|
exports.PACKET_DATA_SIZE = PACKET_DATA_SIZE;
|
|
9563
9691
|
exports.PublicKey = PublicKey;
|
|
9692
|
+
exports.SIGNATURE_LENGTH_IN_BYTES = SIGNATURE_LENGTH_IN_BYTES;
|
|
9564
9693
|
exports.SOLANA_SCHEMA = SOLANA_SCHEMA;
|
|
9565
9694
|
exports.STAKE_CONFIG_ID = STAKE_CONFIG_ID;
|
|
9566
9695
|
exports.STAKE_INSTRUCTION_LAYOUTS = STAKE_INSTRUCTION_LAYOUTS;
|