@solana/web3.js 1.40.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 +648 -388
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +646 -388
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +648 -388
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +96 -30
- package/lib/index.esm.js +646 -388
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +680 -629
- 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/compute-budget.ts +189 -0
- 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.esm.js
CHANGED
|
@@ -2085,6 +2085,16 @@ class Account {
|
|
|
2085
2085
|
|
|
2086
2086
|
const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader1111111111111111111111111111111111');
|
|
2087
2087
|
|
|
2088
|
+
/**
|
|
2089
|
+
* Maximum over-the-wire size of a Transaction
|
|
2090
|
+
*
|
|
2091
|
+
* 1280 is IPv6 minimum MTU
|
|
2092
|
+
* 40 bytes is the size of the IPv6 header
|
|
2093
|
+
* 8 bytes is the size of the fragment header
|
|
2094
|
+
*/
|
|
2095
|
+
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2096
|
+
const SIGNATURE_LENGTH_IN_BYTES = 64;
|
|
2097
|
+
|
|
2088
2098
|
/**
|
|
2089
2099
|
* Layout for a public key
|
|
2090
2100
|
*/
|
|
@@ -2344,20 +2354,8 @@ function assert (condition, message) {
|
|
|
2344
2354
|
|
|
2345
2355
|
/**
|
|
2346
2356
|
* Default (empty) signature
|
|
2347
|
-
*
|
|
2348
|
-
* Signatures are 64 bytes in length
|
|
2349
|
-
*/
|
|
2350
|
-
const DEFAULT_SIGNATURE = Buffer.alloc(64).fill(0);
|
|
2351
|
-
/**
|
|
2352
|
-
* Maximum over-the-wire size of a Transaction
|
|
2353
|
-
*
|
|
2354
|
-
* 1280 is IPv6 minimum MTU
|
|
2355
|
-
* 40 bytes is the size of the IPv6 header
|
|
2356
|
-
* 8 bytes is the size of the fragment header
|
|
2357
2357
|
*/
|
|
2358
|
-
|
|
2359
|
-
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
2360
|
-
const SIGNATURE_LENGTH = 64;
|
|
2358
|
+
const DEFAULT_SIGNATURE = Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
|
|
2361
2359
|
/**
|
|
2362
2360
|
* Account metadata used to define instructions
|
|
2363
2361
|
*/
|
|
@@ -2987,8 +2985,8 @@ class Transaction {
|
|
|
2987
2985
|
let signatures = [];
|
|
2988
2986
|
|
|
2989
2987
|
for (let i = 0; i < signatureCount; i++) {
|
|
2990
|
-
const signature = byteArray.slice(0,
|
|
2991
|
-
byteArray = byteArray.slice(
|
|
2988
|
+
const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
|
|
2989
|
+
byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
|
|
2992
2990
|
signatures.push(bs58.encode(Buffer.from(signature)));
|
|
2993
2991
|
}
|
|
2994
2992
|
|
|
@@ -3877,11 +3875,11 @@ class SystemProgram {
|
|
|
3877
3875
|
}
|
|
3878
3876
|
SystemProgram.programId = new PublicKey('11111111111111111111111111111111');
|
|
3879
3877
|
|
|
3880
|
-
// Keep program chunks under PACKET_DATA_SIZE, leaving enough room for the
|
|
3881
3878
|
// rest of the Transaction fields
|
|
3882
3879
|
//
|
|
3883
3880
|
// TODO: replace 300 with a proper constant for the size of the other
|
|
3884
3881
|
// Transaction fields
|
|
3882
|
+
|
|
3885
3883
|
const CHUNK_SIZE = PACKET_DATA_SIZE - 300;
|
|
3886
3884
|
/**
|
|
3887
3885
|
* Program loader interface
|
|
@@ -4081,6 +4079,212 @@ class BpfLoader {
|
|
|
4081
4079
|
|
|
4082
4080
|
}
|
|
4083
4081
|
|
|
4082
|
+
/**
|
|
4083
|
+
* Compute Budget Instruction class
|
|
4084
|
+
*/
|
|
4085
|
+
|
|
4086
|
+
class ComputeBudgetInstruction {
|
|
4087
|
+
/**
|
|
4088
|
+
* @internal
|
|
4089
|
+
*/
|
|
4090
|
+
constructor() {}
|
|
4091
|
+
/**
|
|
4092
|
+
* Decode a compute budget instruction and retrieve the instruction type.
|
|
4093
|
+
*/
|
|
4094
|
+
|
|
4095
|
+
|
|
4096
|
+
static decodeInstructionType(instruction) {
|
|
4097
|
+
this.checkProgramId(instruction.programId);
|
|
4098
|
+
const instructionTypeLayout = BufferLayout.u8('instruction');
|
|
4099
|
+
const typeIndex = instructionTypeLayout.decode(instruction.data);
|
|
4100
|
+
let type;
|
|
4101
|
+
|
|
4102
|
+
for (const [ixType, layout] of Object.entries(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS)) {
|
|
4103
|
+
if (layout.index == typeIndex) {
|
|
4104
|
+
type = ixType;
|
|
4105
|
+
break;
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
|
|
4109
|
+
if (!type) {
|
|
4110
|
+
throw new Error('Instruction type incorrect; not a ComputeBudgetInstruction');
|
|
4111
|
+
}
|
|
4112
|
+
|
|
4113
|
+
return type;
|
|
4114
|
+
}
|
|
4115
|
+
/**
|
|
4116
|
+
* Decode request units compute budget instruction and retrieve the instruction params.
|
|
4117
|
+
*/
|
|
4118
|
+
|
|
4119
|
+
|
|
4120
|
+
static decodeRequestUnits(instruction) {
|
|
4121
|
+
this.checkProgramId(instruction.programId);
|
|
4122
|
+
const {
|
|
4123
|
+
units,
|
|
4124
|
+
additionalFee
|
|
4125
|
+
} = decodeData(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits, instruction.data);
|
|
4126
|
+
return {
|
|
4127
|
+
units,
|
|
4128
|
+
additionalFee
|
|
4129
|
+
};
|
|
4130
|
+
}
|
|
4131
|
+
/**
|
|
4132
|
+
* Decode request heap frame compute budget instruction and retrieve the instruction params.
|
|
4133
|
+
*/
|
|
4134
|
+
|
|
4135
|
+
|
|
4136
|
+
static decodeRequestHeapFrame(instruction) {
|
|
4137
|
+
this.checkProgramId(instruction.programId);
|
|
4138
|
+
const {
|
|
4139
|
+
bytes
|
|
4140
|
+
} = decodeData(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame, instruction.data);
|
|
4141
|
+
return {
|
|
4142
|
+
bytes
|
|
4143
|
+
};
|
|
4144
|
+
}
|
|
4145
|
+
/**
|
|
4146
|
+
* @internal
|
|
4147
|
+
*/
|
|
4148
|
+
|
|
4149
|
+
|
|
4150
|
+
static checkProgramId(programId) {
|
|
4151
|
+
if (!programId.equals(ComputeBudgetProgram.programId)) {
|
|
4152
|
+
throw new Error('invalid instruction; programId is not ComputeBudgetProgram');
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
|
|
4156
|
+
}
|
|
4157
|
+
/**
|
|
4158
|
+
* An enumeration of valid ComputeBudgetInstructionType's
|
|
4159
|
+
*/
|
|
4160
|
+
|
|
4161
|
+
/**
|
|
4162
|
+
* An enumeration of valid ComputeBudget InstructionType's
|
|
4163
|
+
* @internal
|
|
4164
|
+
*/
|
|
4165
|
+
const COMPUTE_BUDGET_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
4166
|
+
RequestUnits: {
|
|
4167
|
+
index: 0,
|
|
4168
|
+
layout: BufferLayout.struct([BufferLayout.u8('instruction'), BufferLayout.u32('units'), BufferLayout.u32('additionalFee')])
|
|
4169
|
+
},
|
|
4170
|
+
RequestHeapFrame: {
|
|
4171
|
+
index: 1,
|
|
4172
|
+
layout: BufferLayout.struct([BufferLayout.u8('instruction'), BufferLayout.u32('bytes')])
|
|
4173
|
+
}
|
|
4174
|
+
});
|
|
4175
|
+
/**
|
|
4176
|
+
* Factory class for transaction instructions to interact with the Compute Budget program
|
|
4177
|
+
*/
|
|
4178
|
+
|
|
4179
|
+
class ComputeBudgetProgram {
|
|
4180
|
+
/**
|
|
4181
|
+
* @internal
|
|
4182
|
+
*/
|
|
4183
|
+
constructor() {}
|
|
4184
|
+
/**
|
|
4185
|
+
* Public key that identifies the Compute Budget program
|
|
4186
|
+
*/
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
static requestUnits(params) {
|
|
4190
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits;
|
|
4191
|
+
const data = encodeData(type, params);
|
|
4192
|
+
return new TransactionInstruction({
|
|
4193
|
+
keys: [],
|
|
4194
|
+
programId: this.programId,
|
|
4195
|
+
data
|
|
4196
|
+
});
|
|
4197
|
+
}
|
|
4198
|
+
|
|
4199
|
+
static requestHeapFrame(params) {
|
|
4200
|
+
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame;
|
|
4201
|
+
const data = encodeData(type, params);
|
|
4202
|
+
return new TransactionInstruction({
|
|
4203
|
+
keys: [],
|
|
4204
|
+
programId: this.programId,
|
|
4205
|
+
data
|
|
4206
|
+
});
|
|
4207
|
+
}
|
|
4208
|
+
|
|
4209
|
+
}
|
|
4210
|
+
ComputeBudgetProgram.programId = new PublicKey('ComputeBudget111111111111111111111111111111');
|
|
4211
|
+
|
|
4212
|
+
var objToString = Object.prototype.toString;
|
|
4213
|
+
var objKeys = Object.keys || function(obj) {
|
|
4214
|
+
var keys = [];
|
|
4215
|
+
for (var name in obj) {
|
|
4216
|
+
keys.push(name);
|
|
4217
|
+
}
|
|
4218
|
+
return keys;
|
|
4219
|
+
};
|
|
4220
|
+
|
|
4221
|
+
function stringify(val, isArrayProp) {
|
|
4222
|
+
var i, max, str, keys, key, propVal, toStr;
|
|
4223
|
+
if (val === true) {
|
|
4224
|
+
return "true";
|
|
4225
|
+
}
|
|
4226
|
+
if (val === false) {
|
|
4227
|
+
return "false";
|
|
4228
|
+
}
|
|
4229
|
+
switch (typeof val) {
|
|
4230
|
+
case "object":
|
|
4231
|
+
if (val === null) {
|
|
4232
|
+
return null;
|
|
4233
|
+
} else if (val.toJSON && typeof val.toJSON === "function") {
|
|
4234
|
+
return stringify(val.toJSON(), isArrayProp);
|
|
4235
|
+
} else {
|
|
4236
|
+
toStr = objToString.call(val);
|
|
4237
|
+
if (toStr === "[object Array]") {
|
|
4238
|
+
str = '[';
|
|
4239
|
+
max = val.length - 1;
|
|
4240
|
+
for(i = 0; i < max; i++) {
|
|
4241
|
+
str += stringify(val[i], true) + ',';
|
|
4242
|
+
}
|
|
4243
|
+
if (max > -1) {
|
|
4244
|
+
str += stringify(val[i], true);
|
|
4245
|
+
}
|
|
4246
|
+
return str + ']';
|
|
4247
|
+
} else if (toStr === "[object Object]") {
|
|
4248
|
+
// only object is left
|
|
4249
|
+
keys = objKeys(val).sort();
|
|
4250
|
+
max = keys.length;
|
|
4251
|
+
str = "";
|
|
4252
|
+
i = 0;
|
|
4253
|
+
while (i < max) {
|
|
4254
|
+
key = keys[i];
|
|
4255
|
+
propVal = stringify(val[key], false);
|
|
4256
|
+
if (propVal !== undefined) {
|
|
4257
|
+
if (str) {
|
|
4258
|
+
str += ',';
|
|
4259
|
+
}
|
|
4260
|
+
str += JSON.stringify(key) + ':' + propVal;
|
|
4261
|
+
}
|
|
4262
|
+
i++;
|
|
4263
|
+
}
|
|
4264
|
+
return '{' + str + '}';
|
|
4265
|
+
} else {
|
|
4266
|
+
return JSON.stringify(val);
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
case "function":
|
|
4270
|
+
case "undefined":
|
|
4271
|
+
return isArrayProp ? null : undefined;
|
|
4272
|
+
case "string":
|
|
4273
|
+
return JSON.stringify(val);
|
|
4274
|
+
default:
|
|
4275
|
+
return isFinite(val) ? val : null;
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
var fastStableStringify = function(val) {
|
|
4280
|
+
var returnVal = stringify(val, false);
|
|
4281
|
+
if (returnVal !== undefined) {
|
|
4282
|
+
return ''+ returnVal;
|
|
4283
|
+
}
|
|
4284
|
+
};
|
|
4285
|
+
|
|
4286
|
+
var fastStableStringify$1 = fastStableStringify;
|
|
4287
|
+
|
|
4084
4288
|
const DESTROY_TIMEOUT_MS = 5000;
|
|
4085
4289
|
class AgentManager {
|
|
4086
4290
|
static _newAgent(useHttps) {
|
|
@@ -4296,6 +4500,12 @@ const BufferFromRawAccountData = coerce(instance(Buffer), RawAccountDataResult,
|
|
|
4296
4500
|
*/
|
|
4297
4501
|
|
|
4298
4502
|
const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
|
|
4503
|
+
/**
|
|
4504
|
+
* HACK.
|
|
4505
|
+
* Copied from rpc-websockets/dist/lib/client.
|
|
4506
|
+
* Otherwise, `yarn build` fails with:
|
|
4507
|
+
* https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
|
|
4508
|
+
*/
|
|
4299
4509
|
|
|
4300
4510
|
/**
|
|
4301
4511
|
* @internal
|
|
@@ -5170,14 +5380,9 @@ const LogsNotificationResult = type({
|
|
|
5170
5380
|
* Filter for log subscriptions.
|
|
5171
5381
|
*/
|
|
5172
5382
|
|
|
5173
|
-
function createSubscriptionWarningMessage(id, label) {
|
|
5174
|
-
return 'Ignored unsubscribe request because an active subscription ' + `with id \`${id}\` for '${label}' events could not be found.`;
|
|
5175
|
-
}
|
|
5176
5383
|
/**
|
|
5177
5384
|
* A connection to a fullnode JSON RPC endpoint
|
|
5178
5385
|
*/
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
5386
|
class Connection {
|
|
5182
5387
|
/** @internal */
|
|
5183
5388
|
|
|
@@ -5201,21 +5406,13 @@ class Connection {
|
|
|
5201
5406
|
|
|
5202
5407
|
/** @internal */
|
|
5203
5408
|
|
|
5204
|
-
/** @internal
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
/** @internal */
|
|
5213
|
-
|
|
5214
|
-
/** @internal */
|
|
5215
|
-
|
|
5216
|
-
/** @internal */
|
|
5217
|
-
|
|
5218
|
-
/** @internal */
|
|
5409
|
+
/** @internal
|
|
5410
|
+
* A number that we increment every time an active connection closes.
|
|
5411
|
+
* Used to determine whether the same socket connection that was open
|
|
5412
|
+
* when an async operation started is the same one that's active when
|
|
5413
|
+
* its continuation fires.
|
|
5414
|
+
*
|
|
5415
|
+
*/
|
|
5219
5416
|
|
|
5220
5417
|
/** @internal */
|
|
5221
5418
|
|
|
@@ -5231,7 +5428,19 @@ class Connection {
|
|
|
5231
5428
|
|
|
5232
5429
|
/** @internal */
|
|
5233
5430
|
|
|
5234
|
-
/**
|
|
5431
|
+
/**
|
|
5432
|
+
* Special case.
|
|
5433
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
5434
|
+
* subscription on the server side. We need to track which of these
|
|
5435
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
5436
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
5437
|
+
* (in which case we must tear down the server subscription) or an
|
|
5438
|
+
* already-processed signature (in which case the client can simply
|
|
5439
|
+
* clear out the subscription locally without telling the server).
|
|
5440
|
+
*
|
|
5441
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
5442
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
5443
|
+
*/
|
|
5235
5444
|
|
|
5236
5445
|
/** @internal */
|
|
5237
5446
|
|
|
@@ -5253,6 +5462,7 @@ class Connection {
|
|
|
5253
5462
|
this._rpcWebSocketConnected = false;
|
|
5254
5463
|
this._rpcWebSocketHeartbeat = null;
|
|
5255
5464
|
this._rpcWebSocketIdleTimeout = null;
|
|
5465
|
+
this._rpcWebSocketGeneration = 0;
|
|
5256
5466
|
this._disableBlockhashCaching = false;
|
|
5257
5467
|
this._pollingBlockhash = false;
|
|
5258
5468
|
this._blockhashInfo = {
|
|
@@ -5261,20 +5471,11 @@ class Connection {
|
|
|
5261
5471
|
transactionSignatures: [],
|
|
5262
5472
|
simulatedSignatures: []
|
|
5263
5473
|
};
|
|
5264
|
-
this.
|
|
5265
|
-
this.
|
|
5266
|
-
this.
|
|
5267
|
-
this.
|
|
5268
|
-
this.
|
|
5269
|
-
this._rootSubscriptions = {};
|
|
5270
|
-
this._signatureSubscriptionCounter = 0;
|
|
5271
|
-
this._signatureSubscriptions = {};
|
|
5272
|
-
this._slotSubscriptionCounter = 0;
|
|
5273
|
-
this._slotSubscriptions = {};
|
|
5274
|
-
this._logsSubscriptionCounter = 0;
|
|
5275
|
-
this._logsSubscriptions = {};
|
|
5276
|
-
this._slotUpdateSubscriptionCounter = 0;
|
|
5277
|
-
this._slotUpdateSubscriptions = {};
|
|
5474
|
+
this._nextClientSubscriptionId = 0;
|
|
5475
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
5476
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
5477
|
+
this._subscriptionsByHash = {};
|
|
5478
|
+
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
5278
5479
|
let url = new URL(endpoint);
|
|
5279
5480
|
const useHttps = url.protocol === 'https:';
|
|
5280
5481
|
let wsEndpoint;
|
|
@@ -7042,6 +7243,8 @@ class Connection {
|
|
|
7042
7243
|
|
|
7043
7244
|
|
|
7044
7245
|
_wsOnClose(code) {
|
|
7246
|
+
this._rpcWebSocketGeneration++;
|
|
7247
|
+
|
|
7045
7248
|
if (this._rpcWebSocketHeartbeat) {
|
|
7046
7249
|
clearInterval(this._rpcWebSocketHeartbeat);
|
|
7047
7250
|
this._rpcWebSocketHeartbeat = null;
|
|
@@ -7055,85 +7258,20 @@ class Connection {
|
|
|
7055
7258
|
} // implicit close, prepare subscriptions for auto-reconnect
|
|
7056
7259
|
|
|
7057
7260
|
|
|
7058
|
-
this.
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
async _subscribe(sub, rpcMethod, rpcArgs) {
|
|
7066
|
-
if (sub.subscriptionId == null) {
|
|
7067
|
-
sub.subscriptionId = 'subscribing';
|
|
7068
|
-
|
|
7069
|
-
try {
|
|
7070
|
-
const id = await this._rpcWebSocket.call(rpcMethod, rpcArgs);
|
|
7071
|
-
|
|
7072
|
-
if (typeof id === 'number' && sub.subscriptionId === 'subscribing') {
|
|
7073
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7074
|
-
sub.subscriptionId = id;
|
|
7075
|
-
}
|
|
7076
|
-
} catch (err) {
|
|
7077
|
-
if (sub.subscriptionId === 'subscribing') {
|
|
7078
|
-
// eslint-disable-next-line require-atomic-updates
|
|
7079
|
-
sub.subscriptionId = null;
|
|
7080
|
-
}
|
|
7081
|
-
|
|
7082
|
-
if (err instanceof Error) {
|
|
7083
|
-
console.error(`${rpcMethod} error for argument`, rpcArgs, err.message);
|
|
7084
|
-
}
|
|
7085
|
-
}
|
|
7086
|
-
}
|
|
7087
|
-
}
|
|
7088
|
-
/**
|
|
7089
|
-
* @internal
|
|
7090
|
-
*/
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
async _unsubscribe(sub, rpcMethod) {
|
|
7094
|
-
const subscriptionId = sub.subscriptionId;
|
|
7095
|
-
|
|
7096
|
-
if (subscriptionId != null && typeof subscriptionId != 'string') {
|
|
7097
|
-
const unsubscribeId = subscriptionId;
|
|
7098
|
-
|
|
7099
|
-
try {
|
|
7100
|
-
await this._rpcWebSocket.call(rpcMethod, [unsubscribeId]);
|
|
7101
|
-
} catch (err) {
|
|
7102
|
-
if (err instanceof Error) {
|
|
7103
|
-
console.error(`${rpcMethod} error:`, err.message);
|
|
7104
|
-
}
|
|
7105
|
-
}
|
|
7106
|
-
}
|
|
7107
|
-
}
|
|
7108
|
-
/**
|
|
7109
|
-
* @internal
|
|
7110
|
-
*/
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
_resetSubscriptions() {
|
|
7114
|
-
Object.values(this._accountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7115
|
-
Object.values(this._logsSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7116
|
-
Object.values(this._programAccountChangeSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7117
|
-
Object.values(this._rootSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7118
|
-
Object.values(this._signatureSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7119
|
-
Object.values(this._slotSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7120
|
-
Object.values(this._slotUpdateSubscriptions).forEach(s => s.subscriptionId = null);
|
|
7261
|
+
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
7262
|
+
Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
|
|
7263
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7264
|
+
state: 'pending'
|
|
7265
|
+
};
|
|
7266
|
+
});
|
|
7121
7267
|
}
|
|
7122
7268
|
/**
|
|
7123
7269
|
* @internal
|
|
7124
7270
|
*/
|
|
7125
7271
|
|
|
7126
7272
|
|
|
7127
|
-
_updateSubscriptions() {
|
|
7128
|
-
|
|
7129
|
-
const programKeys = Object.keys(this._programAccountChangeSubscriptions).map(Number);
|
|
7130
|
-
const slotKeys = Object.keys(this._slotSubscriptions).map(Number);
|
|
7131
|
-
const slotUpdateKeys = Object.keys(this._slotUpdateSubscriptions).map(Number);
|
|
7132
|
-
const signatureKeys = Object.keys(this._signatureSubscriptions).map(Number);
|
|
7133
|
-
const rootKeys = Object.keys(this._rootSubscriptions).map(Number);
|
|
7134
|
-
const logsKeys = Object.keys(this._logsSubscriptions).map(Number);
|
|
7135
|
-
|
|
7136
|
-
if (accountKeys.length === 0 && programKeys.length === 0 && slotKeys.length === 0 && slotUpdateKeys.length === 0 && signatureKeys.length === 0 && rootKeys.length === 0 && logsKeys.length === 0) {
|
|
7273
|
+
async _updateSubscriptions() {
|
|
7274
|
+
if (Object.keys(this._subscriptionsByHash).length === 0) {
|
|
7137
7275
|
if (this._rpcWebSocketConnected) {
|
|
7138
7276
|
this._rpcWebSocketConnected = false;
|
|
7139
7277
|
this._rpcWebSocketIdleTimeout = setTimeout(() => {
|
|
@@ -7165,60 +7303,167 @@ class Connection {
|
|
|
7165
7303
|
return;
|
|
7166
7304
|
}
|
|
7167
7305
|
|
|
7168
|
-
|
|
7169
|
-
const sub = this._accountChangeSubscriptions[id];
|
|
7306
|
+
const activeWebSocketGeneration = this._rpcWebSocketGeneration;
|
|
7170
7307
|
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
for (let id of programKeys) {
|
|
7175
|
-
const sub = this._programAccountChangeSubscriptions[id];
|
|
7308
|
+
const isCurrentConnectionStillActive = () => {
|
|
7309
|
+
return activeWebSocketGeneration === this._rpcWebSocketGeneration;
|
|
7310
|
+
};
|
|
7176
7311
|
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7312
|
+
await Promise.all( // Don't be tempted to change this to `Object.entries`. We call
|
|
7313
|
+
// `_updateSubscriptions` recursively when processing the state,
|
|
7314
|
+
// so it's important that we look up the *current* version of
|
|
7315
|
+
// each subscription, every time we process a hash.
|
|
7316
|
+
Object.keys(this._subscriptionsByHash).map(async hash => {
|
|
7317
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7181
7318
|
|
|
7182
|
-
|
|
7183
|
-
|
|
7319
|
+
if (subscription === undefined) {
|
|
7320
|
+
// This entry has since been deleted. Skip.
|
|
7321
|
+
return;
|
|
7322
|
+
}
|
|
7184
7323
|
|
|
7185
|
-
|
|
7186
|
-
|
|
7324
|
+
switch (subscription.state) {
|
|
7325
|
+
case 'pending':
|
|
7326
|
+
case 'unsubscribed':
|
|
7327
|
+
if (subscription.callbacks.size === 0) {
|
|
7328
|
+
/**
|
|
7329
|
+
* You can end up here when:
|
|
7330
|
+
*
|
|
7331
|
+
* - a subscription has recently unsubscribed
|
|
7332
|
+
* without having new callbacks added to it
|
|
7333
|
+
* while the unsubscribe was in flight, or
|
|
7334
|
+
* - when a pending subscription has its
|
|
7335
|
+
* listeners removed before a request was
|
|
7336
|
+
* sent to the server.
|
|
7337
|
+
*
|
|
7338
|
+
* Being that nobody is interested in this
|
|
7339
|
+
* subscription any longer, delete it.
|
|
7340
|
+
*/
|
|
7341
|
+
delete this._subscriptionsByHash[hash];
|
|
7342
|
+
|
|
7343
|
+
if (subscription.state === 'unsubscribed') {
|
|
7344
|
+
delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId];
|
|
7345
|
+
}
|
|
7187
7346
|
|
|
7188
|
-
|
|
7189
|
-
|
|
7347
|
+
await this._updateSubscriptions();
|
|
7348
|
+
return;
|
|
7349
|
+
}
|
|
7190
7350
|
|
|
7191
|
-
|
|
7192
|
-
|
|
7351
|
+
await (async () => {
|
|
7352
|
+
const {
|
|
7353
|
+
args,
|
|
7354
|
+
method
|
|
7355
|
+
} = subscription;
|
|
7193
7356
|
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7357
|
+
try {
|
|
7358
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7359
|
+
state: 'subscribing'
|
|
7360
|
+
};
|
|
7361
|
+
const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
|
|
7362
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7363
|
+
serverSubscriptionId,
|
|
7364
|
+
state: 'subscribed'
|
|
7365
|
+
};
|
|
7366
|
+
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
|
|
7367
|
+
await this._updateSubscriptions();
|
|
7368
|
+
} catch (e) {
|
|
7369
|
+
if (e instanceof Error) {
|
|
7370
|
+
console.error(`${method} error for argument`, args, e.message);
|
|
7371
|
+
}
|
|
7372
|
+
|
|
7373
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7374
|
+
return;
|
|
7375
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7198
7376
|
|
|
7199
|
-
this._subscribe(sub, 'signatureSubscribe', args);
|
|
7200
|
-
}
|
|
7201
7377
|
|
|
7202
|
-
|
|
7203
|
-
|
|
7378
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7379
|
+
state: 'pending'
|
|
7380
|
+
};
|
|
7381
|
+
await this._updateSubscriptions();
|
|
7382
|
+
}
|
|
7383
|
+
})();
|
|
7384
|
+
break;
|
|
7204
7385
|
|
|
7205
|
-
|
|
7206
|
-
|
|
7386
|
+
case 'subscribed':
|
|
7387
|
+
if (subscription.callbacks.size === 0) {
|
|
7388
|
+
// By the time we successfully set up a subscription
|
|
7389
|
+
// with the server, the client stopped caring about it.
|
|
7390
|
+
// Tear it down now.
|
|
7391
|
+
await (async () => {
|
|
7392
|
+
const {
|
|
7393
|
+
serverSubscriptionId,
|
|
7394
|
+
unsubscribeMethod
|
|
7395
|
+
} = subscription;
|
|
7396
|
+
|
|
7397
|
+
if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) {
|
|
7398
|
+
/**
|
|
7399
|
+
* Special case.
|
|
7400
|
+
* If we're dealing with a subscription that has been auto-
|
|
7401
|
+
* disposed by the RPC, then we can skip the RPC call to
|
|
7402
|
+
* tear down the subscription here.
|
|
7403
|
+
*
|
|
7404
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
7405
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
7406
|
+
*/
|
|
7407
|
+
this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
|
|
7408
|
+
} else {
|
|
7409
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7410
|
+
state: 'unsubscribing'
|
|
7411
|
+
};
|
|
7412
|
+
|
|
7413
|
+
try {
|
|
7414
|
+
await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
|
|
7415
|
+
} catch (e) {
|
|
7416
|
+
if (e instanceof Error) {
|
|
7417
|
+
console.error(`${unsubscribeMethod} error:`, e.message);
|
|
7418
|
+
}
|
|
7419
|
+
|
|
7420
|
+
if (!isCurrentConnectionStillActive()) {
|
|
7421
|
+
return;
|
|
7422
|
+
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
7423
|
+
|
|
7424
|
+
|
|
7425
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7426
|
+
state: 'subscribed'
|
|
7427
|
+
};
|
|
7428
|
+
await this._updateSubscriptions();
|
|
7429
|
+
return;
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7207
7432
|
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7433
|
+
this._subscriptionsByHash[hash] = { ...subscription,
|
|
7434
|
+
state: 'unsubscribed'
|
|
7435
|
+
};
|
|
7436
|
+
await this._updateSubscriptions();
|
|
7437
|
+
})();
|
|
7438
|
+
}
|
|
7211
7439
|
|
|
7212
|
-
|
|
7213
|
-
filter = {
|
|
7214
|
-
mentions: [sub.filter.toString()]
|
|
7215
|
-
};
|
|
7216
|
-
} else {
|
|
7217
|
-
filter = sub.filter;
|
|
7440
|
+
break;
|
|
7218
7441
|
}
|
|
7442
|
+
}));
|
|
7443
|
+
}
|
|
7444
|
+
/**
|
|
7445
|
+
* @internal
|
|
7446
|
+
*/
|
|
7447
|
+
|
|
7448
|
+
|
|
7449
|
+
_handleServerNotification(serverSubscriptionId, callbackArgs) {
|
|
7450
|
+
const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
|
|
7219
7451
|
|
|
7220
|
-
|
|
7452
|
+
if (callbacks === undefined) {
|
|
7453
|
+
return;
|
|
7221
7454
|
}
|
|
7455
|
+
|
|
7456
|
+
callbacks.forEach(cb => {
|
|
7457
|
+
try {
|
|
7458
|
+
cb( // I failed to find a way to convince TypeScript that `cb` is of type
|
|
7459
|
+
// `TCallback` which is certainly compatible with `Parameters<TCallback>`.
|
|
7460
|
+
// See https://github.com/microsoft/TypeScript/issues/47615
|
|
7461
|
+
// @ts-ignore
|
|
7462
|
+
...callbackArgs);
|
|
7463
|
+
} catch (e) {
|
|
7464
|
+
console.error(e);
|
|
7465
|
+
}
|
|
7466
|
+
});
|
|
7222
7467
|
}
|
|
7223
7468
|
/**
|
|
7224
7469
|
* @internal
|
|
@@ -7226,14 +7471,71 @@ class Connection {
|
|
|
7226
7471
|
|
|
7227
7472
|
|
|
7228
7473
|
_wsOnAccountNotification(notification) {
|
|
7229
|
-
const
|
|
7474
|
+
const {
|
|
7475
|
+
result,
|
|
7476
|
+
subscription
|
|
7477
|
+
} = create(notification, AccountNotificationResult);
|
|
7230
7478
|
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7479
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
7480
|
+
}
|
|
7481
|
+
/**
|
|
7482
|
+
* @internal
|
|
7483
|
+
*/
|
|
7484
|
+
|
|
7485
|
+
|
|
7486
|
+
_makeSubscription(subscriptionConfig,
|
|
7487
|
+
/**
|
|
7488
|
+
* When preparing `args` for a call to `_makeSubscription`, be sure
|
|
7489
|
+
* to carefully apply a default `commitment` property, if necessary.
|
|
7490
|
+
*
|
|
7491
|
+
* - If the user supplied a `commitment` use that.
|
|
7492
|
+
* - Otherwise, if the `Connection::commitment` is set, use that.
|
|
7493
|
+
* - Otherwise, set it to the RPC server default: `finalized`.
|
|
7494
|
+
*
|
|
7495
|
+
* This is extremely important to ensure that these two fundamentally
|
|
7496
|
+
* identical subscriptions produce the same identifying hash:
|
|
7497
|
+
*
|
|
7498
|
+
* - A subscription made without specifying a commitment.
|
|
7499
|
+
* - A subscription made where the commitment specified is the same
|
|
7500
|
+
* as the default applied to the subscription above.
|
|
7501
|
+
*
|
|
7502
|
+
* Example; these two subscriptions must produce the same hash:
|
|
7503
|
+
*
|
|
7504
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'`
|
|
7505
|
+
* - An `accountSubscribe` subscription for `'PUBKEY'` with commitment
|
|
7506
|
+
* `'finalized'`.
|
|
7507
|
+
*
|
|
7508
|
+
* See the 'making a subscription with defaulted params omitted' test
|
|
7509
|
+
* in `connection-subscriptions.ts` for more.
|
|
7510
|
+
*/
|
|
7511
|
+
args) {
|
|
7512
|
+
const clientSubscriptionId = this._nextClientSubscriptionId++;
|
|
7513
|
+
const hash = fastStableStringify$1([subscriptionConfig.method, args], true
|
|
7514
|
+
/* isArrayProp */
|
|
7515
|
+
);
|
|
7516
|
+
const existingSubscription = this._subscriptionsByHash[hash];
|
|
7517
|
+
|
|
7518
|
+
if (existingSubscription === undefined) {
|
|
7519
|
+
this._subscriptionsByHash[hash] = { ...subscriptionConfig,
|
|
7520
|
+
args,
|
|
7521
|
+
callbacks: new Set([subscriptionConfig.callback]),
|
|
7522
|
+
state: 'pending'
|
|
7523
|
+
};
|
|
7524
|
+
} else {
|
|
7525
|
+
existingSubscription.callbacks.add(subscriptionConfig.callback);
|
|
7236
7526
|
}
|
|
7527
|
+
|
|
7528
|
+
this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
|
|
7529
|
+
delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7530
|
+
const subscription = this._subscriptionsByHash[hash];
|
|
7531
|
+
assert(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
|
|
7532
|
+
subscription.callbacks.delete(subscriptionConfig.callback);
|
|
7533
|
+
await this._updateSubscriptions();
|
|
7534
|
+
};
|
|
7535
|
+
|
|
7536
|
+
this._updateSubscriptions();
|
|
7537
|
+
|
|
7538
|
+
return clientSubscriptionId;
|
|
7237
7539
|
}
|
|
7238
7540
|
/**
|
|
7239
7541
|
* Register a callback to be invoked whenever the specified account changes
|
|
@@ -7246,35 +7548,24 @@ class Connection {
|
|
|
7246
7548
|
|
|
7247
7549
|
|
|
7248
7550
|
onAccountChange(publicKey, callback, commitment) {
|
|
7249
|
-
const
|
|
7250
|
-
|
|
7251
|
-
publicKey: publicKey.toBase58(),
|
|
7252
|
-
callback,
|
|
7253
|
-
commitment,
|
|
7254
|
-
subscriptionId: null
|
|
7255
|
-
};
|
|
7256
|
-
|
|
7257
|
-
this._updateSubscriptions();
|
|
7551
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
7552
|
+
'base64');
|
|
7258
7553
|
|
|
7259
|
-
return
|
|
7554
|
+
return this._makeSubscription({
|
|
7555
|
+
callback,
|
|
7556
|
+
method: 'accountSubscribe',
|
|
7557
|
+
unsubscribeMethod: 'accountUnsubscribe'
|
|
7558
|
+
}, args);
|
|
7260
7559
|
}
|
|
7261
7560
|
/**
|
|
7262
7561
|
* Deregister an account notification callback
|
|
7263
7562
|
*
|
|
7264
|
-
* @param id subscription id to deregister
|
|
7563
|
+
* @param id client subscription id to deregister
|
|
7265
7564
|
*/
|
|
7266
7565
|
|
|
7267
7566
|
|
|
7268
|
-
async removeAccountChangeListener(
|
|
7269
|
-
|
|
7270
|
-
const subInfo = this._accountChangeSubscriptions[id];
|
|
7271
|
-
delete this._accountChangeSubscriptions[id];
|
|
7272
|
-
await this._unsubscribe(subInfo, 'accountUnsubscribe');
|
|
7273
|
-
|
|
7274
|
-
this._updateSubscriptions();
|
|
7275
|
-
} else {
|
|
7276
|
-
console.warn(createSubscriptionWarningMessage(id, 'account change'));
|
|
7277
|
-
}
|
|
7567
|
+
async removeAccountChangeListener(clientSubscriptionId) {
|
|
7568
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change');
|
|
7278
7569
|
}
|
|
7279
7570
|
/**
|
|
7280
7571
|
* @internal
|
|
@@ -7282,21 +7573,15 @@ class Connection {
|
|
|
7282
7573
|
|
|
7283
7574
|
|
|
7284
7575
|
_wsOnProgramAccountNotification(notification) {
|
|
7285
|
-
const
|
|
7576
|
+
const {
|
|
7577
|
+
result,
|
|
7578
|
+
subscription
|
|
7579
|
+
} = create(notification, ProgramAccountNotificationResult);
|
|
7286
7580
|
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
context
|
|
7292
|
-
} = res.result;
|
|
7293
|
-
sub.callback({
|
|
7294
|
-
accountId: value.pubkey,
|
|
7295
|
-
accountInfo: value.account
|
|
7296
|
-
}, context);
|
|
7297
|
-
return;
|
|
7298
|
-
}
|
|
7299
|
-
}
|
|
7581
|
+
this._handleServerNotification(subscription, [{
|
|
7582
|
+
accountId: result.value.pubkey,
|
|
7583
|
+
accountInfo: result.value.account
|
|
7584
|
+
}, result.context]);
|
|
7300
7585
|
}
|
|
7301
7586
|
/**
|
|
7302
7587
|
* Register a callback to be invoked whenever accounts owned by the
|
|
@@ -7311,36 +7596,30 @@ class Connection {
|
|
|
7311
7596
|
|
|
7312
7597
|
|
|
7313
7598
|
onProgramAccountChange(programId, callback, commitment, filters) {
|
|
7314
|
-
const
|
|
7315
|
-
|
|
7316
|
-
|
|
7599
|
+
const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default.
|
|
7600
|
+
'base64'
|
|
7601
|
+
/* encoding */
|
|
7602
|
+
, filters ? {
|
|
7603
|
+
filters: filters
|
|
7604
|
+
} : undefined
|
|
7605
|
+
/* extra */
|
|
7606
|
+
);
|
|
7607
|
+
|
|
7608
|
+
return this._makeSubscription({
|
|
7317
7609
|
callback,
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
};
|
|
7322
|
-
|
|
7323
|
-
this._updateSubscriptions();
|
|
7324
|
-
|
|
7325
|
-
return id;
|
|
7610
|
+
method: 'programSubscribe',
|
|
7611
|
+
unsubscribeMethod: 'programUnsubscribe'
|
|
7612
|
+
}, args);
|
|
7326
7613
|
}
|
|
7327
7614
|
/**
|
|
7328
7615
|
* Deregister an account notification callback
|
|
7329
7616
|
*
|
|
7330
|
-
* @param id subscription id to deregister
|
|
7617
|
+
* @param id client subscription id to deregister
|
|
7331
7618
|
*/
|
|
7332
7619
|
|
|
7333
7620
|
|
|
7334
|
-
async removeProgramAccountChangeListener(
|
|
7335
|
-
|
|
7336
|
-
const subInfo = this._programAccountChangeSubscriptions[id];
|
|
7337
|
-
delete this._programAccountChangeSubscriptions[id];
|
|
7338
|
-
await this._unsubscribe(subInfo, 'programUnsubscribe');
|
|
7339
|
-
|
|
7340
|
-
this._updateSubscriptions();
|
|
7341
|
-
} else {
|
|
7342
|
-
console.warn(createSubscriptionWarningMessage(id, 'program account change'));
|
|
7343
|
-
}
|
|
7621
|
+
async removeProgramAccountChangeListener(clientSubscriptionId) {
|
|
7622
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change');
|
|
7344
7623
|
}
|
|
7345
7624
|
/**
|
|
7346
7625
|
* Registers a callback to be invoked whenever logs are emitted.
|
|
@@ -7348,35 +7627,26 @@ class Connection {
|
|
|
7348
7627
|
|
|
7349
7628
|
|
|
7350
7629
|
onLogs(filter, callback, commitment) {
|
|
7351
|
-
const
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
commitment,
|
|
7356
|
-
subscriptionId: null
|
|
7357
|
-
};
|
|
7630
|
+
const args = this._buildArgs([typeof filter === 'object' ? {
|
|
7631
|
+
mentions: [filter.toString()]
|
|
7632
|
+
} : filter], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7633
|
+
);
|
|
7358
7634
|
|
|
7359
|
-
this.
|
|
7360
|
-
|
|
7361
|
-
|
|
7635
|
+
return this._makeSubscription({
|
|
7636
|
+
callback,
|
|
7637
|
+
method: 'logsSubscribe',
|
|
7638
|
+
unsubscribeMethod: 'logsUnsubscribe'
|
|
7639
|
+
}, args);
|
|
7362
7640
|
}
|
|
7363
7641
|
/**
|
|
7364
7642
|
* Deregister a logs callback.
|
|
7365
7643
|
*
|
|
7366
|
-
* @param id subscription id to deregister.
|
|
7644
|
+
* @param id client subscription id to deregister.
|
|
7367
7645
|
*/
|
|
7368
7646
|
|
|
7369
7647
|
|
|
7370
|
-
async removeOnLogsListener(
|
|
7371
|
-
|
|
7372
|
-
const subInfo = this._logsSubscriptions[id];
|
|
7373
|
-
delete this._logsSubscriptions[id];
|
|
7374
|
-
await this._unsubscribe(subInfo, 'logsUnsubscribe');
|
|
7375
|
-
|
|
7376
|
-
this._updateSubscriptions();
|
|
7377
|
-
} else {
|
|
7378
|
-
console.warn(createSubscriptionWarningMessage(id, 'logs'));
|
|
7379
|
-
}
|
|
7648
|
+
async removeOnLogsListener(clientSubscriptionId) {
|
|
7649
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs');
|
|
7380
7650
|
}
|
|
7381
7651
|
/**
|
|
7382
7652
|
* @internal
|
|
@@ -7384,17 +7654,12 @@ class Connection {
|
|
|
7384
7654
|
|
|
7385
7655
|
|
|
7386
7656
|
_wsOnLogsNotification(notification) {
|
|
7387
|
-
const
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
const sub = this._logsSubscriptions[id];
|
|
7657
|
+
const {
|
|
7658
|
+
result,
|
|
7659
|
+
subscription
|
|
7660
|
+
} = create(notification, LogsNotificationResult);
|
|
7392
7661
|
|
|
7393
|
-
|
|
7394
|
-
sub.callback(res.result.value, res.result.context);
|
|
7395
|
-
return;
|
|
7396
|
-
}
|
|
7397
|
-
}
|
|
7662
|
+
this._handleServerNotification(subscription, [result.value, result.context]);
|
|
7398
7663
|
}
|
|
7399
7664
|
/**
|
|
7400
7665
|
* @internal
|
|
@@ -7402,14 +7667,12 @@ class Connection {
|
|
|
7402
7667
|
|
|
7403
7668
|
|
|
7404
7669
|
_wsOnSlotNotification(notification) {
|
|
7405
|
-
const
|
|
7670
|
+
const {
|
|
7671
|
+
result,
|
|
7672
|
+
subscription
|
|
7673
|
+
} = create(notification, SlotNotificationResult);
|
|
7406
7674
|
|
|
7407
|
-
|
|
7408
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7409
|
-
sub.callback(res.result);
|
|
7410
|
-
return;
|
|
7411
|
-
}
|
|
7412
|
-
}
|
|
7675
|
+
this._handleServerNotification(subscription, [result]);
|
|
7413
7676
|
}
|
|
7414
7677
|
/**
|
|
7415
7678
|
* Register a callback to be invoked upon slot changes
|
|
@@ -7420,33 +7683,23 @@ class Connection {
|
|
|
7420
7683
|
|
|
7421
7684
|
|
|
7422
7685
|
onSlotChange(callback) {
|
|
7423
|
-
|
|
7424
|
-
this._slotSubscriptions[id] = {
|
|
7686
|
+
return this._makeSubscription({
|
|
7425
7687
|
callback,
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
return id;
|
|
7688
|
+
method: 'slotSubscribe',
|
|
7689
|
+
unsubscribeMethod: 'slotUnsubscribe'
|
|
7690
|
+
}, []
|
|
7691
|
+
/* args */
|
|
7692
|
+
);
|
|
7432
7693
|
}
|
|
7433
7694
|
/**
|
|
7434
7695
|
* Deregister a slot notification callback
|
|
7435
7696
|
*
|
|
7436
|
-
* @param id subscription id to deregister
|
|
7697
|
+
* @param id client subscription id to deregister
|
|
7437
7698
|
*/
|
|
7438
7699
|
|
|
7439
7700
|
|
|
7440
|
-
async removeSlotChangeListener(
|
|
7441
|
-
|
|
7442
|
-
const subInfo = this._slotSubscriptions[id];
|
|
7443
|
-
delete this._slotSubscriptions[id];
|
|
7444
|
-
await this._unsubscribe(subInfo, 'slotUnsubscribe');
|
|
7445
|
-
|
|
7446
|
-
this._updateSubscriptions();
|
|
7447
|
-
} else {
|
|
7448
|
-
console.warn(createSubscriptionWarningMessage(id, 'slot change'));
|
|
7449
|
-
}
|
|
7701
|
+
async removeSlotChangeListener(clientSubscriptionId) {
|
|
7702
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change');
|
|
7450
7703
|
}
|
|
7451
7704
|
/**
|
|
7452
7705
|
* @internal
|
|
@@ -7454,14 +7707,12 @@ class Connection {
|
|
|
7454
7707
|
|
|
7455
7708
|
|
|
7456
7709
|
_wsOnSlotUpdatesNotification(notification) {
|
|
7457
|
-
const
|
|
7710
|
+
const {
|
|
7711
|
+
result,
|
|
7712
|
+
subscription
|
|
7713
|
+
} = create(notification, SlotUpdateNotificationResult);
|
|
7458
7714
|
|
|
7459
|
-
|
|
7460
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7461
|
-
sub.callback(res.result);
|
|
7462
|
-
return;
|
|
7463
|
-
}
|
|
7464
|
-
}
|
|
7715
|
+
this._handleServerNotification(subscription, [result]);
|
|
7465
7716
|
}
|
|
7466
7717
|
/**
|
|
7467
7718
|
* Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s
|
|
@@ -7473,32 +7724,36 @@ class Connection {
|
|
|
7473
7724
|
|
|
7474
7725
|
|
|
7475
7726
|
onSlotUpdate(callback) {
|
|
7476
|
-
|
|
7477
|
-
this._slotUpdateSubscriptions[id] = {
|
|
7727
|
+
return this._makeSubscription({
|
|
7478
7728
|
callback,
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
return id;
|
|
7729
|
+
method: 'slotsUpdatesSubscribe',
|
|
7730
|
+
unsubscribeMethod: 'slotsUpdatesUnsubscribe'
|
|
7731
|
+
}, []
|
|
7732
|
+
/* args */
|
|
7733
|
+
);
|
|
7485
7734
|
}
|
|
7486
7735
|
/**
|
|
7487
7736
|
* Deregister a slot update notification callback
|
|
7488
7737
|
*
|
|
7489
|
-
* @param id subscription id to deregister
|
|
7738
|
+
* @param id client subscription id to deregister
|
|
7490
7739
|
*/
|
|
7491
7740
|
|
|
7492
7741
|
|
|
7493
|
-
async removeSlotUpdateListener(
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7742
|
+
async removeSlotUpdateListener(clientSubscriptionId) {
|
|
7743
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update');
|
|
7744
|
+
}
|
|
7745
|
+
/**
|
|
7746
|
+
* @internal
|
|
7747
|
+
*/
|
|
7498
7748
|
|
|
7499
|
-
|
|
7749
|
+
|
|
7750
|
+
async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) {
|
|
7751
|
+
const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7752
|
+
|
|
7753
|
+
if (dispose) {
|
|
7754
|
+
await dispose();
|
|
7500
7755
|
} else {
|
|
7501
|
-
console.warn(
|
|
7756
|
+
console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.');
|
|
7502
7757
|
}
|
|
7503
7758
|
}
|
|
7504
7759
|
|
|
@@ -7545,30 +7800,34 @@ class Connection {
|
|
|
7545
7800
|
|
|
7546
7801
|
|
|
7547
7802
|
_wsOnSignatureNotification(notification) {
|
|
7548
|
-
const
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7803
|
+
const {
|
|
7804
|
+
result,
|
|
7805
|
+
subscription
|
|
7806
|
+
} = create(notification, SignatureNotificationResult);
|
|
7807
|
+
|
|
7808
|
+
if (result.value !== 'receivedSignature') {
|
|
7809
|
+
/**
|
|
7810
|
+
* Special case.
|
|
7811
|
+
* After a signature is processed, RPCs automatically dispose of the
|
|
7812
|
+
* subscription on the server side. We need to track which of these
|
|
7813
|
+
* subscriptions have been disposed in such a way, so that we know
|
|
7814
|
+
* whether the client is dealing with a not-yet-processed signature
|
|
7815
|
+
* (in which case we must tear down the server subscription) or an
|
|
7816
|
+
* already-processed signature (in which case the client can simply
|
|
7817
|
+
* clear out the subscription locally without telling the server).
|
|
7818
|
+
*
|
|
7819
|
+
* NOTE: There is a proposal to eliminate this special case, here:
|
|
7820
|
+
* https://github.com/solana-labs/solana/issues/18892
|
|
7821
|
+
*/
|
|
7822
|
+
this._subscriptionsAutoDisposedByRpc.add(subscription);
|
|
7823
|
+
}
|
|
7824
|
+
|
|
7825
|
+
this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{
|
|
7826
|
+
type: 'received'
|
|
7827
|
+
}, result.context] : [{
|
|
7828
|
+
type: 'status',
|
|
7829
|
+
result: result.value
|
|
7830
|
+
}, result.context]);
|
|
7572
7831
|
}
|
|
7573
7832
|
/**
|
|
7574
7833
|
* Register a callback to be invoked upon signature updates
|
|
@@ -7581,23 +7840,26 @@ class Connection {
|
|
|
7581
7840
|
|
|
7582
7841
|
|
|
7583
7842
|
onSignature(signature, callback, commitment) {
|
|
7584
|
-
const
|
|
7585
|
-
|
|
7586
|
-
|
|
7843
|
+
const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7844
|
+
);
|
|
7845
|
+
|
|
7846
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
7587
7847
|
callback: (notification, context) => {
|
|
7588
7848
|
if (notification.type === 'status') {
|
|
7589
|
-
callback(notification.result, context);
|
|
7849
|
+
callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
7850
|
+
// so no need to explicitly send an unsubscribe message.
|
|
7851
|
+
|
|
7852
|
+
try {
|
|
7853
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
7854
|
+
} catch {// Already removed.
|
|
7855
|
+
}
|
|
7590
7856
|
}
|
|
7591
7857
|
},
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
subscriptionId: null
|
|
7596
|
-
};
|
|
7858
|
+
method: 'signatureSubscribe',
|
|
7859
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
7860
|
+
}, args);
|
|
7597
7861
|
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
return id;
|
|
7862
|
+
return clientSubscriptionId;
|
|
7601
7863
|
}
|
|
7602
7864
|
/**
|
|
7603
7865
|
* Register a callback to be invoked when a transaction is
|
|
@@ -7612,35 +7874,43 @@ class Connection {
|
|
|
7612
7874
|
|
|
7613
7875
|
|
|
7614
7876
|
onSignatureWithOptions(signature, callback, options) {
|
|
7615
|
-
const
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
options
|
|
7620
|
-
|
|
7877
|
+
const {
|
|
7878
|
+
commitment,
|
|
7879
|
+
...extra
|
|
7880
|
+
} = { ...options,
|
|
7881
|
+
commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default.
|
|
7882
|
+
|
|
7621
7883
|
};
|
|
7622
7884
|
|
|
7623
|
-
this.
|
|
7885
|
+
const args = this._buildArgs([signature], commitment, undefined
|
|
7886
|
+
/* encoding */
|
|
7887
|
+
, extra);
|
|
7624
7888
|
|
|
7625
|
-
|
|
7889
|
+
const clientSubscriptionId = this._makeSubscription({
|
|
7890
|
+
callback: (notification, context) => {
|
|
7891
|
+
callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service
|
|
7892
|
+
// so no need to explicitly send an unsubscribe message.
|
|
7893
|
+
|
|
7894
|
+
try {
|
|
7895
|
+
this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty
|
|
7896
|
+
} catch {// Already removed.
|
|
7897
|
+
}
|
|
7898
|
+
},
|
|
7899
|
+
method: 'signatureSubscribe',
|
|
7900
|
+
unsubscribeMethod: 'signatureUnsubscribe'
|
|
7901
|
+
}, args);
|
|
7902
|
+
|
|
7903
|
+
return clientSubscriptionId;
|
|
7626
7904
|
}
|
|
7627
7905
|
/**
|
|
7628
7906
|
* Deregister a signature notification callback
|
|
7629
7907
|
*
|
|
7630
|
-
* @param id subscription id to deregister
|
|
7908
|
+
* @param id client subscription id to deregister
|
|
7631
7909
|
*/
|
|
7632
7910
|
|
|
7633
7911
|
|
|
7634
|
-
async removeSignatureListener(
|
|
7635
|
-
|
|
7636
|
-
const subInfo = this._signatureSubscriptions[id];
|
|
7637
|
-
delete this._signatureSubscriptions[id];
|
|
7638
|
-
await this._unsubscribe(subInfo, 'signatureUnsubscribe');
|
|
7639
|
-
|
|
7640
|
-
this._updateSubscriptions();
|
|
7641
|
-
} else {
|
|
7642
|
-
console.warn(createSubscriptionWarningMessage(id, 'signature result'));
|
|
7643
|
-
}
|
|
7912
|
+
async removeSignatureListener(clientSubscriptionId) {
|
|
7913
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result');
|
|
7644
7914
|
}
|
|
7645
7915
|
/**
|
|
7646
7916
|
* @internal
|
|
@@ -7648,14 +7918,12 @@ class Connection {
|
|
|
7648
7918
|
|
|
7649
7919
|
|
|
7650
7920
|
_wsOnRootNotification(notification) {
|
|
7651
|
-
const
|
|
7921
|
+
const {
|
|
7922
|
+
result,
|
|
7923
|
+
subscription
|
|
7924
|
+
} = create(notification, RootNotificationResult);
|
|
7652
7925
|
|
|
7653
|
-
|
|
7654
|
-
if (sub.subscriptionId === res.subscription) {
|
|
7655
|
-
sub.callback(res.result);
|
|
7656
|
-
return;
|
|
7657
|
-
}
|
|
7658
|
-
}
|
|
7926
|
+
this._handleServerNotification(subscription, [result]);
|
|
7659
7927
|
}
|
|
7660
7928
|
/**
|
|
7661
7929
|
* Register a callback to be invoked upon root changes
|
|
@@ -7666,33 +7934,23 @@ class Connection {
|
|
|
7666
7934
|
|
|
7667
7935
|
|
|
7668
7936
|
onRootChange(callback) {
|
|
7669
|
-
|
|
7670
|
-
this._rootSubscriptions[id] = {
|
|
7937
|
+
return this._makeSubscription({
|
|
7671
7938
|
callback,
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
return id;
|
|
7939
|
+
method: 'rootSubscribe',
|
|
7940
|
+
unsubscribeMethod: 'rootUnsubscribe'
|
|
7941
|
+
}, []
|
|
7942
|
+
/* args */
|
|
7943
|
+
);
|
|
7678
7944
|
}
|
|
7679
7945
|
/**
|
|
7680
7946
|
* Deregister a root notification callback
|
|
7681
7947
|
*
|
|
7682
|
-
* @param id subscription id to deregister
|
|
7948
|
+
* @param id client subscription id to deregister
|
|
7683
7949
|
*/
|
|
7684
7950
|
|
|
7685
7951
|
|
|
7686
|
-
async removeRootChangeListener(
|
|
7687
|
-
|
|
7688
|
-
const subInfo = this._rootSubscriptions[id];
|
|
7689
|
-
delete this._rootSubscriptions[id];
|
|
7690
|
-
await this._unsubscribe(subInfo, 'rootUnsubscribe');
|
|
7691
|
-
|
|
7692
|
-
this._updateSubscriptions();
|
|
7693
|
-
} else {
|
|
7694
|
-
console.warn(createSubscriptionWarningMessage(id, 'root change'));
|
|
7695
|
-
}
|
|
7952
|
+
async removeRootChangeListener(clientSubscriptionId) {
|
|
7953
|
+
await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change');
|
|
7696
7954
|
}
|
|
7697
7955
|
|
|
7698
7956
|
}
|
|
@@ -9372,5 +9630,5 @@ function clusterApiUrl(cluster, tls) {
|
|
|
9372
9630
|
|
|
9373
9631
|
const LAMPORTS_PER_SOL = 1000000000;
|
|
9374
9632
|
|
|
9375
|
-
export { Account, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, Loader, Lockup, MAX_SEED_LENGTH, Message, NONCE_ACCOUNT_LENGTH, NonceAccount,
|
|
9633
|
+
export { Account, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, COMPUTE_BUDGET_INSTRUCTION_LAYOUTS, ComputeBudgetInstruction, ComputeBudgetProgram, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, Loader, Lockup, MAX_SEED_LENGTH, Message, NONCE_ACCOUNT_LENGTH, NonceAccount, PublicKey, SOLANA_SCHEMA, STAKE_CONFIG_ID, STAKE_INSTRUCTION_LAYOUTS, SYSTEM_INSTRUCTION_LAYOUTS, SYSVAR_CLOCK_PUBKEY, SYSVAR_EPOCH_SCHEDULE_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_REWARDS_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_SLOT_HISTORY_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, Secp256k1Program, SendTransactionError, StakeAuthorizationLayout, StakeInstruction, StakeProgram, Struct, SystemInstruction, SystemProgram, Transaction, TransactionInstruction, VALIDATOR_INFO_KEY, VOTE_PROGRAM_ID, ValidatorInfo, VoteAccount, VoteAuthorizationLayout, VoteInit, VoteInstruction, VoteProgram, clusterApiUrl, sendAndConfirmRawTransaction, sendAndConfirmTransaction };
|
|
9376
9634
|
//# sourceMappingURL=index.esm.js.map
|