@solana/web3.js 1.39.0 → 1.39.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 +103 -19
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +103 -19
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +103 -19
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.esm.js +103 -19
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +103 -19
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +3 -3
- package/lib/index.iife.min.js.map +1 -1
- package/package.json +22 -22
- package/src/connection.ts +2 -0
- package/src/message.ts +9 -12
- package/src/transaction.ts +87 -2
- package/src/util/guarded-array-utils.ts +37 -0
- package/src/validator-info.ts +5 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/web3.js",
|
|
3
|
-
"version": "1.39.
|
|
3
|
+
"version": "1.39.2",
|
|
4
4
|
"description": "Solana Javascript API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -35,26 +35,6 @@
|
|
|
35
35
|
"/lib",
|
|
36
36
|
"/src"
|
|
37
37
|
],
|
|
38
|
-
"scripts": {
|
|
39
|
-
"build": "npm run clean; cross-env NODE_ENV=production rollup -c; npm run type:gen",
|
|
40
|
-
"build:fixtures": "set -ex; ./test/fixtures/noop-program/build.sh",
|
|
41
|
-
"clean": "rimraf ./coverage ./lib",
|
|
42
|
-
"codecov": "set -ex; npm run test:cover; cat ./coverage/lcov.info | codecov",
|
|
43
|
-
"dev": "cross-env NODE_ENV=development rollup -c",
|
|
44
|
-
"doc": "set -ex; typedoc --treatWarningsAsErrors",
|
|
45
|
-
"type:gen": "./scripts/typegen.sh",
|
|
46
|
-
"lint": "set -ex; npm run pretty; eslint . --ext .js,.ts",
|
|
47
|
-
"lint:fix": "npm run pretty:fix && eslint . --fix --ext .js,.ts",
|
|
48
|
-
"type:check": "tsc -p tsconfig.json --noEmit",
|
|
49
|
-
"ok": "run-s lint test doc type:check",
|
|
50
|
-
"pretty": "prettier --check '{,{src,test}/**/}*.{j,t}s'",
|
|
51
|
-
"pretty:fix": "prettier --write '{,{src,test}/**/}*.{j,t}s'",
|
|
52
|
-
"re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git",
|
|
53
|
-
"test": "mocha -r ts-node/register './test/**/*.test.ts'",
|
|
54
|
-
"test:cover": "TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' nyc --reporter=lcov mocha -r ts-node/register './test/**/*.test.ts'",
|
|
55
|
-
"test:live": "TEST_LIVE=1 npm run test",
|
|
56
|
-
"test:live-with-test-validator": "start-server-and-test 'solana-test-validator --reset --quiet' http://localhost:8899/health test:live"
|
|
57
|
-
},
|
|
58
38
|
"dependencies": {
|
|
59
39
|
"@babel/runtime": "^7.12.5",
|
|
60
40
|
"@ethersproject/sha2": "^5.5.0",
|
|
@@ -133,5 +113,25 @@
|
|
|
133
113
|
},
|
|
134
114
|
"engines": {
|
|
135
115
|
"node": ">=12.20.0"
|
|
116
|
+
},
|
|
117
|
+
"scripts": {
|
|
118
|
+
"build": "npm run clean; cross-env NODE_ENV=production rollup -c; npm run type:gen",
|
|
119
|
+
"build:fixtures": "set -ex; ./test/fixtures/noop-program/build.sh",
|
|
120
|
+
"clean": "rimraf ./coverage ./lib",
|
|
121
|
+
"codecov": "set -ex; npm run test:cover; cat ./coverage/lcov.info | codecov",
|
|
122
|
+
"dev": "cross-env NODE_ENV=development rollup -c",
|
|
123
|
+
"doc": "set -ex; typedoc --treatWarningsAsErrors",
|
|
124
|
+
"type:gen": "./scripts/typegen.sh",
|
|
125
|
+
"lint": "set -ex; npm run pretty; eslint . --ext .js,.ts",
|
|
126
|
+
"lint:fix": "npm run pretty:fix && eslint . --fix --ext .js,.ts",
|
|
127
|
+
"type:check": "tsc -p tsconfig.json --noEmit",
|
|
128
|
+
"ok": "run-s lint test doc type:check",
|
|
129
|
+
"pretty": "prettier --check '{,{src,test}/**/}*.{j,t}s'",
|
|
130
|
+
"pretty:fix": "prettier --write '{,{src,test}/**/}*.{j,t}s'",
|
|
131
|
+
"re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git",
|
|
132
|
+
"test": "mocha -r ts-node/register './test/**/*.test.ts'",
|
|
133
|
+
"test:cover": "TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' nyc --reporter=lcov mocha -r ts-node/register './test/**/*.test.ts'",
|
|
134
|
+
"test:live": "TEST_LIVE=1 npm run test",
|
|
135
|
+
"test:live-with-test-validator": "start-server-and-test 'solana-test-validator --reset --quiet' http://localhost:8899/health test:live"
|
|
136
136
|
}
|
|
137
|
-
}
|
|
137
|
+
}
|
package/src/connection.ts
CHANGED
|
@@ -3895,6 +3895,8 @@ export class Connection {
|
|
|
3895
3895
|
transaction.instructions = transactionOrMessage.instructions;
|
|
3896
3896
|
} else {
|
|
3897
3897
|
transaction = Transaction.populate(transactionOrMessage);
|
|
3898
|
+
// HACK: this function relies on mutating the populated transaction
|
|
3899
|
+
transaction._message = transaction._json = undefined;
|
|
3898
3900
|
}
|
|
3899
3901
|
|
|
3900
3902
|
if (transaction.nonceInfo && signers) {
|
package/src/message.ts
CHANGED
|
@@ -8,6 +8,7 @@ import * as Layout from './layout';
|
|
|
8
8
|
import {PACKET_DATA_SIZE} from './transaction';
|
|
9
9
|
import * as shortvec from './util/shortvec-encoding';
|
|
10
10
|
import {toBuffer} from './util/to-buffer';
|
|
11
|
+
import {guardedShift, guardedSplice} from './util/guarded-array-utils';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* The message header, identifying signed and read-only account
|
|
@@ -222,32 +223,28 @@ export class Message {
|
|
|
222
223
|
// Slice up wire data
|
|
223
224
|
let byteArray = [...buffer];
|
|
224
225
|
|
|
225
|
-
const numRequiredSignatures = byteArray
|
|
226
|
-
const numReadonlySignedAccounts = byteArray
|
|
227
|
-
const numReadonlyUnsignedAccounts = byteArray
|
|
226
|
+
const numRequiredSignatures = guardedShift(byteArray);
|
|
227
|
+
const numReadonlySignedAccounts = guardedShift(byteArray);
|
|
228
|
+
const numReadonlyUnsignedAccounts = guardedShift(byteArray);
|
|
228
229
|
|
|
229
230
|
const accountCount = shortvec.decodeLength(byteArray);
|
|
230
231
|
let accountKeys = [];
|
|
231
232
|
for (let i = 0; i < accountCount; i++) {
|
|
232
|
-
const account = byteArray
|
|
233
|
-
byteArray = byteArray.slice(PUBKEY_LENGTH);
|
|
233
|
+
const account = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
|
|
234
234
|
accountKeys.push(bs58.encode(Buffer.from(account)));
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
const recentBlockhash = byteArray
|
|
238
|
-
byteArray = byteArray.slice(PUBKEY_LENGTH);
|
|
237
|
+
const recentBlockhash = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
|
|
239
238
|
|
|
240
239
|
const instructionCount = shortvec.decodeLength(byteArray);
|
|
241
240
|
let instructions: CompiledInstruction[] = [];
|
|
242
241
|
for (let i = 0; i < instructionCount; i++) {
|
|
243
|
-
const programIdIndex = byteArray
|
|
242
|
+
const programIdIndex = guardedShift(byteArray);
|
|
244
243
|
const accountCount = shortvec.decodeLength(byteArray);
|
|
245
|
-
const accounts = byteArray
|
|
246
|
-
byteArray = byteArray.slice(accountCount);
|
|
244
|
+
const accounts = guardedSplice(byteArray, 0, accountCount);
|
|
247
245
|
const dataLength = shortvec.decodeLength(byteArray);
|
|
248
|
-
const dataSlice = byteArray
|
|
246
|
+
const dataSlice = guardedSplice(byteArray, 0, dataLength);
|
|
249
247
|
const data = bs58.encode(Buffer.from(dataSlice));
|
|
250
|
-
byteArray = byteArray.slice(dataLength);
|
|
251
248
|
instructions.push({
|
|
252
249
|
programIdIndex,
|
|
253
250
|
accounts,
|
package/src/transaction.ts
CHANGED
|
@@ -11,6 +11,7 @@ import invariant from './util/assert';
|
|
|
11
11
|
import type {Signer} from './keypair';
|
|
12
12
|
import type {Blockhash} from './blockhash';
|
|
13
13
|
import type {CompiledInstruction} from './message';
|
|
14
|
+
import {guardedSplice} from './util/guarded-array-utils';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Transaction signature as base-58 encoded string
|
|
@@ -66,6 +67,19 @@ export type SerializeConfig = {
|
|
|
66
67
|
verifySignatures?: boolean;
|
|
67
68
|
};
|
|
68
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export interface TransactionInstructionJSON {
|
|
74
|
+
keys: {
|
|
75
|
+
pubkey: string;
|
|
76
|
+
isSigner: boolean;
|
|
77
|
+
isWritable: boolean;
|
|
78
|
+
}[];
|
|
79
|
+
programId: string;
|
|
80
|
+
data: number[];
|
|
81
|
+
}
|
|
82
|
+
|
|
69
83
|
/**
|
|
70
84
|
* Transaction Instruction class
|
|
71
85
|
*/
|
|
@@ -93,6 +107,21 @@ export class TransactionInstruction {
|
|
|
93
107
|
this.data = opts.data;
|
|
94
108
|
}
|
|
95
109
|
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
toJSON(): TransactionInstructionJSON {
|
|
115
|
+
return {
|
|
116
|
+
keys: this.keys.map(({pubkey, isSigner, isWritable}) => ({
|
|
117
|
+
pubkey: pubkey.toJSON(),
|
|
118
|
+
isSigner,
|
|
119
|
+
isWritable,
|
|
120
|
+
})),
|
|
121
|
+
programId: this.programId.toJSON(),
|
|
122
|
+
data: [...this.data],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
96
125
|
}
|
|
97
126
|
|
|
98
127
|
/**
|
|
@@ -128,6 +157,20 @@ export type NonceInformation = {
|
|
|
128
157
|
nonceInstruction: TransactionInstruction;
|
|
129
158
|
};
|
|
130
159
|
|
|
160
|
+
/**
|
|
161
|
+
* @internal
|
|
162
|
+
*/
|
|
163
|
+
export interface TransactionJSON {
|
|
164
|
+
recentBlockhash: string | null;
|
|
165
|
+
feePayer: string | null;
|
|
166
|
+
nonceInfo: {
|
|
167
|
+
nonce: string;
|
|
168
|
+
nonceInstruction: TransactionInstructionJSON;
|
|
169
|
+
} | null;
|
|
170
|
+
instructions: TransactionInstructionJSON[];
|
|
171
|
+
signatures: {publicKey: string; signature: number[] | null}[];
|
|
172
|
+
}
|
|
173
|
+
|
|
131
174
|
/**
|
|
132
175
|
* Transaction class
|
|
133
176
|
*/
|
|
@@ -169,6 +212,16 @@ export class Transaction {
|
|
|
169
212
|
*/
|
|
170
213
|
nonceInfo?: NonceInformation;
|
|
171
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @internal
|
|
217
|
+
*/
|
|
218
|
+
_message?: Message;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* @internal
|
|
222
|
+
*/
|
|
223
|
+
_json?: TransactionJSON;
|
|
224
|
+
|
|
172
225
|
/**
|
|
173
226
|
* Construct an empty Transaction
|
|
174
227
|
*/
|
|
@@ -176,6 +229,27 @@ export class Transaction {
|
|
|
176
229
|
opts && Object.assign(this, opts);
|
|
177
230
|
}
|
|
178
231
|
|
|
232
|
+
/**
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
235
|
+
toJSON(): TransactionJSON {
|
|
236
|
+
return {
|
|
237
|
+
recentBlockhash: this.recentBlockhash || null,
|
|
238
|
+
feePayer: this.feePayer ? this.feePayer.toJSON() : null,
|
|
239
|
+
nonceInfo: this.nonceInfo
|
|
240
|
+
? {
|
|
241
|
+
nonce: this.nonceInfo.nonce,
|
|
242
|
+
nonceInstruction: this.nonceInfo.nonceInstruction.toJSON(),
|
|
243
|
+
}
|
|
244
|
+
: null,
|
|
245
|
+
instructions: this.instructions.map(instruction => instruction.toJSON()),
|
|
246
|
+
signatures: this.signatures.map(({publicKey, signature}) => ({
|
|
247
|
+
publicKey: publicKey.toJSON(),
|
|
248
|
+
signature: signature ? [...signature] : null,
|
|
249
|
+
})),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
179
253
|
/**
|
|
180
254
|
* Add one or more instructions to this Transaction
|
|
181
255
|
*/
|
|
@@ -204,6 +278,15 @@ export class Transaction {
|
|
|
204
278
|
* Compile transaction data
|
|
205
279
|
*/
|
|
206
280
|
compileMessage(): Message {
|
|
281
|
+
if (this._message) {
|
|
282
|
+
if (JSON.stringify(this.toJSON()) !== JSON.stringify(this._json)) {
|
|
283
|
+
throw new Error(
|
|
284
|
+
'Transaction mutated after being populated from Message',
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
return this._message;
|
|
288
|
+
}
|
|
289
|
+
|
|
207
290
|
const {nonceInfo} = this;
|
|
208
291
|
if (nonceInfo && this.instructions[0] != nonceInfo.nonceInstruction) {
|
|
209
292
|
this.recentBlockhash = nonceInfo.nonce;
|
|
@@ -666,8 +749,7 @@ export class Transaction {
|
|
|
666
749
|
const signatureCount = shortvec.decodeLength(byteArray);
|
|
667
750
|
let signatures = [];
|
|
668
751
|
for (let i = 0; i < signatureCount; i++) {
|
|
669
|
-
const signature = byteArray
|
|
670
|
-
byteArray = byteArray.slice(SIGNATURE_LENGTH);
|
|
752
|
+
const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH);
|
|
671
753
|
signatures.push(bs58.encode(Buffer.from(signature)));
|
|
672
754
|
}
|
|
673
755
|
|
|
@@ -719,6 +801,9 @@ export class Transaction {
|
|
|
719
801
|
);
|
|
720
802
|
});
|
|
721
803
|
|
|
804
|
+
transaction._message = message;
|
|
805
|
+
transaction._json = transaction.toJSON();
|
|
806
|
+
|
|
722
807
|
return transaction;
|
|
723
808
|
}
|
|
724
809
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Delegates to `Array#shift`, but throws if the array is zero-length.
|
|
5
|
+
*/
|
|
6
|
+
export function guardedShift<T>(byteArray: T[]): T {
|
|
7
|
+
if (byteArray.length === 0) {
|
|
8
|
+
throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
|
|
9
|
+
}
|
|
10
|
+
return byteArray.shift() as T;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of
|
|
15
|
+
* the array.
|
|
16
|
+
*/
|
|
17
|
+
export function guardedSplice<T>(
|
|
18
|
+
byteArray: T[],
|
|
19
|
+
...args:
|
|
20
|
+
| [start: number, deleteCount?: number]
|
|
21
|
+
| [start: number, deleteCount: number, ...items: T[]]
|
|
22
|
+
): T[] {
|
|
23
|
+
var _args$;
|
|
24
|
+
const [start] = args;
|
|
25
|
+
if (
|
|
26
|
+
args.length === 2 // Implies that `deleteCount` was supplied
|
|
27
|
+
? start +
|
|
28
|
+
((_args$ = args[1]) !== null && _args$ !== void 0 ? _args$ : 0) >
|
|
29
|
+
byteArray.length
|
|
30
|
+
: start >= byteArray.length
|
|
31
|
+
) {
|
|
32
|
+
throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
|
|
33
|
+
}
|
|
34
|
+
return byteArray.splice(
|
|
35
|
+
...(args as Parameters<typeof Array.prototype.splice>),
|
|
36
|
+
);
|
|
37
|
+
}
|
package/src/validator-info.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import * as Layout from './layout';
|
|
10
10
|
import * as shortvec from './util/shortvec-encoding';
|
|
11
11
|
import {PublicKey} from './publickey';
|
|
12
|
+
import {guardedShift, guardedSplice} from './util/guarded-array-utils';
|
|
12
13
|
|
|
13
14
|
export const VALIDATOR_INFO_KEY = new PublicKey(
|
|
14
15
|
'Va1idator1nfo111111111111111111111111111111',
|
|
@@ -85,10 +86,10 @@ export class ValidatorInfo {
|
|
|
85
86
|
|
|
86
87
|
const configKeys: Array<ConfigKey> = [];
|
|
87
88
|
for (let i = 0; i < 2; i++) {
|
|
88
|
-
const publicKey = new PublicKey(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
const publicKey = new PublicKey(
|
|
90
|
+
guardedSplice(byteArray, 0, PUBKEY_LENGTH),
|
|
91
|
+
);
|
|
92
|
+
const isSigner = guardedShift(byteArray) === 1;
|
|
92
93
|
configKeys.push({publicKey, isSigner});
|
|
93
94
|
}
|
|
94
95
|
|