@solana/web3.js 1.53.0 → 1.55.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.
Files changed (39) hide show
  1. package/lib/index.browser.cjs.js +459 -1825
  2. package/lib/index.browser.cjs.js.map +1 -1
  3. package/lib/index.browser.esm.js +455 -1826
  4. package/lib/index.browser.esm.js.map +1 -1
  5. package/lib/index.cjs.js +462 -1847
  6. package/lib/index.cjs.js.map +1 -1
  7. package/lib/index.d.ts +114 -12
  8. package/lib/index.esm.js +458 -1848
  9. package/lib/index.esm.js.map +1 -1
  10. package/lib/index.iife.js +19272 -25771
  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 +459 -1824
  15. package/lib/index.native.js.map +1 -1
  16. package/package.json +5 -7
  17. package/src/account.ts +18 -9
  18. package/src/connection.ts +11 -9
  19. package/src/keypair.ts +19 -24
  20. package/src/layout.ts +7 -0
  21. package/src/message/index.ts +19 -6
  22. package/src/message/legacy.ts +58 -9
  23. package/src/message/v0.ts +324 -0
  24. package/src/message/versioned.ts +36 -0
  25. package/src/programs/ed25519.ts +2 -2
  26. package/src/programs/secp256k1.ts +6 -5
  27. package/src/programs/vote.ts +21 -0
  28. package/src/publickey.ts +14 -73
  29. package/src/transaction/constants.ts +2 -0
  30. package/src/transaction/index.ts +1 -0
  31. package/src/transaction/legacy.ts +3 -5
  32. package/src/transaction/versioned.ts +105 -0
  33. package/src/utils/ed25519.ts +46 -0
  34. package/src/utils/index.ts +1 -0
  35. package/src/utils/makeWebsocketUrl.ts +22 -16
  36. package/src/utils/secp256k1.ts +18 -0
  37. package/src/validator-info.ts +3 -5
  38. package/src/utils/__forks__/react-native/url-impl.ts +0 -2
  39. package/src/utils/url-impl.ts +0 -2
@@ -0,0 +1,105 @@
1
+ import * as BufferLayout from '@solana/buffer-layout';
2
+
3
+ import {Signer} from '../keypair';
4
+ import assert from '../utils/assert';
5
+ import {VersionedMessage} from '../message/versioned';
6
+ import {SIGNATURE_LENGTH_IN_BYTES} from './constants';
7
+ import * as shortvec from '../utils/shortvec-encoding';
8
+ import * as Layout from '../layout';
9
+ import {sign} from '../utils/ed25519';
10
+
11
+ export type TransactionVersion = 'legacy' | 0;
12
+
13
+ /**
14
+ * Versioned transaction class
15
+ */
16
+ export class VersionedTransaction {
17
+ signatures: Array<Uint8Array>;
18
+ message: VersionedMessage;
19
+
20
+ constructor(message: VersionedMessage, signatures?: Array<Uint8Array>) {
21
+ if (signatures !== undefined) {
22
+ assert(
23
+ signatures.length === message.header.numRequiredSignatures,
24
+ 'Expected signatures length to be equal to the number of required signatures',
25
+ );
26
+ this.signatures = signatures;
27
+ } else {
28
+ const defaultSignatures = [];
29
+ for (let i = 0; i < message.header.numRequiredSignatures; i++) {
30
+ defaultSignatures.push(new Uint8Array(SIGNATURE_LENGTH_IN_BYTES));
31
+ }
32
+ this.signatures = defaultSignatures;
33
+ }
34
+ this.message = message;
35
+ }
36
+
37
+ serialize(): Uint8Array {
38
+ const serializedMessage = this.message.serialize();
39
+
40
+ const encodedSignaturesLength = Array<number>();
41
+ shortvec.encodeLength(encodedSignaturesLength, this.signatures.length);
42
+
43
+ const transactionLayout = BufferLayout.struct<{
44
+ encodedSignaturesLength: Uint8Array;
45
+ signatures: Array<Uint8Array>;
46
+ serializedMessage: Uint8Array;
47
+ }>([
48
+ BufferLayout.blob(
49
+ encodedSignaturesLength.length,
50
+ 'encodedSignaturesLength',
51
+ ),
52
+ BufferLayout.seq(
53
+ Layout.signature(),
54
+ this.signatures.length,
55
+ 'signatures',
56
+ ),
57
+ BufferLayout.blob(serializedMessage.length, 'serializedMessage'),
58
+ ]);
59
+
60
+ const serializedTransaction = new Uint8Array(2048);
61
+ const serializedTransactionLength = transactionLayout.encode(
62
+ {
63
+ encodedSignaturesLength: new Uint8Array(encodedSignaturesLength),
64
+ signatures: this.signatures,
65
+ serializedMessage,
66
+ },
67
+ serializedTransaction,
68
+ );
69
+
70
+ return serializedTransaction.slice(0, serializedTransactionLength);
71
+ }
72
+
73
+ static deserialize(serializedTransaction: Uint8Array): VersionedTransaction {
74
+ let byteArray = [...serializedTransaction];
75
+
76
+ const signatures = [];
77
+ const signaturesLength = shortvec.decodeLength(byteArray);
78
+ for (let i = 0; i < signaturesLength; i++) {
79
+ signatures.push(
80
+ new Uint8Array(byteArray.splice(0, SIGNATURE_LENGTH_IN_BYTES)),
81
+ );
82
+ }
83
+
84
+ const message = VersionedMessage.deserialize(new Uint8Array(byteArray));
85
+ return new VersionedTransaction(message, signatures);
86
+ }
87
+
88
+ sign(signers: Array<Signer>) {
89
+ const messageData = this.message.serialize();
90
+ const signerPubkeys = this.message.staticAccountKeys.slice(
91
+ 0,
92
+ this.message.header.numRequiredSignatures,
93
+ );
94
+ for (const signer of signers) {
95
+ const signerIndex = signerPubkeys.findIndex(pubkey =>
96
+ pubkey.equals(signer.publicKey),
97
+ );
98
+ assert(
99
+ signerIndex >= 0,
100
+ `Cannot sign with non signer key ${signer.publicKey.toBase58()}`,
101
+ );
102
+ this.signatures[signerIndex] = sign(messageData, signer.secretKey);
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,46 @@
1
+ import {sha512} from '@noble/hashes/sha512';
2
+ import * as ed25519 from '@noble/ed25519';
3
+
4
+ /**
5
+ * A 64 byte secret key, the first 32 bytes of which is the
6
+ * private scalar and the last 32 bytes is the public key.
7
+ * Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
8
+ */
9
+ type Ed25519SecretKey = Uint8Array;
10
+
11
+ /**
12
+ * Ed25519 Keypair
13
+ */
14
+ export interface Ed25519Keypair {
15
+ publicKey: Uint8Array;
16
+ secretKey: Ed25519SecretKey;
17
+ }
18
+
19
+ ed25519.utils.sha512Sync = (...m) => sha512(ed25519.utils.concatBytes(...m));
20
+
21
+ export const generatePrivateKey = ed25519.utils.randomPrivateKey;
22
+ export const generateKeypair = (): Ed25519Keypair => {
23
+ const privateScalar = ed25519.utils.randomPrivateKey();
24
+ const publicKey = getPublicKey(privateScalar);
25
+ const secretKey = new Uint8Array(64);
26
+ secretKey.set(privateScalar);
27
+ secretKey.set(publicKey, 32);
28
+ return {
29
+ publicKey,
30
+ secretKey,
31
+ };
32
+ };
33
+ export const getPublicKey = ed25519.sync.getPublicKey;
34
+ export function isOnCurve(publicKey: Uint8Array): boolean {
35
+ try {
36
+ ed25519.Point.fromHex(publicKey, true /* strict */);
37
+ return true;
38
+ } catch {
39
+ return false;
40
+ }
41
+ }
42
+ export const sign = (
43
+ message: Parameters<typeof ed25519.sync.sign>[0],
44
+ secretKey: Ed25519SecretKey,
45
+ ) => ed25519.sync.sign(message, secretKey.slice(0, 32));
46
+ export const verify = ed25519.sync.verify;
@@ -1,4 +1,5 @@
1
1
  export * from './borsh-schema';
2
2
  export * from './cluster';
3
+ export type {Ed25519Keypair} from './ed25519';
3
4
  export * from './send-and-confirm-raw-transaction';
4
5
  export * from './send-and-confirm-transaction';
@@ -1,20 +1,26 @@
1
- import {URL} from './url-impl';
1
+ const URL_RE = /^[^:]+:\/\/([^:[]+|\[[^\]]+\])(:\d+)?(.*)/i;
2
2
 
3
3
  export function makeWebsocketUrl(endpoint: string) {
4
- let url = new URL(endpoint);
5
- const useHttps = url.protocol === 'https:';
6
-
7
- url.protocol = useHttps ? 'wss:' : 'ws:';
8
- url.host = '';
9
-
10
- // Only shift the port by +1 as a convention for ws(s) only if given endpoint
11
- // is explictly specifying the endpoint port (HTTP-based RPC), assuming
12
- // we're directly trying to connect to solana-validator's ws listening port.
13
- // When the endpoint omits the port, we're connecting to the protocol
14
- // default ports: http(80) or https(443) and it's assumed we're behind a reverse
15
- // proxy which manages WebSocket upgrade and backend port redirection.
16
- if (url.port !== '') {
17
- url.port = String(Number(url.port) + 1);
4
+ const matches = endpoint.match(URL_RE);
5
+ if (matches == null) {
6
+ throw TypeError(`Failed to validate endpoint URL \`${endpoint}\``);
18
7
  }
19
- return url.toString();
8
+ const [
9
+ _, // eslint-disable-line @typescript-eslint/no-unused-vars
10
+ hostish,
11
+ portWithColon,
12
+ rest,
13
+ ] = matches;
14
+ const protocol = endpoint.startsWith('https:') ? 'wss:' : 'ws:';
15
+ const startPort =
16
+ portWithColon == null ? null : parseInt(portWithColon.slice(1), 10);
17
+ const websocketPort =
18
+ // Only shift the port by +1 as a convention for ws(s) only if given endpoint
19
+ // is explictly specifying the endpoint port (HTTP-based RPC), assuming
20
+ // we're directly trying to connect to solana-validator's ws listening port.
21
+ // When the endpoint omits the port, we're connecting to the protocol
22
+ // default ports: http(80) or https(443) and it's assumed we're behind a reverse
23
+ // proxy which manages WebSocket upgrade and backend port redirection.
24
+ startPort == null ? '' : `:${startPort + 1}`;
25
+ return `${protocol}//${hostish}${websocketPort}${rest}`;
20
26
  }
@@ -0,0 +1,18 @@
1
+ import {hmac} from '@noble/hashes/hmac';
2
+ import {sha256} from '@noble/hashes/sha256';
3
+ import * as secp256k1 from '@noble/secp256k1';
4
+
5
+ // Supply a synchronous hashing algorithm to make this
6
+ // library interoperable with the synchronous APIs in web3.js.
7
+ secp256k1.utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => {
8
+ const h = hmac.create(sha256, key);
9
+ msgs.forEach(msg => h.update(msg));
10
+ return h.digest();
11
+ };
12
+
13
+ export const ecdsaSign = (
14
+ msgHash: Parameters<typeof secp256k1.signSync>[0],
15
+ privKey: Parameters<typeof secp256k1.signSync>[1],
16
+ ) => secp256k1.signSync(msgHash, privKey, {der: false, recovered: true});
17
+ export const isValidPrivateKey = secp256k1.utils.isValidPrivateKey;
18
+ export const publicKeyCreate = secp256k1.getPublicKey;
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  import * as Layout from './layout';
10
10
  import * as shortvec from './utils/shortvec-encoding';
11
- import {PublicKey} from './publickey';
11
+ import {PublicKey, PUBLIC_KEY_LENGTH} from './publickey';
12
12
 
13
13
  export const VALIDATOR_INFO_KEY = new PublicKey(
14
14
  'Va1idator1nfo111111111111111111111111111111',
@@ -77,16 +77,14 @@ export class ValidatorInfo {
77
77
  static fromConfigData(
78
78
  buffer: Buffer | Uint8Array | Array<number>,
79
79
  ): ValidatorInfo | null {
80
- const PUBKEY_LENGTH = 32;
81
-
82
80
  let byteArray = [...buffer];
83
81
  const configKeyCount = shortvec.decodeLength(byteArray);
84
82
  if (configKeyCount !== 2) return null;
85
83
 
86
84
  const configKeys: Array<ConfigKey> = [];
87
85
  for (let i = 0; i < 2; i++) {
88
- const publicKey = new PublicKey(byteArray.slice(0, PUBKEY_LENGTH));
89
- byteArray = byteArray.slice(PUBKEY_LENGTH);
86
+ const publicKey = new PublicKey(byteArray.slice(0, PUBLIC_KEY_LENGTH));
87
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
90
88
  const isSigner = byteArray.slice(0, 1)[0] === 1;
91
89
  byteArray = byteArray.slice(1);
92
90
  configKeys.push({publicKey, isSigner});
@@ -1,2 +0,0 @@
1
- export {default} from 'react-native-url-polyfill';
2
- export * from 'react-native-url-polyfill';
@@ -1,2 +0,0 @@
1
- export const URL = globalThis.URL;
2
- export const URLSearchParams = globalThis.URLSearchParams;