@solana/web3.js 1.41.1 → 1.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.browser.cjs.js +501 -371
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +501 -371
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +501 -371
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +37 -22
- package/lib/index.esm.js +501 -371
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +533 -612
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +1 -23
- package/lib/index.iife.min.js.map +1 -1
- package/package.json +8 -5
- package/src/connection.ts +657 -486
package/lib/index.cjs.js
CHANGED
|
@@ -4244,6 +4244,82 @@ class ComputeBudgetProgram {
|
|
|
4244
4244
|
}
|
|
4245
4245
|
ComputeBudgetProgram.programId = new PublicKey('ComputeBudget111111111111111111111111111111');
|
|
4246
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
|
+
|
|
4247
4323
|
const DESTROY_TIMEOUT_MS = 5000;
|
|
4248
4324
|
class AgentManager {
|
|
4249
4325
|
static _newAgent(useHttps) {
|
|
@@ -4459,6 +4535,12 @@ const BufferFromRawAccountData = superstruct.coerce(superstruct.instance(buffer.
|
|
|
4459
4535
|
*/
|
|
4460
4536
|
|
|
4461
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
|
+
*/
|
|
4462
4544
|
|
|
4463
4545
|
/**
|
|
4464
4546
|
* @internal
|
|
@@ -5333,14 +5415,9 @@ const LogsNotificationResult = superstruct.type({
|
|
|
5333
5415
|
* Filter for log subscriptions.
|
|
5334
5416
|
*/
|
|
5335
5417
|
|
|
5336
|
-
function createSubscriptionWarningMessage(id, label) {
|
|
5337
|
-
return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
|
|
5338
|
-
}
|
|
5339
5418
|
/**
|
|
5340
5419
|
* A connection to a fullnode JSON RPC endpoint
|
|
5341
5420
|
*/
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
5421
|
class Connection {
|
|
5345
5422
|
/** @internal */
|
|
5346
5423
|
|
|
@@ -5364,21 +5441,13 @@ class Connection {
|
|
|
5364
5441
|
|
|
5365
5442
|
/** @internal */
|
|
5366
5443
|
|
|
5367
|
-
/** @internal
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
/** @internal */
|
|
5376
|
-
|
|
5377
|
-
/** @internal */
|
|
5378
|
-
|
|
5379
|
-
/** @internal */
|
|
5380
|
-
|
|
5381
|
-
/** @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
|
+
*/
|
|
5382
5451
|
|
|
5383
5452
|
/** @internal */
|
|
5384
5453
|
|
|
@@ -5394,7 +5463,19 @@ class Connection {
|
|
|
5394
5463
|
|
|
5395
5464
|
/** @internal */
|
|
5396
5465
|
|
|
5397
|
-
/**
|
|
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
|
+
*/
|
|
5398
5479
|
|
|
5399
5480
|
/** @internal */
|
|
5400
5481
|
|
|
@@ -5416,6 +5497,7 @@ class Connection {
|
|
|
5416
5497
|
this._rpcWebSocketConnected = false;
|
|
5417
5498
|
this._rpcWebSocketHeartbeat = null;
|
|
5418
5499
|
this._rpcWebSocketIdleTimeout = null;
|
|
5500
|
+
this._rpcWebSocketGeneration = 0;
|
|
5419
5501
|
this._disableBlockhashCaching = false;
|
|
5420
5502
|
this._pollingBlockhash = false;
|
|
5421
5503
|
this._blockhashInfo = {
|
|
@@ -5424,20 +5506,11 @@ class Connection {
|
|
|
5424
5506
|
transactionSignatures: [],
|
|
5425
5507
|
simulatedSignatures: []
|
|
5426
5508
|
};
|
|
5427
|
-
this.
|
|
5428
|
-
this.
|
|
5429
|
-
this.
|
|
5430
|
-
this.
|
|
5431
|
-
this.
|
|
5432
|
-
this._rootSubscriptions = {};
|
|
5433
|
-
this._signatureSubscriptionCounter = 0;
|
|
5434
|
-
this._signatureSubscriptions = {};
|
|
5435
|
-
this._slotSubscriptionCounter = 0;
|
|
5436
|
-
this._slotSubscriptions = {};
|
|
5437
|
-
this._logsSubscriptionCounter = 0;
|
|
5438
|
-
this._logsSubscriptions = {};
|
|
5439
|
-
this._slotUpdateSubscriptionCounter = 0;
|
|
5440
|
-
this._slotUpdateSubscriptions = {};
|
|
5509
|
+
this._nextClientSubscriptionId = 0;
|
|
5510
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
5511
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
5512
|
+
this._subscriptionsByHash = {};
|
|
5513
|
+
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
5441
5514
|
let url = new URL(endpoint);
|
|
5442
5515
|
const useHttps = url.protocol === 'https:';
|
|
5443
5516
|
let wsEndpoint;
|
|
@@ -7205,6 +7278,8 @@ class Connection {
|
|
|
7205
7278
|
|
|
7206
7279
|
|
|
7207
7280
|
_wsOnClose(code) {
|
|
7281
|
+
this._rpcWebSocketGeneration++;
|
|
7282
|
+
|
|
7208
7283
|
if (this._rpcWebSocketHeartbeat) {
|
|
7209
7284
|
clearInterval(this._rpcWebSocketHeartbeat);
|
|
7210
7285
|
this._rpcWebSocketHeartbeat = null;
|
|
@@ -7218,85 +7293,20 @@ class Connection {
|
|
|
7218
7293
|
} // implicit close, prepare subscriptions for auto-reconnect
|
|
7219
7294
|
|
|
7220
7295
|
|
|
7221
|
-
this.
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
async _subscribe(sub, rpcMethod, rpcArgs) {
|
|
7229
|
-
if (sub.subscriptionId == null) {
|
|
7230
|
-
sub.subscriptionId = 'subscribing';
|
|
7231
|
-
|
|
7232
|
-
try {
|
|
7233
|
-
const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
|
|
7234
|
-
|
|
7235
|
-
if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
|
|
7236
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7237
|
-
sub.subscriptionId = id;
|
|
7238
|
-
}
|
|
7239
|
-
} catch (err) {
|
|
7240
|
-
if (sub.subscriptionId === 'subscribing') {
|
|
7241
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7242
|
-
sub.subscriptionId = null;
|
|
7243
|
-
}
|
|
7244
|
-
|
|
7245
|
-
if (err instanceof Error) {
|
|
7246
|
-
console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
|
|
7247
|
-
}
|
|
7248
|
-
}
|
|
7249
|
-
}
|
|
7250
|
-
}
|
|
7251
|
-
/**
|
|
7252
|
-
* @internal
|
|
7253
|
-
*/
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
async _unsubscribe(sub, rpcMethod) {
|
|
7257
|
-
const subscriptionId = sub.subscriptionId;
|
|
7258
|
-
|
|
7259
|
-
if (subscriptionId != null && typeof subscriptionId != 'string') {
|
|
7260
|
-
const unsubscribeId = subscriptionId;
|
|
7261
|
-
|
|
7262
|
-
try {
|
|
7263
|
-
await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
|
|
7264
|
-
} catch (err) {
|
|
7265
|
-
if (err instanceof Error) {
|
|
7266
|
-
console.error(`${rpcMethod} error:`, err.message);
|
|
7267
|
-
}
|
|
7268
|
-
}
|
|
7269
|
-
}
|
|
7270
|
-
}
|
|
7271
|
-
/**
|
|
7272
|
-
* @internal
|
|
7273
|
-
*/
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
_resetSubscriptions() {
|
|
7277
|
-
Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7278
|
-
Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7279
|
-
Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7280
|
-
Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7281
|
-
Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7282
|
-
Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7283
|
-
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
|
+
});
|
|
7284
7302
|
}
|
|
7285
7303
|
/**
|
|
7286
7304
|
* @internal
|
|
7287
7305
|
*/
|
|
7288
7306
|
|
|
7289
7307
|
|
|
7290
|
-
_updateSubscriptions() {
|
|
7291
|
-
|
|
7292
|
-
const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
|
|
7293
|
-
const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
|
|
7294
|
-
const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
|
|
7295
|
-
const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
|
|
7296
|
-
const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
|
|
7297
|
-
const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
|
|
7298
|
-
|
|
7299
|
-
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) {
|
|
7300
7310
|
if (this._rpcWebSocketConnected) {
|
|
7301
7311
|
this._rpcWebSocketConnected = false;
|
|
7302
7312
|
this._rpcWebSocketIdleTimeout = setTimeout(() => {
|
|
@@ -7328,60 +7338,167 @@ class Connection {
|
|
|
7328
7338
|
return;
|
|
7329
7339
|
}
|
|
7330
7340
|
|
|
7331
|
-
|
|
7332
|
-
const sub = this._accountChangeSubscriptions[id];
|
|
7333
|
-
|
|
7334
|
-
this._subscribe(sub, 'accountSubscribe', this._buildArgs([sub.publicKey], sub.commitment, 'base64'));
|
|
7335
|
-
}
|
|
7341
|
+
const activeWebSocketGeneration = this._rpcWebSocketGeneration;
|
|
7336
7342
|
|
|
7337
|
-
|
|
7338
|
-
|
|
7343
|
+
const isCurrentConnectionStillActive = () => {
|
|
7344
|
+
return activeWebSocketGeneration === this._rpcWebSocketGeneration;
|
|
7345
|
+
};
|
|
7339
7346
|
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
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];
|
|
7344
7353
|
|
|
7345
|
-
|
|
7346
|
-
|
|
7354
|
+
if (subscription === undefined) {
|
|
7355
|
+
// This entry has since been deleted. Skip.
|
|
7356
|
+
return;
|
|
7357
|
+
}
|
|
7347
7358
|
|
|
7348
|
-
|
|
7349
|
-
|
|
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
|
+
}
|
|
7350
7381
|
|
|
7351
|
-
|
|
7352
|
-
|
|
7382
|
+
await this._updateSubscriptions();
|
|
7383
|
+
return;
|
|
7384
|
+
}
|
|
7353
7385
|
|
|
7354
|
-
|
|
7355
|
-
|
|
7386
|
+
await (async () => {
|
|
7387
|
+
const {
|
|
7388
|
+
args,
|
|
7389
|
+
method
|
|
7390
|
+
} = subscription;
|
|
7356
7391
|
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
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?
|
|
7361
7411
|
|
|
7362
|
-
this._subscribe(sub, 'signatureSubscribe', args);
|
|
7363
|
-
}
|
|
7364
7412
|
|
|
7365
|
-
|
|
7366
|
-
|
|
7413
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7414
|
+
state: 'pending'
|
|
7415
|
+
};
|
|
7416
|
+
await this._updateSubscriptions();
|
|
7417
|
+
}
|
|
7418
|
+
})();
|
|
7419
|
+
break;
|
|
7367
7420
|
|
|
7368
|
-
|
|
7369
|
-
|
|
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
|
+
}
|
|
7370
7467
|
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7468
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7469
|
+
state: 'unsubscribed'
|
|
7470
|
+
};
|
|
7471
|
+
await this._updateSubscriptions();
|
|
7472
|
+
})();
|
|
7473
|
+
}
|
|
7374
7474
|
|
|
7375
|
-
|
|
7376
|
-
filter = {
|
|
7377
|
-
mentions: [sub.filter.toString()]
|
|
7378
|
-
};
|
|
7379
|
-
} else {
|
|
7380
|
-
filter = sub.filter;
|
|
7475
|
+
break;
|
|
7381
7476
|
}
|
|
7477
|
+
}));
|
|
7478
|
+
}
|
|
7479
|
+
/**
|
|
7480
|
+
* @internal
|
|
7481
|
+
*/
|
|
7382
7482
|
|
|
7383
|
-
|
|
7483
|
+
|
|
7484
|
+
_handleServerNotification(serverSubscriptionId, callbackArgs) {
|
|
7485
|
+
const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
|
|
7486
|
+
|
|
7487
|
+
if (callbacks === undefined) {
|
|
7488
|
+
return;
|
|
7384
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
|
+
});
|
|
7385
7502
|
}
|
|
7386
7503
|
/**
|
|
7387
7504
|
* @internal
|
|
@@ -7389,14 +7506,71 @@ class Connection {
|
|
|
7389
7506
|
|
|
7390
7507
|
|
|
7391
7508
|
_wsOnAccountNotification(notification) {
|
|
7392
|
-
const
|
|
7509
|
+
const {
|
|
7510
|
+
result,
|
|
7511
|
+
subscription
|
|
7512
|
+
} = superstruct.create(notification, AccountNotificationResult);
|
|
7393
7513
|
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
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);
|
|
7399
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;
|
|
7400
7574
|
}
|
|
7401
7575
|
/**
|
|
7402
7576
|
* Register a callback to be invoked whenever the specified account changes
|
|
@@ -7409,35 +7583,24 @@ class Connection {
|
|
|
7409
7583
|
|
|
7410
7584
|
|
|
7411
7585
|
onAccountChange(publicKey, callback, commitment) {
|
|
7412
|
-
const
|
|
7413
|
-
|
|
7414
|
-
publicKey: publicKey.toBase58(),
|
|
7415
|
-
callback,
|
|
7416
|
-
commitment,
|
|
7417
|
-
subscriptionId: null
|
|
7418
|
-
};
|
|
7586
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
7587
|
+
'base64');
|
|
7419
7588
|
|
|
7420
|
-
this.
|
|
7421
|
-
|
|
7422
|
-
|
|
7589
|
+
return this._makeSubscription({
|
|
7590
|
+
callback,
|
|
7591
|
+
method: 'accountSubscribe',
|
|
7592
|
+
unsubscribeMethod: 'accountUnsubscribe'
|
|
7593
|
+
}, args);
|
|
7423
7594
|
}
|
|
7424
7595
|
/**
|
|
7425
7596
|
* Deregister an account notification callback
|
|
7426
7597
|
*
|
|
7427
|
-
* @param id subscription id to deregister
|
|
7598
|
+
* @param id client subscription id to deregister
|
|
7428
7599
|
*/
|
|
7429
7600
|
|
|
7430
7601
|
|
|
7431
|
-
async removeAccountChangeListener(
|
|
7432
|
-
|
|
7433
|
-
const subInfo = this._accountChangeSubscriptions[id];
|
|
7434
|
-
delete this._accountChangeSubscriptions[id];
|
|
7435
|
-
await this._unsubscribe(subInfo, 'accountUnsubscribe');
|
|
7436
|
-
|
|
7437
|
-
this._updateSubscriptions();
|
|
7438
|
-
} else {
|
|
7439
|
-
console.warn(createSubscriptionWarningMessage(id, 'account change'));
|
|
7440
|
-
}
|
|
7602
|
+
async removeAccountChangeListener(clientSubscriptionId) {
|
|
7603
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
|
|
7441
7604
|
}
|
|
7442
7605
|
/**
|
|
7443
7606
|
* @internal
|
|
@@ -7445,21 +7608,15 @@ class Connection {
|
|
|
7445
7608
|
|
|
7446
7609
|
|
|
7447
7610
|
_wsOnProgramAccountNotification(notification) {
|
|
7448
|
-
const
|
|
7611
|
+
const {
|
|
7612
|
+
result,
|
|
7613
|
+
subscription
|
|
7614
|
+
} = superstruct.create(notification, ProgramAccountNotificationResult);
|
|
7449
7615
|
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
context
|
|
7455
|
-
} = res.result;
|
|
7456
|
-
sub.callback({
|
|
7457
|
-
accountId: value.pubkey,
|
|
7458
|
-
accountInfo: value.account
|
|
7459
|
-
}, context);
|
|
7460
|
-
return;
|
|
7461
|
-
}
|
|
7462
|
-
}
|
|
7616
|
+
this._handleServerNotification(subscription, [{
|
|
7617
|
+
accountId: result.value.pubkey,
|
|
7618
|
+
accountInfo: result.value.account
|
|
7619
|
+
}, result.context]);
|
|
7463
7620
|
}
|
|
7464
7621
|
/**
|
|
7465
7622
|
* Register a callback to be invoked whenever accounts owned by the
|
|
@@ -7474,36 +7631,30 @@ class Connection {
|
|
|
7474
7631
|
|
|
7475
7632
|
|
|
7476
7633
|
onProgramAccountChange(programId, callback, commitment, filters) {
|
|
7477
|
-
const
|
|
7478
|
-
|
|
7479
|
-
|
|
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({
|
|
7480
7644
|
callback,
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
};
|
|
7485
|
-
|
|
7486
|
-
this._updateSubscriptions();
|
|
7487
|
-
|
|
7488
|
-
return id;
|
|
7645
|
+
method: 'programSubscribe',
|
|
7646
|
+
unsubscribeMethod: 'programUnsubscribe'
|
|
7647
|
+
}, args);
|
|
7489
7648
|
}
|
|
7490
7649
|
/**
|
|
7491
7650
|
* Deregister an account notification callback
|
|
7492
7651
|
*
|
|
7493
|
-
* @param id subscription id to deregister
|
|
7652
|
+
* @param id client subscription id to deregister
|
|
7494
7653
|
*/
|
|
7495
7654
|
|
|
7496
7655
|
|
|
7497
|
-
async removeProgramAccountChangeListener(
|
|
7498
|
-
|
|
7499
|
-
const subInfo = this._programAccountChangeSubscriptions[id];
|
|
7500
|
-
delete this._programAccountChangeSubscriptions[id];
|
|
7501
|
-
await this._unsubscribe(subInfo, 'programUnsubscribe');
|
|
7502
|
-
|
|
7503
|
-
this._updateSubscriptions();
|
|
7504
|
-
} else {
|
|
7505
|
-
console.warn(createSubscriptionWarningMessage(id, 'program account change'));
|
|
7506
|
-
}
|
|
7656
|
+
async removeProgramAccountChangeListener(clientSubscriptionId) {
|
|
7657
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
|
|
7507
7658
|
}
|
|
7508
7659
|
/**
|
|
7509
7660
|
* Registers a callback to be invoked whenever logs are emitted.
|
|
@@ -7511,35 +7662,26 @@ class Connection {
|
|
|
7511
7662
|
|
|
7512
7663
|
|
|
7513
7664
|
onLogs(filter, callback, commitment) {
|
|
7514
|
-
const
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
commitment,
|
|
7519
|
-
subscriptionId: null
|
|
7520
|
-
};
|
|
7521
|
-
|
|
7522
|
-
this._updateSubscriptions();
|
|
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
|
-
return
|
|
7670
|
+
return this._makeSubscription({
|
|
7671
|
+
callback,
|
|
7672
|
+
method: 'logsSubscribe',
|
|
7673
|
+
unsubscribeMethod: 'logsUnsubscribe'
|
|
7674
|
+
}, args);
|
|
7525
7675
|
}
|
|
7526
7676
|
/**
|
|
7527
7677
|
* Deregister a logs callback.
|
|
7528
7678
|
*
|
|
7529
|
-
* @param id subscription id to deregister.
|
|
7679
|
+
* @param id client subscription id to deregister.
|
|
7530
7680
|
*/
|
|
7531
7681
|
|
|
7532
7682
|
|
|
7533
|
-
async removeOnLogsListener(
|
|
7534
|
-
|
|
7535
|
-
const subInfo = this._logsSubscriptions[id];
|
|
7536
|
-
delete this._logsSubscriptions[id];
|
|
7537
|
-
await this._unsubscribe(subInfo, 'logsUnsubscribe');
|
|
7538
|
-
|
|
7539
|
-
this._updateSubscriptions();
|
|
7540
|
-
} else {
|
|
7541
|
-
console.warn(createSubscriptionWarningMessage(id, 'logs'));
|
|
7542
|
-
}
|
|
7683
|
+
async removeOnLogsListener(clientSubscriptionId) {
|
|
7684
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
|
|
7543
7685
|
}
|
|
7544
7686
|
/**
|
|
7545
7687
|
* @internal
|
|
@@ -7547,17 +7689,12 @@ class Connection {
|
|
|
7547
7689
|
|
|
7548
7690
|
|
|
7549
7691
|
_wsOnLogsNotification(notification) {
|
|
7550
|
-
const
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
const sub = this._logsSubscriptions[id];
|
|
7692
|
+
const {
|
|
7693
|
+
result,
|
|
7694
|
+
subscription
|
|
7695
|
+
} = superstruct.create(notification, LogsNotificationResult);
|
|
7555
7696
|
|
|
7556
|
-
|
|
7557
|
-
sub.callback(res.result.value, res.result.context);
|
|
7558
|
-
return;
|
|
7559
|
-
}
|
|
7560
|
-
}
|
|
7697
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
7561
7698
|
}
|
|
7562
7699
|
/**
|
|
7563
7700
|
* @internal
|
|
@@ -7565,14 +7702,12 @@ class Connection {
|
|
|
7565
7702
|
|
|
7566
7703
|
|
|
7567
7704
|
_wsOnSlotNotification(notification) {
|
|
7568
|
-
const
|
|
7705
|
+
const {
|
|
7706
|
+
result,
|
|
7707
|
+
subscription
|
|
7708
|
+
} = superstruct.create(notification, SlotNotificationResult);
|
|
7569
7709
|
|
|
7570
|
-
|
|
7571
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7572
|
-
sub.callback(res.result);
|
|
7573
|
-
return;
|
|
7574
|
-
}
|
|
7575
|
-
}
|
|
7710
|
+
this._handleServerNotification(subscription, [result]);
|
|
7576
7711
|
}
|
|
7577
7712
|
/**
|
|
7578
7713
|
* Register a callback to be invoked upon slot changes
|
|
@@ -7583,33 +7718,23 @@ class Connection {
|
|
|
7583
7718
|
|
|
7584
7719
|
|
|
7585
7720
|
onSlotChange(callback) {
|
|
7586
|
-
|
|
7587
|
-
this._slotSubscriptions[id] = {
|
|
7721
|
+
return this._makeSubscription({
|
|
7588
7722
|
callback,
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
return id;
|
|
7723
|
+
method: 'slotSubscribe',
|
|
7724
|
+
unsubscribeMethod: 'slotUnsubscribe'
|
|
7725
|
+
}, []
|
|
7726
|
+
/* args */
|
|
7727
|
+
);
|
|
7595
7728
|
}
|
|
7596
7729
|
/**
|
|
7597
7730
|
* Deregister a slot notification callback
|
|
7598
7731
|
*
|
|
7599
|
-
* @param id subscription id to deregister
|
|
7732
|
+
* @param id client subscription id to deregister
|
|
7600
7733
|
*/
|
|
7601
7734
|
|
|
7602
7735
|
|
|
7603
|
-
async removeSlotChangeListener(
|
|
7604
|
-
|
|
7605
|
-
const subInfo = this._slotSubscriptions[id];
|
|
7606
|
-
delete this._slotSubscriptions[id];
|
|
7607
|
-
await this._unsubscribe(subInfo, 'slotUnsubscribe');
|
|
7608
|
-
|
|
7609
|
-
this._updateSubscriptions();
|
|
7610
|
-
} else {
|
|
7611
|
-
console.warn(createSubscriptionWarningMessage(id, 'slot change'));
|
|
7612
|
-
}
|
|
7736
|
+
async removeSlotChangeListener(clientSubscriptionId) {
|
|
7737
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
|
|
7613
7738
|
}
|
|
7614
7739
|
/**
|
|
7615
7740
|
* @internal
|
|
@@ -7617,14 +7742,12 @@ class Connection {
|
|
|
7617
7742
|
|
|
7618
7743
|
|
|
7619
7744
|
_wsOnSlotUpdatesNotification(notification) {
|
|
7620
|
-
const
|
|
7745
|
+
const {
|
|
7746
|
+
result,
|
|
7747
|
+
subscription
|
|
7748
|
+
} = superstruct.create(notification, SlotUpdateNotificationResult);
|
|
7621
7749
|
|
|
7622
|
-
|
|
7623
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7624
|
-
sub.callback(res.result);
|
|
7625
|
-
return;
|
|
7626
|
-
}
|
|
7627
|
-
}
|
|
7750
|
+
this._handleServerNotification(subscription, [result]);
|
|
7628
7751
|
}
|
|
7629
7752
|
/**
|
|
7630
7753
|
* Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
|
|
@@ -7636,32 +7759,36 @@ class Connection {
|
|
|
7636
7759
|
|
|
7637
7760
|
|
|
7638
7761
|
onSlotUpdate(callback) {
|
|
7639
|
-
|
|
7640
|
-
this._slotUpdateSubscriptions[id] = {
|
|
7762
|
+
return this._makeSubscription({
|
|
7641
7763
|
callback,
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
return id;
|
|
7764
|
+
method: 'slotsUpdatesSubscribe',
|
|
7765
|
+
unsubscribeMethod: 'slotsUpdatesUnsubscribe'
|
|
7766
|
+
}, []
|
|
7767
|
+
/* args */
|
|
7768
|
+
);
|
|
7648
7769
|
}
|
|
7649
7770
|
/**
|
|
7650
7771
|
* Deregister a slot update notification callback
|
|
7651
7772
|
*
|
|
7652
|
-
* @param id subscription id to deregister
|
|
7773
|
+
* @param id client subscription id to deregister
|
|
7653
7774
|
*/
|
|
7654
7775
|
|
|
7655
7776
|
|
|
7656
|
-
async removeSlotUpdateListener(
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7777
|
+
async removeSlotUpdateListener(clientSubscriptionId) {
|
|
7778
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
|
|
7779
|
+
}
|
|
7780
|
+
/**
|
|
7781
|
+
* @internal
|
|
7782
|
+
*/
|
|
7661
7783
|
|
|
7662
|
-
|
|
7784
|
+
|
|
7785
|
+
async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
|
|
7786
|
+
const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7787
|
+
|
|
7788
|
+
if (dispose) {
|
|
7789
|
+
await dispose();
|
|
7663
7790
|
} else {
|
|
7664
|
-
console.warn(
|
|
7791
|
+
console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
|
|
7665
7792
|
}
|
|
7666
7793
|
}
|
|
7667
7794
|
|
|
@@ -7708,30 +7835,34 @@ class Connection {
|
|
|
7708
7835
|
|
|
7709
7836
|
|
|
7710
7837
|
_wsOnSignatureNotification(notification) {
|
|
7711
|
-
const
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
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]);
|
|
7735
7866
|
}
|
|
7736
7867
|
/**
|
|
7737
7868
|
* Register a callback to be invoked upon signature updates
|
|
@@ -7744,23 +7875,26 @@ class Connection {
|
|
|
7744
7875
|
|
|
7745
7876
|
|
|
7746
7877
|
onSignature(signature, callback, commitment) {
|
|
7747
|
-
const
|
|
7748
|
-
|
|
7749
|
-
|
|
7878
|
+
const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7879
|
+
);
|
|
7880
|
+
|
|
7881
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
7750
7882
|
callback: (notification, context) => {
|
|
7751
7883
|
if (notification.type === 'status') {
|
|
7752
|
-
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
|
+
}
|
|
7753
7891
|
}
|
|
7754
7892
|
},
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
subscriptionId: null
|
|
7759
|
-
};
|
|
7893
|
+
method: 'signatureSubscribe',
|
|
7894
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
7895
|
+
}, args);
|
|
7760
7896
|
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
return id;
|
|
7897
|
+
return clientSubscriptionId;
|
|
7764
7898
|
}
|
|
7765
7899
|
/**
|
|
7766
7900
|
* Register a callback to be invoked when a transaction is
|
|
@@ -7775,35 +7909,43 @@ class Connection {
|
|
|
7775
7909
|
|
|
7776
7910
|
|
|
7777
7911
|
onSignatureWithOptions(signature, callback, options) {
|
|
7778
|
-
const
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
options
|
|
7783
|
-
|
|
7912
|
+
const {
|
|
7913
|
+
commitment,
|
|
7914
|
+
...extra
|
|
7915
|
+
} = { ...options,
|
|
7916
|
+
commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7917
|
+
|
|
7784
7918
|
};
|
|
7785
7919
|
|
|
7786
|
-
this.
|
|
7920
|
+
const args = this._buildArgs([signature], commitment, undefined
|
|
7921
|
+
/* encoding */
|
|
7922
|
+
, extra);
|
|
7787
7923
|
|
|
7788
|
-
|
|
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);
|
|
7937
|
+
|
|
7938
|
+
return clientSubscriptionId;
|
|
7789
7939
|
}
|
|
7790
7940
|
/**
|
|
7791
7941
|
* Deregister a signature notification callback
|
|
7792
7942
|
*
|
|
7793
|
-
* @param id subscription id to deregister
|
|
7943
|
+
* @param id client subscription id to deregister
|
|
7794
7944
|
*/
|
|
7795
7945
|
|
|
7796
7946
|
|
|
7797
|
-
async removeSignatureListener(
|
|
7798
|
-
|
|
7799
|
-
const subInfo = this._signatureSubscriptions[id];
|
|
7800
|
-
delete this._signatureSubscriptions[id];
|
|
7801
|
-
await this._unsubscribe(subInfo, 'signatureUnsubscribe');
|
|
7802
|
-
|
|
7803
|
-
this._updateSubscriptions();
|
|
7804
|
-
} else {
|
|
7805
|
-
console.warn(createSubscriptionWarningMessage(id, 'signature result'));
|
|
7806
|
-
}
|
|
7947
|
+
async removeSignatureListener(clientSubscriptionId) {
|
|
7948
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
|
|
7807
7949
|
}
|
|
7808
7950
|
/**
|
|
7809
7951
|
* @internal
|
|
@@ -7811,14 +7953,12 @@ class Connection {
|
|
|
7811
7953
|
|
|
7812
7954
|
|
|
7813
7955
|
_wsOnRootNotification(notification) {
|
|
7814
|
-
const
|
|
7956
|
+
const {
|
|
7957
|
+
result,
|
|
7958
|
+
subscription
|
|
7959
|
+
} = superstruct.create(notification, RootNotificationResult);
|
|
7815
7960
|
|
|
7816
|
-
|
|
7817
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7818
|
-
sub.callback(res.result);
|
|
7819
|
-
return;
|
|
7820
|
-
}
|
|
7821
|
-
}
|
|
7961
|
+
this._handleServerNotification(subscription, [result]);
|
|
7822
7962
|
}
|
|
7823
7963
|
/**
|
|
7824
7964
|
* Register a callback to be invoked upon root changes
|
|
@@ -7829,33 +7969,23 @@ class Connection {
|
|
|
7829
7969
|
|
|
7830
7970
|
|
|
7831
7971
|
onRootChange(callback) {
|
|
7832
|
-
|
|
7833
|
-
this._rootSubscriptions[id] = {
|
|
7972
|
+
return this._makeSubscription({
|
|
7834
7973
|
callback,
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
return id;
|
|
7974
|
+
method: 'rootSubscribe',
|
|
7975
|
+
unsubscribeMethod: 'rootUnsubscribe'
|
|
7976
|
+
}, []
|
|
7977
|
+
/* args */
|
|
7978
|
+
);
|
|
7841
7979
|
}
|
|
7842
7980
|
/**
|
|
7843
7981
|
* Deregister a root notification callback
|
|
7844
7982
|
*
|
|
7845
|
-
* @param id subscription id to deregister
|
|
7983
|
+
* @param id client subscription id to deregister
|
|
7846
7984
|
*/
|
|
7847
7985
|
|
|
7848
7986
|
|
|
7849
|
-
async removeRootChangeListener(
|
|
7850
|
-
|
|
7851
|
-
const subInfo = this._rootSubscriptions[id];
|
|
7852
|
-
delete this._rootSubscriptions[id];
|
|
7853
|
-
await this._unsubscribe(subInfo, 'rootUnsubscribe');
|
|
7854
|
-
|
|
7855
|
-
this._updateSubscriptions();
|
|
7856
|
-
} else {
|
|
7857
|
-
console.warn(createSubscriptionWarningMessage(id, 'root change'));
|
|
7858
|
-
}
|
|
7987
|
+
async removeRootChangeListener(clientSubscriptionId) {
|
|
7988
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
|
|
7859
7989
|
}
|
|
7860
7990
|
|
|
7861
7991
|
}
|