@solana/web3.js 1.52.0 → 1.54.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.
Files changed (62) hide show
  1. package/lib/index.browser.cjs.js +6188 -7481
  2. package/lib/index.browser.cjs.js.map +1 -1
  3. package/lib/index.browser.esm.js +6183 -7482
  4. package/lib/index.browser.esm.js.map +1 -1
  5. package/lib/index.cjs.js +6219 -7531
  6. package/lib/index.cjs.js.map +1 -1
  7. package/lib/index.d.ts +957 -832
  8. package/lib/index.esm.js +6214 -7532
  9. package/lib/index.esm.js.map +1 -1
  10. package/lib/index.iife.js +20976 -27402
  11. package/lib/index.iife.js.map +1 -1
  12. package/lib/index.iife.min.js +8 -5
  13. package/lib/index.iife.min.js.map +1 -1
  14. package/lib/index.native.js +6188 -7480
  15. package/lib/index.native.js.map +1 -1
  16. package/package.json +5 -7
  17. package/src/account-data.ts +39 -0
  18. package/src/account.ts +19 -10
  19. package/src/connection.ts +40 -14
  20. package/src/index.ts +3 -14
  21. package/src/keypair.ts +19 -24
  22. package/src/layout.ts +7 -0
  23. package/src/loader.ts +4 -5
  24. package/src/message/index.ts +45 -0
  25. package/src/{message.ts → message/legacy.ts} +46 -27
  26. package/src/message/v0.ts +324 -0
  27. package/src/message/versioned.ts +27 -0
  28. package/src/nonce-account.ts +1 -1
  29. package/src/{address-lookup-table-program.ts → programs/address-lookup-table/index.ts} +8 -6
  30. package/src/programs/address-lookup-table/state.ts +84 -0
  31. package/src/{compute-budget.ts → programs/compute-budget.ts} +4 -4
  32. package/src/{ed25519-program.ts → programs/ed25519.ts} +6 -6
  33. package/src/programs/index.ts +7 -0
  34. package/src/{secp256k1-program.ts → programs/secp256k1.ts} +10 -9
  35. package/src/{stake-program.ts → programs/stake.ts} +7 -7
  36. package/src/{system-program.ts → programs/system.ts} +8 -8
  37. package/src/{vote-program.ts → programs/vote.ts} +28 -7
  38. package/src/publickey.ts +16 -75
  39. package/src/{transaction-constants.ts → transaction/constants.ts} +2 -0
  40. package/src/{util/tx-expiry-custom-errors.ts → transaction/expiry-custom-errors.ts} +0 -0
  41. package/src/transaction/index.ts +4 -0
  42. package/src/{transaction.ts → transaction/legacy.ts} +13 -18
  43. package/src/transaction/versioned.ts +105 -0
  44. package/src/{util → utils}/assert.ts +0 -0
  45. package/src/{util → utils}/bigint.ts +0 -0
  46. package/src/{util → utils}/borsh-schema.ts +0 -0
  47. package/src/{util → utils}/cluster.ts +0 -0
  48. package/src/utils/ed25519.ts +46 -0
  49. package/src/utils/index.ts +5 -0
  50. package/src/utils/makeWebsocketUrl.ts +26 -0
  51. package/src/{util → utils}/promise-timeout.ts +0 -0
  52. package/src/utils/secp256k1.ts +18 -0
  53. package/src/{util → utils}/send-and-confirm-raw-transaction.ts +0 -0
  54. package/src/{util → utils}/send-and-confirm-transaction.ts +0 -0
  55. package/src/{util → utils}/shortvec-encoding.ts +0 -0
  56. package/src/{util → utils}/sleep.ts +0 -0
  57. package/src/{util → utils}/to-buffer.ts +0 -0
  58. package/src/validator-info.ts +4 -6
  59. package/src/vote-account.ts +1 -1
  60. package/src/util/__forks__/react-native/url-impl.ts +0 -2
  61. package/src/util/makeWebsocketUrl.ts +0 -20
  62. package/src/util/url-impl.ts +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/web3.js",
3
- "version": "1.52.0",
3
+ "version": "1.54.1",
4
4
  "description": "Solana Javascript API",
5
5
  "keywords": [
6
6
  "api",
@@ -58,7 +58,9 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@babel/runtime": "^7.12.5",
61
- "@ethersproject/sha2": "^5.5.0",
61
+ "@noble/ed25519": "^1.7.0",
62
+ "@noble/hashes": "^1.1.2",
63
+ "@noble/secp256k1": "^1.6.3",
62
64
  "@solana/buffer-layout": "^4.0.0",
63
65
  "bigint-buffer": "^1.1.5",
64
66
  "bn.js": "^5.0.0",
@@ -69,11 +71,8 @@
69
71
  "jayson": "^3.4.4",
70
72
  "js-sha3": "^0.8.0",
71
73
  "node-fetch": "2",
72
- "react-native-url-polyfill": "^1.3.0",
73
74
  "rpc-websockets": "^7.5.0",
74
- "secp256k1": "^4.0.2",
75
- "superstruct": "^0.14.2",
76
- "tweetnacl": "^1.0.3"
75
+ "superstruct": "^0.14.2"
77
76
  },
78
77
  "devDependencies": {
79
78
  "@babel/core": "^7.12.13",
@@ -101,7 +100,6 @@
101
100
  "@types/mz": "^2.7.3",
102
101
  "@types/node": "^17.0.24",
103
102
  "@types/node-fetch": "2",
104
- "@types/secp256k1": "^4.0.1",
105
103
  "@types/sinon": "^10.0.0",
106
104
  "@types/sinon-chai": "^3.2.8",
107
105
  "@typescript-eslint/eslint-plugin": "^4.14.2",
@@ -0,0 +1,39 @@
1
+ import * as BufferLayout from '@solana/buffer-layout';
2
+
3
+ export interface IAccountStateData {
4
+ readonly typeIndex: number;
5
+ }
6
+
7
+ /**
8
+ * @internal
9
+ */
10
+ export type AccountType<TInputData extends IAccountStateData> = {
11
+ /** The account type index (from solana upstream program) */
12
+ index: number;
13
+ /** The BufferLayout to use to build data */
14
+ layout: BufferLayout.Layout<TInputData>;
15
+ };
16
+
17
+ /**
18
+ * Decode account data buffer using an AccountType
19
+ * @internal
20
+ */
21
+ export function decodeData<TAccountStateData extends IAccountStateData>(
22
+ type: AccountType<TAccountStateData>,
23
+ data: Uint8Array,
24
+ ): TAccountStateData {
25
+ let decoded: TAccountStateData;
26
+ try {
27
+ decoded = type.layout.decode(data);
28
+ } catch (err) {
29
+ throw new Error('invalid instruction; ' + err);
30
+ }
31
+
32
+ if (decoded.typeIndex !== type.index) {
33
+ throw new Error(
34
+ `invalid account data; account type mismatch ${decoded.typeIndex} != ${type.index}`,
35
+ );
36
+ }
37
+
38
+ return decoded;
39
+ }
package/src/account.ts CHANGED
@@ -1,8 +1,7 @@
1
- import nacl from 'tweetnacl';
2
- import type {SignKeyPair as KeyPair} from 'tweetnacl';
3
- import type {Buffer} from 'buffer';
1
+ import {Buffer} from 'buffer';
4
2
 
5
- import {toBuffer} from './util/to-buffer';
3
+ import {generatePrivateKey, getPublicKey} from './utils/ed25519';
4
+ import {toBuffer} from './utils/to-buffer';
6
5
  import {PublicKey} from './publickey';
7
6
 
8
7
  /**
@@ -12,7 +11,9 @@ import {PublicKey} from './publickey';
12
11
  */
13
12
  export class Account {
14
13
  /** @internal */
15
- _keypair: KeyPair;
14
+ private _publicKey: Buffer;
15
+ /** @internal */
16
+ private _secretKey: Buffer;
16
17
 
17
18
  /**
18
19
  * Create a new Account object
@@ -24,9 +25,15 @@ export class Account {
24
25
  */
25
26
  constructor(secretKey?: Buffer | Uint8Array | Array<number>) {
26
27
  if (secretKey) {
27
- this._keypair = nacl.sign.keyPair.fromSecretKey(toBuffer(secretKey));
28
+ const secretKeyBuffer = toBuffer(secretKey);
29
+ if (secretKey.length !== 64) {
30
+ throw new Error('bad secret key size');
31
+ }
32
+ this._publicKey = secretKeyBuffer.slice(32, 64);
33
+ this._secretKey = secretKeyBuffer.slice(0, 32);
28
34
  } else {
29
- this._keypair = nacl.sign.keyPair();
35
+ this._secretKey = toBuffer(generatePrivateKey());
36
+ this._publicKey = toBuffer(getPublicKey(this._secretKey));
30
37
  }
31
38
  }
32
39
 
@@ -34,13 +41,15 @@ export class Account {
34
41
  * The public key for this account
35
42
  */
36
43
  get publicKey(): PublicKey {
37
- return new PublicKey(this._keypair.publicKey);
44
+ return new PublicKey(this._publicKey);
38
45
  }
39
46
 
40
47
  /**
41
- * The **unencrypted** secret key for this account
48
+ * The **unencrypted** secret key for this account. The first 32 bytes
49
+ * is the private scalar and the last 32 bytes is the public key.
50
+ * Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
42
51
  */
43
52
  get secretKey(): Buffer {
44
- return toBuffer(this._keypair.secretKey);
53
+ return Buffer.concat([this._secretKey, this._publicKey], 64);
45
54
  }
46
55
  }
package/src/connection.ts CHANGED
@@ -24,7 +24,6 @@ import type {Struct} from 'superstruct';
24
24
  import {Client as RpcWebSocketClient} from 'rpc-websockets';
25
25
  import RpcClient from 'jayson/lib/client/browser';
26
26
 
27
- import {URL} from './util/url-impl';
28
27
  import {AgentManager} from './agent-manager';
29
28
  import {EpochSchedule} from './epoch-schedule';
30
29
  import {SendTransactionError, SolanaJSONRPCError} from './errors';
@@ -35,14 +34,15 @@ import {Signer} from './keypair';
35
34
  import {MS_PER_SLOT} from './timing';
36
35
  import {Transaction, TransactionStatus} from './transaction';
37
36
  import {Message} from './message';
38
- import assert from './util/assert';
39
- import {sleep} from './util/sleep';
40
- import {toBuffer} from './util/to-buffer';
37
+ import {AddressLookupTableAccount} from './programs/address-lookup-table/state';
38
+ import assert from './utils/assert';
39
+ import {sleep} from './utils/sleep';
40
+ import {toBuffer} from './utils/to-buffer';
41
41
  import {
42
42
  TransactionExpiredBlockheightExceededError,
43
43
  TransactionExpiredTimeoutError,
44
- } from './util/tx-expiry-custom-errors';
45
- import {makeWebsocketUrl} from './util/makeWebsocketUrl';
44
+ } from './transaction/expiry-custom-errors';
45
+ import {makeWebsocketUrl} from './utils/makeWebsocketUrl';
46
46
  import type {Blockhash} from './blockhash';
47
47
  import type {FeeCalculator} from './fee-calculator';
48
48
  import type {TransactionSignature} from './transaction';
@@ -304,6 +304,14 @@ export type BlockheightBasedTransactionConfirmationStrategy = {
304
304
  signature: TransactionSignature;
305
305
  } & BlockhashWithExpiryBlockHeight;
306
306
 
307
+ /* @internal */
308
+ function assertEndpointUrl(putativeUrl: string) {
309
+ if (/^https?:/.test(putativeUrl) === false) {
310
+ throw new TypeError('Endpoint URL must start with `http:` or `https:`.');
311
+ }
312
+ return putativeUrl;
313
+ }
314
+
307
315
  /** @internal */
308
316
  function extractCommitmentFromConfig<TConfig>(
309
317
  commitmentOrConfig?: Commitment | ({commitment?: Commitment} & TConfig),
@@ -1116,7 +1124,6 @@ export type PerfSample = {
1116
1124
 
1117
1125
  function createRpcClient(
1118
1126
  url: string,
1119
- useHttps: boolean,
1120
1127
  httpHeaders?: HttpHeaders,
1121
1128
  customFetch?: FetchFn,
1122
1129
  fetchMiddleware?: FetchMiddleware,
@@ -1125,7 +1132,7 @@ function createRpcClient(
1125
1132
  const fetch = customFetch ? customFetch : fetchImpl;
1126
1133
  let agentManager: AgentManager | undefined;
1127
1134
  if (!process.env.BROWSER) {
1128
- agentManager = new AgentManager(useHttps);
1135
+ agentManager = new AgentManager(url.startsWith('https:') /* useHttps */);
1129
1136
  }
1130
1137
 
1131
1138
  let fetchWithMiddleware: FetchFn | undefined;
@@ -2492,9 +2499,6 @@ export class Connection {
2492
2499
  endpoint: string,
2493
2500
  commitmentOrConfig?: Commitment | ConnectionConfig,
2494
2501
  ) {
2495
- let url = new URL(endpoint);
2496
- const useHttps = url.protocol === 'https:';
2497
-
2498
2502
  let wsEndpoint;
2499
2503
  let httpHeaders;
2500
2504
  let fetch;
@@ -2513,12 +2517,11 @@ export class Connection {
2513
2517
  disableRetryOnRateLimit = commitmentOrConfig.disableRetryOnRateLimit;
2514
2518
  }
2515
2519
 
2516
- this._rpcEndpoint = endpoint;
2520
+ this._rpcEndpoint = assertEndpointUrl(endpoint);
2517
2521
  this._rpcWsEndpoint = wsEndpoint || makeWebsocketUrl(endpoint);
2518
2522
 
2519
2523
  this._rpcClient = createRpcClient(
2520
- url.toString(),
2521
- useHttps,
2524
+ endpoint,
2522
2525
  httpHeaders,
2523
2526
  fetch,
2524
2527
  fetchMiddleware,
@@ -4218,6 +4221,29 @@ export class Connection {
4218
4221
  return res.result;
4219
4222
  }
4220
4223
 
4224
+ async getAddressLookupTable(
4225
+ accountKey: PublicKey,
4226
+ config?: GetAccountInfoConfig,
4227
+ ): Promise<RpcResponseAndContext<AddressLookupTableAccount | null>> {
4228
+ const {context, value: accountInfo} = await this.getAccountInfoAndContext(
4229
+ accountKey,
4230
+ config,
4231
+ );
4232
+
4233
+ let value = null;
4234
+ if (accountInfo !== null) {
4235
+ value = new AddressLookupTableAccount({
4236
+ key: accountKey,
4237
+ state: AddressLookupTableAccount.deserialize(accountInfo.data),
4238
+ });
4239
+ }
4240
+
4241
+ return {
4242
+ context,
4243
+ value,
4244
+ };
4245
+ }
4246
+
4221
4247
  /**
4222
4248
  * Fetch the contents of a Nonce account from the cluster, return with context
4223
4249
  */
package/src/index.ts CHANGED
@@ -1,33 +1,22 @@
1
1
  export * from './account';
2
- export * from './address-lookup-table-program';
3
2
  export * from './blockhash';
4
3
  export * from './bpf-loader-deprecated';
5
4
  export * from './bpf-loader';
6
- export * from './compute-budget';
7
5
  export * from './connection';
8
6
  export * from './epoch-schedule';
9
- export * from './ed25519-program';
7
+ export * from './errors';
10
8
  export * from './fee-calculator';
11
9
  export * from './keypair';
12
10
  export * from './loader';
13
11
  export * from './message';
14
12
  export * from './nonce-account';
13
+ export * from './programs';
15
14
  export * from './publickey';
16
- export * from './stake-program';
17
- export * from './system-program';
18
- export * from './secp256k1-program';
19
15
  export * from './transaction';
20
- export * from './transaction-constants';
21
16
  export * from './validator-info';
22
17
  export * from './vote-account';
23
- export * from './vote-program';
24
18
  export * from './sysvar';
25
- export * from './errors';
26
- export * from './util/borsh-schema';
27
- export * from './util/send-and-confirm-transaction';
28
- export * from './util/send-and-confirm-raw-transaction';
29
- export * from './util/tx-expiry-custom-errors';
30
- export * from './util/cluster';
19
+ export * from './utils';
31
20
 
32
21
  /**
33
22
  * There are 1-billion lamports in one SOL
package/src/keypair.ts CHANGED
@@ -1,5 +1,4 @@
1
- import nacl from 'tweetnacl';
2
-
1
+ import {generateKeypair, getPublicKey, Ed25519Keypair} from './utils/ed25519';
3
2
  import {PublicKey} from './publickey';
4
3
 
5
4
  /**
@@ -10,14 +9,6 @@ export interface Signer {
10
9
  secretKey: Uint8Array;
11
10
  }
12
11
 
13
- /**
14
- * Ed25519 Keypair
15
- */
16
- export interface Ed25519Keypair {
17
- publicKey: Uint8Array;
18
- secretKey: Uint8Array;
19
- }
20
-
21
12
  /**
22
13
  * An account keypair used for signing transactions.
23
14
  */
@@ -31,18 +22,14 @@ export class Keypair {
31
22
  * @param keypair ed25519 keypair
32
23
  */
33
24
  constructor(keypair?: Ed25519Keypair) {
34
- if (keypair) {
35
- this._keypair = keypair;
36
- } else {
37
- this._keypair = nacl.sign.keyPair();
38
- }
25
+ this._keypair = keypair ?? generateKeypair();
39
26
  }
40
27
 
41
28
  /**
42
29
  * Generate a new random keypair
43
30
  */
44
31
  static generate(): Keypair {
45
- return new Keypair(nacl.sign.keyPair());
32
+ return new Keypair(generateKeypair());
46
33
  }
47
34
 
48
35
  /**
@@ -61,16 +48,20 @@ export class Keypair {
61
48
  secretKey: Uint8Array,
62
49
  options?: {skipValidation?: boolean},
63
50
  ): Keypair {
64
- const keypair = nacl.sign.keyPair.fromSecretKey(secretKey);
51
+ if (secretKey.byteLength !== 64) {
52
+ throw new Error('bad secret key size');
53
+ }
54
+ const publicKey = secretKey.slice(32, 64);
65
55
  if (!options || !options.skipValidation) {
66
- const encoder = new TextEncoder();
67
- const signData = encoder.encode('@solana/web3.js-validation-v1');
68
- const signature = nacl.sign.detached(signData, keypair.secretKey);
69
- if (!nacl.sign.detached.verify(signData, signature, keypair.publicKey)) {
70
- throw new Error('provided secretKey is invalid');
56
+ const privateScalar = secretKey.slice(0, 32);
57
+ const computedPublicKey = getPublicKey(privateScalar);
58
+ for (let ii = 0; ii < 32; ii++) {
59
+ if (publicKey[ii] !== computedPublicKey[ii]) {
60
+ throw new Error('provided secretKey is invalid');
61
+ }
71
62
  }
72
63
  }
73
- return new Keypair(keypair);
64
+ return new Keypair({publicKey, secretKey});
74
65
  }
75
66
 
76
67
  /**
@@ -79,7 +70,11 @@ export class Keypair {
79
70
  * @param seed seed byte array
80
71
  */
81
72
  static fromSeed(seed: Uint8Array): Keypair {
82
- return new Keypair(nacl.sign.keyPair.fromSeed(seed));
73
+ const publicKey = getPublicKey(seed);
74
+ const secretKey = new Uint8Array(64);
75
+ secretKey.set(seed);
76
+ secretKey.set(publicKey, 32);
77
+ return new Keypair({publicKey, secretKey});
83
78
  }
84
79
 
85
80
  /**
package/src/layout.ts CHANGED
@@ -8,6 +8,13 @@ export const publicKey = (property: string = 'publicKey') => {
8
8
  return BufferLayout.blob(32, property);
9
9
  };
10
10
 
11
+ /**
12
+ * Layout for a signature
13
+ */
14
+ export const signature = (property: string = 'signature') => {
15
+ return BufferLayout.blob(64, property);
16
+ };
17
+
11
18
  /**
12
19
  * Layout for a 64bit unsigned value
13
20
  */
package/src/loader.ts CHANGED
@@ -2,15 +2,14 @@ import {Buffer} from 'buffer';
2
2
  import * as BufferLayout from '@solana/buffer-layout';
3
3
 
4
4
  import {PublicKey} from './publickey';
5
- import {Transaction} from './transaction';
5
+ import {Transaction, PACKET_DATA_SIZE} from './transaction';
6
6
  import {SYSVAR_RENT_PUBKEY} from './sysvar';
7
- import {sendAndConfirmTransaction} from './util/send-and-confirm-transaction';
8
- import {sleep} from './util/sleep';
7
+ import {sendAndConfirmTransaction} from './utils/send-and-confirm-transaction';
8
+ import {sleep} from './utils/sleep';
9
9
  import type {Connection} from './connection';
10
10
  import type {Signer} from './keypair';
11
- import {SystemProgram} from './system-program';
11
+ import {SystemProgram} from './programs/system';
12
12
  import {IInstructionInputData} from './instruction';
13
- import {PACKET_DATA_SIZE} from './transaction-constants';
14
13
 
15
14
  // Keep program chunks under PACKET_DATA_SIZE, leaving enough room for the
16
15
  // rest of the Transaction fields
@@ -0,0 +1,45 @@
1
+ import {PublicKey} from '../publickey';
2
+
3
+ export * from './legacy';
4
+ export * from './versioned';
5
+ export * from './v0';
6
+
7
+ /**
8
+ * The message header, identifying signed and read-only account
9
+ */
10
+ export type MessageHeader = {
11
+ /**
12
+ * The number of signatures required for this message to be considered valid. The
13
+ * signatures must match the first `numRequiredSignatures` of `accountKeys`.
14
+ */
15
+ numRequiredSignatures: number;
16
+ /** The last `numReadonlySignedAccounts` of the signed keys are read-only accounts */
17
+ numReadonlySignedAccounts: number;
18
+ /** The last `numReadonlySignedAccounts` of the unsigned keys are read-only accounts */
19
+ numReadonlyUnsignedAccounts: number;
20
+ };
21
+
22
+ /**
23
+ * An address table lookup used to load additional accounts
24
+ */
25
+ export type MessageAddressTableLookup = {
26
+ accountKey: PublicKey;
27
+ writableIndexes: Array<number>;
28
+ readonlyIndexes: Array<number>;
29
+ };
30
+
31
+ /**
32
+ * An instruction to execute by a program
33
+ *
34
+ * @property {number} programIdIndex
35
+ * @property {number[]} accountKeyIndexes
36
+ * @property {Uint8Array} data
37
+ */
38
+ export type MessageCompiledInstruction = {
39
+ /** Index into the transaction keys array indicating the program account that executes this instruction */
40
+ programIdIndex: number;
41
+ /** Ordered indices into the transaction keys array indicating which accounts to pass to the program */
42
+ accountKeyIndexes: number[];
43
+ /** The program input data */
44
+ data: Uint8Array;
45
+ };
@@ -2,27 +2,17 @@ import bs58 from 'bs58';
2
2
  import {Buffer} from 'buffer';
3
3
  import * as BufferLayout from '@solana/buffer-layout';
4
4
 
5
- import {PublicKey} from './publickey';
6
- import type {Blockhash} from './blockhash';
7
- import * as Layout from './layout';
8
- import {PACKET_DATA_SIZE} from './transaction-constants';
9
- import * as shortvec from './util/shortvec-encoding';
10
- import {toBuffer} from './util/to-buffer';
11
-
12
- /**
13
- * The message header, identifying signed and read-only account
14
- */
15
- export type MessageHeader = {
16
- /**
17
- * The number of signatures required for this message to be considered valid. The
18
- * signatures must match the first `numRequiredSignatures` of `accountKeys`.
19
- */
20
- numRequiredSignatures: number;
21
- /** The last `numReadonlySignedAccounts` of the signed keys are read-only accounts */
22
- numReadonlySignedAccounts: number;
23
- /** The last `numReadonlySignedAccounts` of the unsigned keys are read-only accounts */
24
- numReadonlyUnsignedAccounts: number;
25
- };
5
+ import {PublicKey, PUBLIC_KEY_LENGTH} from '../publickey';
6
+ import type {Blockhash} from '../blockhash';
7
+ import * as Layout from '../layout';
8
+ import {PACKET_DATA_SIZE, VERSION_PREFIX_MASK} from '../transaction/constants';
9
+ import * as shortvec from '../utils/shortvec-encoding';
10
+ import {toBuffer} from '../utils/to-buffer';
11
+ import {
12
+ MessageHeader,
13
+ MessageAddressTableLookup,
14
+ MessageCompiledInstruction,
15
+ } from './index';
26
16
 
27
17
  /**
28
18
  * An instruction to execute by a program
@@ -54,8 +44,6 @@ export type MessageArgs = {
54
44
  instructions: CompiledInstruction[];
55
45
  };
56
46
 
57
- const PUBKEY_LENGTH = 32;
58
-
59
47
  /**
60
48
  * List of instructions to be processed atomically
61
49
  */
@@ -83,6 +71,28 @@ export class Message {
83
71
  );
84
72
  }
85
73
 
74
+ get version(): 'legacy' {
75
+ return 'legacy';
76
+ }
77
+
78
+ get staticAccountKeys(): Array<PublicKey> {
79
+ return this.accountKeys;
80
+ }
81
+
82
+ get compiledInstructions(): Array<MessageCompiledInstruction> {
83
+ return this.instructions.map(
84
+ (ix): MessageCompiledInstruction => ({
85
+ programIdIndex: ix.programIdIndex,
86
+ accountKeyIndexes: ix.accounts,
87
+ data: bs58.decode(ix.data),
88
+ }),
89
+ );
90
+ }
91
+
92
+ get addressTableLookups(): Array<MessageAddressTableLookup> {
93
+ return [];
94
+ }
95
+
86
96
  isAccountSigner(index: number): boolean {
87
97
  return index < this.header.numRequiredSignatures;
88
98
  }
@@ -223,19 +233,28 @@ export class Message {
223
233
  let byteArray = [...buffer];
224
234
 
225
235
  const numRequiredSignatures = byteArray.shift() as number;
236
+ if (
237
+ numRequiredSignatures !==
238
+ (numRequiredSignatures & VERSION_PREFIX_MASK)
239
+ ) {
240
+ throw new Error(
241
+ 'Versioned messages must be deserialized with VersionedMessage.deserialize()',
242
+ );
243
+ }
244
+
226
245
  const numReadonlySignedAccounts = byteArray.shift() as number;
227
246
  const numReadonlyUnsignedAccounts = byteArray.shift() as number;
228
247
 
229
248
  const accountCount = shortvec.decodeLength(byteArray);
230
249
  let accountKeys = [];
231
250
  for (let i = 0; i < accountCount; i++) {
232
- const account = byteArray.slice(0, PUBKEY_LENGTH);
233
- byteArray = byteArray.slice(PUBKEY_LENGTH);
251
+ const account = byteArray.slice(0, PUBLIC_KEY_LENGTH);
252
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
234
253
  accountKeys.push(bs58.encode(Buffer.from(account)));
235
254
  }
236
255
 
237
- const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
238
- byteArray = byteArray.slice(PUBKEY_LENGTH);
256
+ const recentBlockhash = byteArray.slice(0, PUBLIC_KEY_LENGTH);
257
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
239
258
 
240
259
  const instructionCount = shortvec.decodeLength(byteArray);
241
260
  let instructions: CompiledInstruction[] = [];