@solana/web3.js 1.39.0 → 1.40.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/web3.js",
3
- "version": "1.39.0",
3
+ "version": "1.40.1",
4
4
  "description": "Solana Javascript API",
5
5
  "keywords": [
6
6
  "api",
@@ -79,7 +79,7 @@
79
79
  "@babel/preset-typescript": "^7.12.16",
80
80
  "@babel/register": "^7.12.13",
81
81
  "@commitlint/config-conventional": "^15.0.0",
82
- "@commitlint/travis-cli": "^15.0.0",
82
+ "@commitlint/travis-cli": "^16.2.3",
83
83
  "@rollup/plugin-alias": "^3.1.2",
84
84
  "@rollup/plugin-babel": "^5.2.3",
85
85
  "@rollup/plugin-commonjs": "^21.0.0",
@@ -95,7 +95,7 @@
95
95
  "@types/express-serve-static-core": "^4.17.21",
96
96
  "@types/mocha": "^9.0.0",
97
97
  "@types/mz": "^2.7.3",
98
- "@types/node": "^16.0.0",
98
+ "@types/node": "^17.0.24",
99
99
  "@types/secp256k1": "^4.0.1",
100
100
  "@types/sinon": "^10.0.0",
101
101
  "@typescript-eslint/eslint-plugin": "^4.14.2",
package/src/connection.ts CHANGED
@@ -2120,6 +2120,13 @@ export type ConnectionConfig = {
2120
2120
  confirmTransactionInitialTimeout?: number;
2121
2121
  };
2122
2122
 
2123
+ function createSubscriptionWarningMessage(id: number, label: string): string {
2124
+ return (
2125
+ 'Ignored unsubscribe request because an active subscription ' +
2126
+ `with id \`${id}\` for '${label}' events could not be found.`
2127
+ );
2128
+ }
2129
+
2123
2130
  /**
2124
2131
  * A connection to a fullnode JSON RPC endpoint
2125
2132
  */
@@ -3404,6 +3411,34 @@ export class Connection {
3404
3411
  return res;
3405
3412
  }
3406
3413
 
3414
+ /**
3415
+ * Fetch transaction details for a batch of confirmed transactions.
3416
+ * Similar to {@link getParsedTransactions} but returns a {@link TransactionResponse}.
3417
+ */
3418
+ async getTransactions(
3419
+ signatures: TransactionSignature[],
3420
+ commitment?: Finality,
3421
+ ): Promise<(TransactionResponse | null)[]> {
3422
+ const batch = signatures.map(signature => {
3423
+ const args = this._buildArgsAtLeastConfirmed([signature], commitment);
3424
+ return {
3425
+ methodName: 'getTransaction',
3426
+ args,
3427
+ };
3428
+ });
3429
+
3430
+ const unsafeRes = await this._rpcBatchRequest(batch);
3431
+ const res = unsafeRes.map((unsafeRes: any) => {
3432
+ const res = create(unsafeRes, GetTransactionRpcResult);
3433
+ if ('error' in res) {
3434
+ throw new Error('failed to get transactions: ' + res.error.message);
3435
+ }
3436
+ return res.result;
3437
+ });
3438
+
3439
+ return res;
3440
+ }
3441
+
3407
3442
  /**
3408
3443
  * Fetch a list of Transactions and transaction statuses from the cluster
3409
3444
  * for a confirmed block.
@@ -3895,6 +3930,8 @@ export class Connection {
3895
3930
  transaction.instructions = transactionOrMessage.instructions;
3896
3931
  } else {
3897
3932
  transaction = Transaction.populate(transactionOrMessage);
3933
+ // HACK: this function relies on mutating the populated transaction
3934
+ transaction._message = transaction._json = undefined;
3898
3935
  }
3899
3936
 
3900
3937
  if (transaction.nonceInfo && signers) {
@@ -4351,7 +4388,7 @@ export class Connection {
4351
4388
  await this._unsubscribe(subInfo, 'accountUnsubscribe');
4352
4389
  this._updateSubscriptions();
4353
4390
  } else {
4354
- throw new Error(`Unknown account change id: ${id}`);
4391
+ console.warn(createSubscriptionWarningMessage(id, 'account change'));
4355
4392
  }
4356
4393
  }
4357
4394
 
@@ -4415,7 +4452,9 @@ export class Connection {
4415
4452
  await this._unsubscribe(subInfo, 'programUnsubscribe');
4416
4453
  this._updateSubscriptions();
4417
4454
  } else {
4418
- throw new Error(`Unknown program account change id: ${id}`);
4455
+ console.warn(
4456
+ createSubscriptionWarningMessage(id, 'program account change'),
4457
+ );
4419
4458
  }
4420
4459
  }
4421
4460
 
@@ -4444,13 +4483,14 @@ export class Connection {
4444
4483
  * @param id subscription id to deregister.
4445
4484
  */
4446
4485
  async removeOnLogsListener(id: number): Promise<void> {
4447
- if (!this._logsSubscriptions[id]) {
4448
- throw new Error(`Unknown logs id: ${id}`);
4486
+ if (this._logsSubscriptions[id]) {
4487
+ const subInfo = this._logsSubscriptions[id];
4488
+ delete this._logsSubscriptions[id];
4489
+ await this._unsubscribe(subInfo, 'logsUnsubscribe');
4490
+ this._updateSubscriptions();
4491
+ } else {
4492
+ console.warn(createSubscriptionWarningMessage(id, 'logs'));
4449
4493
  }
4450
- const subInfo = this._logsSubscriptions[id];
4451
- delete this._logsSubscriptions[id];
4452
- await this._unsubscribe(subInfo, 'logsUnsubscribe');
4453
- this._updateSubscriptions();
4454
4494
  }
4455
4495
 
4456
4496
  /**
@@ -4509,7 +4549,7 @@ export class Connection {
4509
4549
  await this._unsubscribe(subInfo, 'slotUnsubscribe');
4510
4550
  this._updateSubscriptions();
4511
4551
  } else {
4512
- throw new Error(`Unknown slot change id: ${id}`);
4552
+ console.warn(createSubscriptionWarningMessage(id, 'slot change'));
4513
4553
  }
4514
4554
  }
4515
4555
 
@@ -4555,7 +4595,7 @@ export class Connection {
4555
4595
  await this._unsubscribe(subInfo, 'slotsUpdatesUnsubscribe');
4556
4596
  this._updateSubscriptions();
4557
4597
  } else {
4558
- throw new Error(`Unknown slot update id: ${id}`);
4598
+ console.warn(createSubscriptionWarningMessage(id, 'slot update'));
4559
4599
  }
4560
4600
  }
4561
4601
 
@@ -4700,7 +4740,7 @@ export class Connection {
4700
4740
  await this._unsubscribe(subInfo, 'signatureUnsubscribe');
4701
4741
  this._updateSubscriptions();
4702
4742
  } else {
4703
- throw new Error(`Unknown signature result id: ${id}`);
4743
+ console.warn(createSubscriptionWarningMessage(id, 'signature result'));
4704
4744
  }
4705
4745
  }
4706
4746
 
@@ -4745,7 +4785,7 @@ export class Connection {
4745
4785
  await this._unsubscribe(subInfo, 'rootUnsubscribe');
4746
4786
  this._updateSubscriptions();
4747
4787
  } else {
4748
- throw new Error(`Unknown root change id: ${id}`);
4788
+ console.warn(createSubscriptionWarningMessage(id, 'root change'));
4749
4789
  }
4750
4790
  }
4751
4791
  }
package/src/publickey.ts CHANGED
@@ -143,10 +143,10 @@ export class PublicKey extends Struct {
143
143
  * Derive a program address from seeds and a program ID.
144
144
  */
145
145
  /* eslint-disable require-await */
146
- static async createProgramAddress(
146
+ static createProgramAddressSync(
147
147
  seeds: Array<Buffer | Uint8Array>,
148
148
  programId: PublicKey,
149
- ): Promise<PublicKey> {
149
+ ): PublicKey {
150
150
  let buffer = Buffer.alloc(0);
151
151
  seeds.forEach(function (seed) {
152
152
  if (seed.length > MAX_SEED_LENGTH) {
@@ -167,6 +167,18 @@ export class PublicKey extends Struct {
167
167
  return new PublicKey(publicKeyBytes);
168
168
  }
169
169
 
170
+ /**
171
+ * Async version of createProgramAddressSync
172
+ * For backwards compatibility
173
+ */
174
+ /* eslint-disable require-await */
175
+ static async createProgramAddress(
176
+ seeds: Array<Buffer | Uint8Array>,
177
+ programId: PublicKey,
178
+ ): Promise<PublicKey> {
179
+ return this.createProgramAddressSync(seeds, programId);
180
+ }
181
+
170
182
  /**
171
183
  * Find a valid program address
172
184
  *
@@ -174,16 +186,16 @@ export class PublicKey extends Struct {
174
186
  * iterates a nonce until it finds one that when combined with the seeds
175
187
  * results in a valid program address.
176
188
  */
177
- static async findProgramAddress(
189
+ static findProgramAddressSync(
178
190
  seeds: Array<Buffer | Uint8Array>,
179
191
  programId: PublicKey,
180
- ): Promise<[PublicKey, number]> {
192
+ ): [PublicKey, number] {
181
193
  let nonce = 255;
182
194
  let address;
183
195
  while (nonce != 0) {
184
196
  try {
185
197
  const seedsWithNonce = seeds.concat(Buffer.from([nonce]));
186
- address = await this.createProgramAddress(seedsWithNonce, programId);
198
+ address = this.createProgramAddressSync(seedsWithNonce, programId);
187
199
  } catch (err) {
188
200
  if (err instanceof TypeError) {
189
201
  throw err;
@@ -196,11 +208,23 @@ export class PublicKey extends Struct {
196
208
  throw new Error(`Unable to find a viable program address nonce`);
197
209
  }
198
210
 
211
+ /**
212
+ * Async version of findProgramAddressSync
213
+ * For backwards compatibility
214
+ */
215
+ static async findProgramAddress(
216
+ seeds: Array<Buffer | Uint8Array>,
217
+ programId: PublicKey,
218
+ ): Promise<[PublicKey, number]> {
219
+ return this.findProgramAddressSync(seeds, programId);
220
+ }
221
+
199
222
  /**
200
223
  * Check that a pubkey is on the ed25519 curve.
201
224
  */
202
- static isOnCurve(pubkey: Uint8Array): boolean {
203
- return is_on_curve(pubkey) == 1;
225
+ static isOnCurve(pubkeyData: PublicKeyInitData): boolean {
226
+ const pubkey = new PublicKey(pubkeyData);
227
+ return is_on_curve(pubkey.toBytes()) == 1;
204
228
  }
205
229
  }
206
230
 
@@ -601,8 +601,8 @@ export class StakeProgram {
601
601
  * Max space of a Stake account
602
602
  *
603
603
  * This is generated from the solana-stake-program StakeState struct as
604
- * `std::mem::size_of::<StakeState>()`:
605
- * https://docs.rs/solana-stake-program/1.4.4/solana_stake_program/stake_state/enum.StakeState.html
604
+ * `StakeState::size_of()`:
605
+ * https://docs.rs/solana-stake-program/latest/solana_stake_program/stake_state/enum.StakeState.html
606
606
  */
607
607
  static space: number = 200;
608
608
 
@@ -66,6 +66,19 @@ export type SerializeConfig = {
66
66
  verifySignatures?: boolean;
67
67
  };
68
68
 
69
+ /**
70
+ * @internal
71
+ */
72
+ export interface TransactionInstructionJSON {
73
+ keys: {
74
+ pubkey: string;
75
+ isSigner: boolean;
76
+ isWritable: boolean;
77
+ }[];
78
+ programId: string;
79
+ data: number[];
80
+ }
81
+
69
82
  /**
70
83
  * Transaction Instruction class
71
84
  */
@@ -93,6 +106,21 @@ export class TransactionInstruction {
93
106
  this.data = opts.data;
94
107
  }
95
108
  }
109
+
110
+ /**
111
+ * @internal
112
+ */
113
+ toJSON(): TransactionInstructionJSON {
114
+ return {
115
+ keys: this.keys.map(({pubkey, isSigner, isWritable}) => ({
116
+ pubkey: pubkey.toJSON(),
117
+ isSigner,
118
+ isWritable,
119
+ })),
120
+ programId: this.programId.toJSON(),
121
+ data: [...this.data],
122
+ };
123
+ }
96
124
  }
97
125
 
98
126
  /**
@@ -128,6 +156,20 @@ export type NonceInformation = {
128
156
  nonceInstruction: TransactionInstruction;
129
157
  };
130
158
 
159
+ /**
160
+ * @internal
161
+ */
162
+ export interface TransactionJSON {
163
+ recentBlockhash: string | null;
164
+ feePayer: string | null;
165
+ nonceInfo: {
166
+ nonce: string;
167
+ nonceInstruction: TransactionInstructionJSON;
168
+ } | null;
169
+ instructions: TransactionInstructionJSON[];
170
+ signers: string[];
171
+ }
172
+
131
173
  /**
132
174
  * Transaction class
133
175
  */
@@ -169,6 +211,16 @@ export class Transaction {
169
211
  */
170
212
  nonceInfo?: NonceInformation;
171
213
 
214
+ /**
215
+ * @internal
216
+ */
217
+ _message?: Message;
218
+
219
+ /**
220
+ * @internal
221
+ */
222
+ _json?: TransactionJSON;
223
+
172
224
  /**
173
225
  * Construct an empty Transaction
174
226
  */
@@ -176,6 +228,26 @@ export class Transaction {
176
228
  opts && Object.assign(this, opts);
177
229
  }
178
230
 
231
+ /**
232
+ * @internal
233
+ */
234
+ toJSON(): TransactionJSON {
235
+ return {
236
+ recentBlockhash: this.recentBlockhash || null,
237
+ feePayer: this.feePayer ? this.feePayer.toJSON() : null,
238
+ nonceInfo: this.nonceInfo
239
+ ? {
240
+ nonce: this.nonceInfo.nonce,
241
+ nonceInstruction: this.nonceInfo.nonceInstruction.toJSON(),
242
+ }
243
+ : null,
244
+ instructions: this.instructions.map(instruction => instruction.toJSON()),
245
+ signers: this.signatures.map(({publicKey}) => {
246
+ return publicKey.toJSON();
247
+ }),
248
+ };
249
+ }
250
+
179
251
  /**
180
252
  * Add one or more instructions to this Transaction
181
253
  */
@@ -204,6 +276,15 @@ export class Transaction {
204
276
  * Compile transaction data
205
277
  */
206
278
  compileMessage(): Message {
279
+ if (this._message) {
280
+ if (JSON.stringify(this.toJSON()) !== JSON.stringify(this._json)) {
281
+ throw new Error(
282
+ 'Transaction message mutated after being populated from Message',
283
+ );
284
+ }
285
+ return this._message;
286
+ }
287
+
207
288
  const {nonceInfo} = this;
208
289
  if (nonceInfo && this.instructions[0] != nonceInfo.nonceInstruction) {
209
290
  this.recentBlockhash = nonceInfo.nonce;
@@ -719,6 +800,9 @@ export class Transaction {
719
800
  );
720
801
  });
721
802
 
803
+ transaction._message = message;
804
+ transaction._json = transaction.toJSON();
805
+
722
806
  return transaction;
723
807
  }
724
808
  }