@solana/web3.js 1.54.0 → 1.56.0

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.54.0",
3
+ "version": "1.56.0",
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",
@@ -70,9 +72,7 @@
70
72
  "js-sha3": "^0.8.0",
71
73
  "node-fetch": "2",
72
74
  "rpc-websockets": "^7.5.0",
73
- "secp256k1": "^4.0.2",
74
- "superstruct": "^0.14.2",
75
- "tweetnacl": "^1.0.3"
75
+ "superstruct": "^0.14.2"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@babel/core": "^7.12.13",
@@ -100,7 +100,6 @@
100
100
  "@types/mz": "^2.7.3",
101
101
  "@types/node": "^17.0.24",
102
102
  "@types/node-fetch": "2",
103
- "@types/secp256k1": "^4.0.1",
104
103
  "@types/sinon": "^10.0.0",
105
104
  "@types/sinon-chai": "^3.2.8",
106
105
  "@typescript-eslint/eslint-plugin": "^4.14.2",
package/src/account.ts CHANGED
@@ -1,7 +1,6 @@
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
 
3
+ import {generatePrivateKey, getPublicKey} from './utils/ed25519';
5
4
  import {toBuffer} from './utils/to-buffer';
6
5
  import {PublicKey} from './publickey';
7
6
 
@@ -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
@@ -32,8 +32,12 @@ import {NonceAccount} from './nonce-account';
32
32
  import {PublicKey} from './publickey';
33
33
  import {Signer} from './keypair';
34
34
  import {MS_PER_SLOT} from './timing';
35
- import {Transaction, TransactionStatus} from './transaction';
36
- import {Message} from './message';
35
+ import {
36
+ Transaction,
37
+ TransactionStatus,
38
+ TransactionVersion,
39
+ } from './transaction';
40
+ import {Message, MessageHeader, MessageV0, VersionedMessage} from './message';
37
41
  import {AddressLookupTableAccount} from './programs/address-lookup-table/state';
38
42
  import assert from './utils/assert';
39
43
  import {sleep} from './utils/sleep';
@@ -395,6 +399,32 @@ function notificationResultAndContext<T, U>(value: Struct<T, U>) {
395
399
  });
396
400
  }
397
401
 
402
+ /**
403
+ * @internal
404
+ */
405
+ function versionedMessageFromResponse(
406
+ version: TransactionVersion | undefined,
407
+ response: MessageResponse,
408
+ ): VersionedMessage {
409
+ if (version === 0) {
410
+ return new MessageV0({
411
+ header: response.header,
412
+ staticAccountKeys: response.accountKeys.map(
413
+ accountKey => new PublicKey(accountKey),
414
+ ),
415
+ recentBlockhash: response.recentBlockhash,
416
+ compiledInstructions: response.instructions.map(ix => ({
417
+ programIdIndex: ix.programIdIndex,
418
+ accountKeyIndexes: ix.accounts,
419
+ data: bs58.decode(ix.data),
420
+ })),
421
+ addressTableLookups: response.addressTableLookups!,
422
+ });
423
+ } else {
424
+ return new Message(response);
425
+ }
426
+ }
427
+
398
428
  /**
399
429
  * The level of commitment desired when querying state
400
430
  * <pre>
@@ -457,6 +487,14 @@ export type GetBalanceConfig = {
457
487
  export type GetBlockConfig = {
458
488
  /** The level of finality desired */
459
489
  commitment?: Finality;
490
+ };
491
+
492
+ /**
493
+ * Configuration object for changing `getBlock` query behavior
494
+ */
495
+ export type GetVersionedBlockConfig = {
496
+ /** The level of finality desired */
497
+ commitment?: Finality;
460
498
  /** The max transaction version to return in responses. If the requested transaction is a higher version, an error will be returned */
461
499
  maxSupportedTransactionVersion?: number;
462
500
  };
@@ -537,6 +575,14 @@ export type GetSlotLeaderConfig = {
537
575
  export type GetTransactionConfig = {
538
576
  /** The level of finality desired */
539
577
  commitment?: Finality;
578
+ };
579
+
580
+ /**
581
+ * Configuration object for changing `getTransaction` query behavior
582
+ */
583
+ export type GetVersionedTransactionConfig = {
584
+ /** The level of finality desired */
585
+ commitment?: Finality;
540
586
  /** The max transaction version to return in responses. If the requested transaction is a higher version, an error will be returned */
541
587
  maxSupportedTransactionVersion?: number;
542
588
  };
@@ -869,6 +915,8 @@ export type ConfirmedTransactionMeta = {
869
915
  postTokenBalances?: Array<TokenBalance> | null;
870
916
  /** The error result of transaction processing */
871
917
  err: TransactionError | null;
918
+ /** The collection of addresses loaded using address lookup tables */
919
+ loadedAddresses?: LoadedAddresses;
872
920
  };
873
921
 
874
922
  /**
@@ -890,6 +938,38 @@ export type TransactionResponse = {
890
938
  blockTime?: number | null;
891
939
  };
892
940
 
941
+ /**
942
+ * A processed transaction from the RPC API
943
+ */
944
+ export type VersionedTransactionResponse = {
945
+ /** The slot during which the transaction was processed */
946
+ slot: number;
947
+ /** The transaction */
948
+ transaction: {
949
+ /** The transaction message */
950
+ message: VersionedMessage;
951
+ /** The transaction signatures */
952
+ signatures: string[];
953
+ };
954
+ /** Metadata produced from the transaction */
955
+ meta: ConfirmedTransactionMeta | null;
956
+ /** The unix timestamp of when the transaction was processed */
957
+ blockTime?: number | null;
958
+ /** The transaction version */
959
+ version?: TransactionVersion;
960
+ };
961
+
962
+ /**
963
+ * A processed transaction message from the RPC API
964
+ */
965
+ type MessageResponse = {
966
+ accountKeys: string[];
967
+ header: MessageHeader;
968
+ instructions: CompiledInstruction[];
969
+ recentBlockhash: string;
970
+ addressTableLookups?: ParsedAddressTableLookup[];
971
+ };
972
+
893
973
  /**
894
974
  * A confirmed transaction on the ledger
895
975
  *
@@ -942,6 +1022,18 @@ export type ParsedInstruction = {
942
1022
  parsed: any;
943
1023
  };
944
1024
 
1025
+ /**
1026
+ * A parsed address table lookup
1027
+ */
1028
+ export type ParsedAddressTableLookup = {
1029
+ /** Address lookup table account key */
1030
+ accountKey: PublicKey;
1031
+ /** Parsed instruction info */
1032
+ writableIndexes: number[];
1033
+ /** Parsed instruction info */
1034
+ readonlyIndexes: number[];
1035
+ };
1036
+
945
1037
  /**
946
1038
  * A parsed transaction message
947
1039
  */
@@ -952,6 +1044,8 @@ export type ParsedMessage = {
952
1044
  instructions: (ParsedInstruction | PartiallyDecodedInstruction)[];
953
1045
  /** Recent blockhash */
954
1046
  recentBlockhash: string;
1047
+ /** Address table lookups used to load additional accounts */
1048
+ addressTableLookups?: ParsedAddressTableLookup[] | null;
955
1049
  };
956
1050
 
957
1051
  /**
@@ -983,6 +1077,8 @@ export type ParsedTransactionWithMeta = {
983
1077
  meta: ParsedTransactionMeta | null;
984
1078
  /** The unix timestamp of when the transaction was processed */
985
1079
  blockTime?: number | null;
1080
+ /** The version of the transaction message */
1081
+ version?: TransactionVersion;
986
1082
  };
987
1083
 
988
1084
  /**
@@ -1006,6 +1102,47 @@ export type BlockResponse = {
1006
1102
  };
1007
1103
  /** Metadata produced from the transaction */
1008
1104
  meta: ConfirmedTransactionMeta | null;
1105
+ /** The transaction version */
1106
+ version?: TransactionVersion;
1107
+ }>;
1108
+ /** Vector of block rewards */
1109
+ rewards?: Array<{
1110
+ /** Public key of reward recipient */
1111
+ pubkey: string;
1112
+ /** Reward value in lamports */
1113
+ lamports: number;
1114
+ /** Account balance after reward is applied */
1115
+ postBalance: number | null;
1116
+ /** Type of reward received */
1117
+ rewardType: string | null;
1118
+ }>;
1119
+ /** The unix timestamp of when the block was processed */
1120
+ blockTime: number | null;
1121
+ };
1122
+
1123
+ /**
1124
+ * A processed block fetched from the RPC API
1125
+ */
1126
+ export type VersionedBlockResponse = {
1127
+ /** Blockhash of this block */
1128
+ blockhash: Blockhash;
1129
+ /** Blockhash of this block's parent */
1130
+ previousBlockhash: Blockhash;
1131
+ /** Slot index of this block's parent */
1132
+ parentSlot: number;
1133
+ /** Vector of transactions with status meta and original message */
1134
+ transactions: Array<{
1135
+ /** The transaction */
1136
+ transaction: {
1137
+ /** The transaction message */
1138
+ message: VersionedMessage;
1139
+ /** The transaction signatures */
1140
+ signatures: string[];
1141
+ };
1142
+ /** Metadata produced from the transaction */
1143
+ meta: ConfirmedTransactionMeta | null;
1144
+ /** The transaction version */
1145
+ version?: TransactionVersion;
1009
1146
  }>;
1010
1147
  /** Vector of block rewards */
1011
1148
  rewards?: Array<{
@@ -1728,6 +1865,12 @@ const GetSignatureStatusesRpcResult = jsonRpcResultAndContext(
1728
1865
  */
1729
1866
  const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult(number());
1730
1867
 
1868
+ const AddressTableLookupStruct = pick({
1869
+ accountKey: PublicKeyFromString,
1870
+ writableIndexes: array(number()),
1871
+ readonlyIndexes: array(number()),
1872
+ });
1873
+
1731
1874
  const ConfirmedTransactionResult = pick({
1732
1875
  signatures: array(string()),
1733
1876
  message: pick({
@@ -1745,6 +1888,7 @@ const ConfirmedTransactionResult = pick({
1745
1888
  }),
1746
1889
  ),
1747
1890
  recentBlockhash: string(),
1891
+ addressTableLookups: optional(array(AddressTableLookupStruct)),
1748
1892
  }),
1749
1893
  });
1750
1894
 
@@ -1805,6 +1949,7 @@ const ParsedConfirmedTransactionResult = pick({
1805
1949
  ),
1806
1950
  instructions: array(ParsedOrRawInstruction),
1807
1951
  recentBlockhash: string(),
1952
+ addressTableLookups: optional(nullable(array(AddressTableLookupStruct))),
1808
1953
  }),
1809
1954
  });
1810
1955
 
@@ -1874,6 +2019,8 @@ const ParsedConfirmedTransactionMetaResult = pick({
1874
2019
  loadedAddresses: optional(LoadedAddressesResult),
1875
2020
  });
1876
2021
 
2022
+ const TransactionVersionStruct = union([literal(0), literal('legacy')]);
2023
+
1877
2024
  /**
1878
2025
  * Expected JSON RPC response for the "getBlock" message
1879
2026
  */
@@ -1887,6 +2034,7 @@ const GetBlockRpcResult = jsonRpcResult(
1887
2034
  pick({
1888
2035
  transaction: ConfirmedTransactionResult,
1889
2036
  meta: nullable(ConfirmedTransactionMetaResult),
2037
+ version: optional(TransactionVersionStruct),
1890
2038
  }),
1891
2039
  ),
1892
2040
  rewards: optional(
@@ -1962,6 +2110,7 @@ const GetTransactionRpcResult = jsonRpcResult(
1962
2110
  meta: ConfirmedTransactionMetaResult,
1963
2111
  blockTime: optional(nullable(number())),
1964
2112
  transaction: ConfirmedTransactionResult,
2113
+ version: optional(TransactionVersionStruct),
1965
2114
  }),
1966
2115
  ),
1967
2116
  );
@@ -1976,6 +2125,7 @@ const GetParsedTransactionRpcResult = jsonRpcResult(
1976
2125
  transaction: ParsedConfirmedTransactionResult,
1977
2126
  meta: nullable(ParsedConfirmedTransactionMetaResult),
1978
2127
  blockTime: optional(nullable(number())),
2128
+ version: optional(TransactionVersionStruct),
1979
2129
  }),
1980
2130
  ),
1981
2131
  );
@@ -3644,11 +3794,32 @@ export class Connection {
3644
3794
 
3645
3795
  /**
3646
3796
  * Fetch a processed block from the cluster.
3797
+ *
3798
+ * @deprecated Instead, call `getBlock` using a `GetVersionedBlockConfig` by
3799
+ * setting the `maxSupportedTransactionVersion` property.
3647
3800
  */
3648
3801
  async getBlock(
3649
3802
  slot: number,
3650
3803
  rawConfig?: GetBlockConfig,
3651
- ): Promise<BlockResponse | null> {
3804
+ ): Promise<BlockResponse | null>;
3805
+
3806
+ /**
3807
+ * Fetch a processed block from the cluster.
3808
+ */
3809
+ // eslint-disable-next-line no-dupe-class-members
3810
+ async getBlock(
3811
+ slot: number,
3812
+ rawConfig?: GetVersionedBlockConfig,
3813
+ ): Promise<VersionedBlockResponse | null>;
3814
+
3815
+ /**
3816
+ * Fetch a processed block from the cluster.
3817
+ */
3818
+ // eslint-disable-next-line no-dupe-class-members
3819
+ async getBlock(
3820
+ slot: number,
3821
+ rawConfig?: GetVersionedBlockConfig,
3822
+ ): Promise<VersionedBlockResponse | null> {
3652
3823
  const {commitment, config} = extractCommitmentFromConfig(rawConfig);
3653
3824
  const args = this._buildArgsAtLeastConfirmed(
3654
3825
  [slot],
@@ -3668,16 +3839,14 @@ export class Connection {
3668
3839
 
3669
3840
  return {
3670
3841
  ...result,
3671
- transactions: result.transactions.map(({transaction, meta}) => {
3672
- const message = new Message(transaction.message);
3673
- return {
3674
- meta,
3675
- transaction: {
3676
- ...transaction,
3677
- message,
3678
- },
3679
- };
3680
- }),
3842
+ transactions: result.transactions.map(({transaction, meta, version}) => ({
3843
+ meta,
3844
+ transaction: {
3845
+ ...transaction,
3846
+ message: versionedMessageFromResponse(version, transaction.message),
3847
+ },
3848
+ version,
3849
+ })),
3681
3850
  };
3682
3851
  }
3683
3852
 
@@ -3739,11 +3908,33 @@ export class Connection {
3739
3908
 
3740
3909
  /**
3741
3910
  * Fetch a confirmed or finalized transaction from the cluster.
3911
+ *
3912
+ * @deprecated Instead, call `getTransaction` using a
3913
+ * `GetVersionedTransactionConfig` by setting the
3914
+ * `maxSupportedTransactionVersion` property.
3742
3915
  */
3743
3916
  async getTransaction(
3744
3917
  signature: string,
3745
3918
  rawConfig?: GetTransactionConfig,
3746
- ): Promise<TransactionResponse | null> {
3919
+ ): Promise<TransactionResponse | null>;
3920
+
3921
+ /**
3922
+ * Fetch a confirmed or finalized transaction from the cluster.
3923
+ */
3924
+ // eslint-disable-next-line no-dupe-class-members
3925
+ async getTransaction(
3926
+ signature: string,
3927
+ rawConfig: GetVersionedTransactionConfig,
3928
+ ): Promise<VersionedTransactionResponse | null>;
3929
+
3930
+ /**
3931
+ * Fetch a confirmed or finalized transaction from the cluster.
3932
+ */
3933
+ // eslint-disable-next-line no-dupe-class-members
3934
+ async getTransaction(
3935
+ signature: string,
3936
+ rawConfig?: GetVersionedTransactionConfig,
3937
+ ): Promise<VersionedTransactionResponse | null> {
3747
3938
  const {commitment, config} = extractCommitmentFromConfig(rawConfig);
3748
3939
  const args = this._buildArgsAtLeastConfirmed(
3749
3940
  [signature],
@@ -3764,7 +3955,10 @@ export class Connection {
3764
3955
  ...result,
3765
3956
  transaction: {
3766
3957
  ...result.transaction,
3767
- message: new Message(result.transaction.message),
3958
+ message: versionedMessageFromResponse(
3959
+ result.version,
3960
+ result.transaction.message,
3961
+ ),
3768
3962
  },
3769
3963
  };
3770
3964
  }
@@ -3774,8 +3968,8 @@ export class Connection {
3774
3968
  */
3775
3969
  async getParsedTransaction(
3776
3970
  signature: TransactionSignature,
3777
- commitmentOrConfig?: GetTransactionConfig | Finality,
3778
- ): Promise<ParsedConfirmedTransaction | null> {
3971
+ commitmentOrConfig?: GetVersionedTransactionConfig | Finality,
3972
+ ): Promise<ParsedTransactionWithMeta | null> {
3779
3973
  const {commitment, config} =
3780
3974
  extractCommitmentFromConfig(commitmentOrConfig);
3781
3975
  const args = this._buildArgsAtLeastConfirmed(
@@ -3797,8 +3991,8 @@ export class Connection {
3797
3991
  */
3798
3992
  async getParsedTransactions(
3799
3993
  signatures: TransactionSignature[],
3800
- commitmentOrConfig?: GetTransactionConfig | Finality,
3801
- ): Promise<(ParsedConfirmedTransaction | null)[]> {
3994
+ commitmentOrConfig?: GetVersionedTransactionConfig | Finality,
3995
+ ): Promise<(ParsedTransactionWithMeta | null)[]> {
3802
3996
  const {commitment, config} =
3803
3997
  extractCommitmentFromConfig(commitmentOrConfig);
3804
3998
  const batch = signatures.map(signature => {
@@ -3829,11 +4023,37 @@ export class Connection {
3829
4023
  /**
3830
4024
  * Fetch transaction details for a batch of confirmed transactions.
3831
4025
  * Similar to {@link getParsedTransactions} but returns a {@link TransactionResponse}.
4026
+ *
4027
+ * @deprecated Instead, call `getTransactions` using a
4028
+ * `GetVersionedTransactionConfig` by setting the
4029
+ * `maxSupportedTransactionVersion` property.
3832
4030
  */
3833
4031
  async getTransactions(
3834
4032
  signatures: TransactionSignature[],
3835
4033
  commitmentOrConfig?: GetTransactionConfig | Finality,
3836
- ): Promise<(TransactionResponse | null)[]> {
4034
+ ): Promise<(TransactionResponse | null)[]>;
4035
+
4036
+ /**
4037
+ * Fetch transaction details for a batch of confirmed transactions.
4038
+ * Similar to {@link getParsedTransactions} but returns a {@link
4039
+ * VersionedTransactionResponse}.
4040
+ */
4041
+ // eslint-disable-next-line no-dupe-class-members
4042
+ async getTransactions(
4043
+ signatures: TransactionSignature[],
4044
+ commitmentOrConfig: GetVersionedTransactionConfig | Finality,
4045
+ ): Promise<(VersionedTransactionResponse | null)[]>;
4046
+
4047
+ /**
4048
+ * Fetch transaction details for a batch of confirmed transactions.
4049
+ * Similar to {@link getParsedTransactions} but returns a {@link
4050
+ * VersionedTransactionResponse}.
4051
+ */
4052
+ // eslint-disable-next-line no-dupe-class-members
4053
+ async getTransactions(
4054
+ signatures: TransactionSignature[],
4055
+ commitmentOrConfig: GetVersionedTransactionConfig | Finality,
4056
+ ): Promise<(VersionedTransactionResponse | null)[]> {
3837
4057
  const {commitment, config} =
3838
4058
  extractCommitmentFromConfig(commitmentOrConfig);
3839
4059
  const batch = signatures.map(signature => {
@@ -3862,7 +4082,10 @@ export class Connection {
3862
4082
  ...result,
3863
4083
  transaction: {
3864
4084
  ...result.transaction,
3865
- message: new Message(result.transaction.message),
4085
+ message: versionedMessageFromResponse(
4086
+ result.version,
4087
+ result.transaction.message,
4088
+ ),
3866
4089
  },
3867
4090
  };
3868
4091
  });
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
  /**
@@ -5,17 +5,26 @@ import {MessageV0} from './v0';
5
5
  export type VersionedMessage = Message | MessageV0;
6
6
  // eslint-disable-next-line no-redeclare
7
7
  export const VersionedMessage = {
8
- deserialize: (serializedMessage: Uint8Array): VersionedMessage => {
8
+ deserializeMessageVersion(serializedMessage: Uint8Array): 'legacy' | number {
9
9
  const prefix = serializedMessage[0];
10
10
  const maskedPrefix = prefix & VERSION_PREFIX_MASK;
11
11
 
12
12
  // if the highest bit of the prefix is not set, the message is not versioned
13
13
  if (maskedPrefix === prefix) {
14
- return Message.from(serializedMessage);
14
+ return 'legacy';
15
15
  }
16
16
 
17
17
  // the lower 7 bits of the prefix indicate the message version
18
- const version = maskedPrefix;
18
+ return maskedPrefix;
19
+ },
20
+
21
+ deserialize: (serializedMessage: Uint8Array): VersionedMessage => {
22
+ const version =
23
+ VersionedMessage.deserializeMessageVersion(serializedMessage);
24
+ if (version === 'legacy') {
25
+ return Message.from(serializedMessage);
26
+ }
27
+
19
28
  if (version === 0) {
20
29
  return MessageV0.deserialize(serializedMessage);
21
30
  } else {
@@ -1,11 +1,11 @@
1
1
  import {Buffer} from 'buffer';
2
2
  import * as BufferLayout from '@solana/buffer-layout';
3
- import nacl from 'tweetnacl';
4
3
 
5
4
  import {Keypair} from '../keypair';
6
5
  import {PublicKey} from '../publickey';
7
6
  import {TransactionInstruction} from '../transaction';
8
7
  import assert from '../utils/assert';
8
+ import {sign} from '../utils/ed25519';
9
9
 
10
10
  const PRIVATE_KEY_BYTES = 64;
11
11
  const PUBLIC_KEY_BYTES = 32;
@@ -142,7 +142,7 @@ export class Ed25519Program {
142
142
  try {
143
143
  const keypair = Keypair.fromSecretKey(privateKey);
144
144
  const publicKey = keypair.publicKey.toBytes();
145
- const signature = nacl.sign.detached(message, keypair.secretKey);
145
+ const signature = sign(message, keypair.secretKey);
146
146
 
147
147
  return this.createInstructionWithPublicKey({
148
148
  publicKey,