@solana/web3.js 0.0.0-next

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 (53) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +158 -0
  3. package/lib/index.browser.cjs.js +10062 -0
  4. package/lib/index.browser.cjs.js.map +1 -0
  5. package/lib/index.browser.esm.js +9976 -0
  6. package/lib/index.browser.esm.js.map +1 -0
  7. package/lib/index.cjs.js +9568 -0
  8. package/lib/index.cjs.js.map +1 -0
  9. package/lib/index.d.ts +3311 -0
  10. package/lib/index.esm.js +9479 -0
  11. package/lib/index.esm.js.map +1 -0
  12. package/lib/index.iife.js +30136 -0
  13. package/lib/index.iife.js.map +1 -0
  14. package/lib/index.iife.min.js +40 -0
  15. package/lib/index.iife.min.js.map +1 -0
  16. package/package.json +140 -0
  17. package/src/account.ts +46 -0
  18. package/src/agent-manager.ts +44 -0
  19. package/src/blockhash.ts +4 -0
  20. package/src/bpf-loader-deprecated.ts +5 -0
  21. package/src/bpf-loader.ts +45 -0
  22. package/src/connection.ts +4935 -0
  23. package/src/ed25519-program.ts +157 -0
  24. package/src/epoch-schedule.ts +102 -0
  25. package/src/errors.ts +9 -0
  26. package/src/fee-calculator.ts +16 -0
  27. package/src/index.ts +31 -0
  28. package/src/instruction.ts +58 -0
  29. package/src/keypair.ts +98 -0
  30. package/src/layout.ts +147 -0
  31. package/src/loader.ts +236 -0
  32. package/src/message.ts +271 -0
  33. package/src/nonce-account.ts +78 -0
  34. package/src/publickey.ts +296 -0
  35. package/src/secp256k1-program.ts +229 -0
  36. package/src/stake-program.ts +923 -0
  37. package/src/system-program.ts +1007 -0
  38. package/src/sysvar.ts +37 -0
  39. package/src/timing.ts +23 -0
  40. package/src/transaction.ts +808 -0
  41. package/src/util/assert.ts +8 -0
  42. package/src/util/borsh-schema.ts +38 -0
  43. package/src/util/cluster.ts +31 -0
  44. package/src/util/promise-timeout.ts +14 -0
  45. package/src/util/send-and-confirm-raw-transaction.ts +46 -0
  46. package/src/util/send-and-confirm-transaction.ts +50 -0
  47. package/src/util/shortvec-encoding.ts +28 -0
  48. package/src/util/sleep.ts +4 -0
  49. package/src/util/to-buffer.ts +11 -0
  50. package/src/util/url.ts +18 -0
  51. package/src/validator-info.ts +106 -0
  52. package/src/vote-account.ts +236 -0
  53. package/src/vote-program.ts +413 -0
@@ -0,0 +1,296 @@
1
+ import BN from 'bn.js';
2
+ import bs58 from 'bs58';
3
+ import {Buffer} from 'buffer';
4
+ import nacl from 'tweetnacl';
5
+ import {sha256} from '@ethersproject/sha2';
6
+
7
+ import {Struct, SOLANA_SCHEMA} from './util/borsh-schema';
8
+ import {toBuffer} from './util/to-buffer';
9
+
10
+ /**
11
+ * Maximum length of derived pubkey seed
12
+ */
13
+ export const MAX_SEED_LENGTH = 32;
14
+
15
+ /**
16
+ * Value to be converted into public key
17
+ */
18
+ export type PublicKeyInitData =
19
+ | number
20
+ | string
21
+ | Buffer
22
+ | Uint8Array
23
+ | Array<number>
24
+ | PublicKeyData;
25
+
26
+ /**
27
+ * JSON object representation of PublicKey class
28
+ */
29
+ export type PublicKeyData = {
30
+ /** @internal */
31
+ _bn: BN;
32
+ };
33
+
34
+ function isPublicKeyData(value: PublicKeyInitData): value is PublicKeyData {
35
+ return (value as PublicKeyData)._bn !== undefined;
36
+ }
37
+
38
+ /**
39
+ * A public key
40
+ */
41
+ export class PublicKey extends Struct {
42
+ /** @internal */
43
+ _bn: BN;
44
+
45
+ /**
46
+ * Create a new PublicKey object
47
+ * @param value ed25519 public key as buffer or base-58 encoded string
48
+ */
49
+ constructor(value: PublicKeyInitData) {
50
+ super({});
51
+ if (isPublicKeyData(value)) {
52
+ this._bn = value._bn;
53
+ } else {
54
+ if (typeof value === 'string') {
55
+ // assume base 58 encoding by default
56
+ const decoded = bs58.decode(value);
57
+ if (decoded.length != 32) {
58
+ throw new Error(`Invalid public key input`);
59
+ }
60
+ this._bn = new BN(decoded);
61
+ } else {
62
+ this._bn = new BN(value);
63
+ }
64
+
65
+ if (this._bn.byteLength() > 32) {
66
+ throw new Error(`Invalid public key input`);
67
+ }
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Default public key value. (All zeros)
73
+ */
74
+ static default: PublicKey = new PublicKey('11111111111111111111111111111111');
75
+
76
+ /**
77
+ * Checks if two publicKeys are equal
78
+ */
79
+ equals(publicKey: PublicKey): boolean {
80
+ return this._bn.eq(publicKey._bn);
81
+ }
82
+
83
+ /**
84
+ * Return the base-58 representation of the public key
85
+ */
86
+ toBase58(): string {
87
+ return bs58.encode(this.toBytes());
88
+ }
89
+
90
+ toJSON(): string {
91
+ return this.toBase58();
92
+ }
93
+
94
+ /**
95
+ * Return the byte array representation of the public key
96
+ */
97
+ toBytes(): Uint8Array {
98
+ return this.toBuffer();
99
+ }
100
+
101
+ /**
102
+ * Return the Buffer representation of the public key
103
+ */
104
+ toBuffer(): Buffer {
105
+ const b = this._bn.toArrayLike(Buffer);
106
+ if (b.length === 32) {
107
+ return b;
108
+ }
109
+
110
+ const zeroPad = Buffer.alloc(32);
111
+ b.copy(zeroPad, 32 - b.length);
112
+ return zeroPad;
113
+ }
114
+
115
+ /**
116
+ * Return the base-58 representation of the public key
117
+ */
118
+ toString(): string {
119
+ return this.toBase58();
120
+ }
121
+
122
+ /**
123
+ * Derive a public key from another key, a seed, and a program ID.
124
+ * The program ID will also serve as the owner of the public key, giving
125
+ * it permission to write data to the account.
126
+ */
127
+ /* eslint-disable require-await */
128
+ static async createWithSeed(
129
+ fromPublicKey: PublicKey,
130
+ seed: string,
131
+ programId: PublicKey,
132
+ ): Promise<PublicKey> {
133
+ const buffer = Buffer.concat([
134
+ fromPublicKey.toBuffer(),
135
+ Buffer.from(seed),
136
+ programId.toBuffer(),
137
+ ]);
138
+ const hash = sha256(new Uint8Array(buffer)).slice(2);
139
+ return new PublicKey(Buffer.from(hash, 'hex'));
140
+ }
141
+
142
+ /**
143
+ * Derive a program address from seeds and a program ID.
144
+ */
145
+ /* eslint-disable require-await */
146
+ static createProgramAddressSync(
147
+ seeds: Array<Buffer | Uint8Array>,
148
+ programId: PublicKey,
149
+ ): PublicKey {
150
+ let buffer = Buffer.alloc(0);
151
+ seeds.forEach(function (seed) {
152
+ if (seed.length > MAX_SEED_LENGTH) {
153
+ throw new TypeError(`Max seed length exceeded`);
154
+ }
155
+ buffer = Buffer.concat([buffer, toBuffer(seed)]);
156
+ });
157
+ buffer = Buffer.concat([
158
+ buffer,
159
+ programId.toBuffer(),
160
+ Buffer.from('ProgramDerivedAddress'),
161
+ ]);
162
+ let hash = sha256(new Uint8Array(buffer)).slice(2);
163
+ let publicKeyBytes = new BN(hash, 16).toArray(undefined, 32);
164
+ if (is_on_curve(publicKeyBytes)) {
165
+ throw new Error(`Invalid seeds, address must fall off the curve`);
166
+ }
167
+ return new PublicKey(publicKeyBytes);
168
+ }
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
+
182
+ /**
183
+ * Find a valid program address
184
+ *
185
+ * Valid program addresses must fall off the ed25519 curve. This function
186
+ * iterates a nonce until it finds one that when combined with the seeds
187
+ * results in a valid program address.
188
+ */
189
+ static findProgramAddressSync(
190
+ seeds: Array<Buffer | Uint8Array>,
191
+ programId: PublicKey,
192
+ ): [PublicKey, number] {
193
+ let nonce = 255;
194
+ let address;
195
+ while (nonce != 0) {
196
+ try {
197
+ const seedsWithNonce = seeds.concat(Buffer.from([nonce]));
198
+ address = this.createProgramAddressSync(seedsWithNonce, programId);
199
+ } catch (err) {
200
+ if (err instanceof TypeError) {
201
+ throw err;
202
+ }
203
+ nonce--;
204
+ continue;
205
+ }
206
+ return [address, nonce];
207
+ }
208
+ throw new Error(`Unable to find a viable program address nonce`);
209
+ }
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
+
222
+ /**
223
+ * Check that a pubkey is on the ed25519 curve.
224
+ */
225
+ static isOnCurve(pubkey: Uint8Array): boolean {
226
+ return is_on_curve(pubkey) == 1;
227
+ }
228
+ }
229
+
230
+ SOLANA_SCHEMA.set(PublicKey, {
231
+ kind: 'struct',
232
+ fields: [['_bn', 'u256']],
233
+ });
234
+
235
+ // @ts-ignore
236
+ let naclLowLevel = nacl.lowlevel;
237
+
238
+ // Check that a pubkey is on the curve.
239
+ // This function and its dependents were sourced from:
240
+ // https://github.com/dchest/tweetnacl-js/blob/f1ec050ceae0861f34280e62498b1d3ed9c350c6/nacl.js#L792
241
+ function is_on_curve(p: any) {
242
+ var r = [
243
+ naclLowLevel.gf(),
244
+ naclLowLevel.gf(),
245
+ naclLowLevel.gf(),
246
+ naclLowLevel.gf(),
247
+ ];
248
+
249
+ var t = naclLowLevel.gf(),
250
+ chk = naclLowLevel.gf(),
251
+ num = naclLowLevel.gf(),
252
+ den = naclLowLevel.gf(),
253
+ den2 = naclLowLevel.gf(),
254
+ den4 = naclLowLevel.gf(),
255
+ den6 = naclLowLevel.gf();
256
+
257
+ naclLowLevel.set25519(r[2], gf1);
258
+ naclLowLevel.unpack25519(r[1], p);
259
+ naclLowLevel.S(num, r[1]);
260
+ naclLowLevel.M(den, num, naclLowLevel.D);
261
+ naclLowLevel.Z(num, num, r[2]);
262
+ naclLowLevel.A(den, r[2], den);
263
+
264
+ naclLowLevel.S(den2, den);
265
+ naclLowLevel.S(den4, den2);
266
+ naclLowLevel.M(den6, den4, den2);
267
+ naclLowLevel.M(t, den6, num);
268
+ naclLowLevel.M(t, t, den);
269
+
270
+ naclLowLevel.pow2523(t, t);
271
+ naclLowLevel.M(t, t, num);
272
+ naclLowLevel.M(t, t, den);
273
+ naclLowLevel.M(t, t, den);
274
+ naclLowLevel.M(r[0], t, den);
275
+
276
+ naclLowLevel.S(chk, r[0]);
277
+ naclLowLevel.M(chk, chk, den);
278
+ if (neq25519(chk, num)) naclLowLevel.M(r[0], r[0], I);
279
+
280
+ naclLowLevel.S(chk, r[0]);
281
+ naclLowLevel.M(chk, chk, den);
282
+ if (neq25519(chk, num)) return 0;
283
+ return 1;
284
+ }
285
+ let gf1 = naclLowLevel.gf([1]);
286
+ let I = naclLowLevel.gf([
287
+ 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7,
288
+ 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83,
289
+ ]);
290
+ function neq25519(a: any, b: any) {
291
+ var c = new Uint8Array(32),
292
+ d = new Uint8Array(32);
293
+ naclLowLevel.pack25519(c, a);
294
+ naclLowLevel.pack25519(d, b);
295
+ return naclLowLevel.crypto_verify_32(c, 0, d, 0);
296
+ }
@@ -0,0 +1,229 @@
1
+ import {Buffer} from 'buffer';
2
+ import * as BufferLayout from '@solana/buffer-layout';
3
+ import secp256k1 from 'secp256k1';
4
+ import sha3 from 'js-sha3';
5
+
6
+ import {PublicKey} from './publickey';
7
+ import {TransactionInstruction} from './transaction';
8
+ import assert from './util/assert';
9
+ import {toBuffer} from './util/to-buffer';
10
+
11
+ const {publicKeyCreate, ecdsaSign} = secp256k1;
12
+
13
+ const PRIVATE_KEY_BYTES = 32;
14
+ const ETHEREUM_ADDRESS_BYTES = 20;
15
+ const PUBLIC_KEY_BYTES = 64;
16
+ const SIGNATURE_OFFSETS_SERIALIZED_SIZE = 11;
17
+
18
+ /**
19
+ * Params for creating an secp256k1 instruction using a public key
20
+ */
21
+ export type CreateSecp256k1InstructionWithPublicKeyParams = {
22
+ publicKey: Buffer | Uint8Array | Array<number>;
23
+ message: Buffer | Uint8Array | Array<number>;
24
+ signature: Buffer | Uint8Array | Array<number>;
25
+ recoveryId: number;
26
+ instructionIndex?: number;
27
+ };
28
+
29
+ /**
30
+ * Params for creating an secp256k1 instruction using an Ethereum address
31
+ */
32
+ export type CreateSecp256k1InstructionWithEthAddressParams = {
33
+ ethAddress: Buffer | Uint8Array | Array<number> | string;
34
+ message: Buffer | Uint8Array | Array<number>;
35
+ signature: Buffer | Uint8Array | Array<number>;
36
+ recoveryId: number;
37
+ instructionIndex?: number;
38
+ };
39
+
40
+ /**
41
+ * Params for creating an secp256k1 instruction using a private key
42
+ */
43
+ export type CreateSecp256k1InstructionWithPrivateKeyParams = {
44
+ privateKey: Buffer | Uint8Array | Array<number>;
45
+ message: Buffer | Uint8Array | Array<number>;
46
+ instructionIndex?: number;
47
+ };
48
+
49
+ const SECP256K1_INSTRUCTION_LAYOUT = BufferLayout.struct<
50
+ Readonly<{
51
+ ethAddress: Uint8Array;
52
+ ethAddressInstructionIndex: number;
53
+ ethAddressOffset: number;
54
+ messageDataOffset: number;
55
+ messageDataSize: number;
56
+ messageInstructionIndex: number;
57
+ numSignatures: number;
58
+ recoveryId: number;
59
+ signature: Uint8Array;
60
+ signatureInstructionIndex: number;
61
+ signatureOffset: number;
62
+ }>
63
+ >([
64
+ BufferLayout.u8('numSignatures'),
65
+ BufferLayout.u16('signatureOffset'),
66
+ BufferLayout.u8('signatureInstructionIndex'),
67
+ BufferLayout.u16('ethAddressOffset'),
68
+ BufferLayout.u8('ethAddressInstructionIndex'),
69
+ BufferLayout.u16('messageDataOffset'),
70
+ BufferLayout.u16('messageDataSize'),
71
+ BufferLayout.u8('messageInstructionIndex'),
72
+ BufferLayout.blob(20, 'ethAddress'),
73
+ BufferLayout.blob(64, 'signature'),
74
+ BufferLayout.u8('recoveryId'),
75
+ ]);
76
+
77
+ export class Secp256k1Program {
78
+ /**
79
+ * @internal
80
+ */
81
+ constructor() {}
82
+
83
+ /**
84
+ * Public key that identifies the secp256k1 program
85
+ */
86
+ static programId: PublicKey = new PublicKey(
87
+ 'KeccakSecp256k11111111111111111111111111111',
88
+ );
89
+
90
+ /**
91
+ * Construct an Ethereum address from a secp256k1 public key buffer.
92
+ * @param {Buffer} publicKey a 64 byte secp256k1 public key buffer
93
+ */
94
+ static publicKeyToEthAddress(
95
+ publicKey: Buffer | Uint8Array | Array<number>,
96
+ ): Buffer {
97
+ assert(
98
+ publicKey.length === PUBLIC_KEY_BYTES,
99
+ `Public key must be ${PUBLIC_KEY_BYTES} bytes but received ${publicKey.length} bytes`,
100
+ );
101
+
102
+ try {
103
+ return Buffer.from(
104
+ sha3.keccak_256.update(toBuffer(publicKey)).digest(),
105
+ ).slice(-ETHEREUM_ADDRESS_BYTES);
106
+ } catch (error) {
107
+ throw new Error(`Error constructing Ethereum address: ${error}`);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Create an secp256k1 instruction with a public key. The public key
113
+ * must be a buffer that is 64 bytes long.
114
+ */
115
+ static createInstructionWithPublicKey(
116
+ params: CreateSecp256k1InstructionWithPublicKeyParams,
117
+ ): TransactionInstruction {
118
+ const {publicKey, message, signature, recoveryId, instructionIndex} =
119
+ params;
120
+ return Secp256k1Program.createInstructionWithEthAddress({
121
+ ethAddress: Secp256k1Program.publicKeyToEthAddress(publicKey),
122
+ message,
123
+ signature,
124
+ recoveryId,
125
+ instructionIndex,
126
+ });
127
+ }
128
+
129
+ /**
130
+ * Create an secp256k1 instruction with an Ethereum address. The address
131
+ * must be a hex string or a buffer that is 20 bytes long.
132
+ */
133
+ static createInstructionWithEthAddress(
134
+ params: CreateSecp256k1InstructionWithEthAddressParams,
135
+ ): TransactionInstruction {
136
+ const {
137
+ ethAddress: rawAddress,
138
+ message,
139
+ signature,
140
+ recoveryId,
141
+ instructionIndex = 0,
142
+ } = params;
143
+
144
+ let ethAddress;
145
+ if (typeof rawAddress === 'string') {
146
+ if (rawAddress.startsWith('0x')) {
147
+ ethAddress = Buffer.from(rawAddress.substr(2), 'hex');
148
+ } else {
149
+ ethAddress = Buffer.from(rawAddress, 'hex');
150
+ }
151
+ } else {
152
+ ethAddress = rawAddress;
153
+ }
154
+
155
+ assert(
156
+ ethAddress.length === ETHEREUM_ADDRESS_BYTES,
157
+ `Address must be ${ETHEREUM_ADDRESS_BYTES} bytes but received ${ethAddress.length} bytes`,
158
+ );
159
+
160
+ const dataStart = 1 + SIGNATURE_OFFSETS_SERIALIZED_SIZE;
161
+ const ethAddressOffset = dataStart;
162
+ const signatureOffset = dataStart + ethAddress.length;
163
+ const messageDataOffset = signatureOffset + signature.length + 1;
164
+ const numSignatures = 1;
165
+
166
+ const instructionData = Buffer.alloc(
167
+ SECP256K1_INSTRUCTION_LAYOUT.span + message.length,
168
+ );
169
+
170
+ SECP256K1_INSTRUCTION_LAYOUT.encode(
171
+ {
172
+ numSignatures,
173
+ signatureOffset,
174
+ signatureInstructionIndex: instructionIndex,
175
+ ethAddressOffset,
176
+ ethAddressInstructionIndex: instructionIndex,
177
+ messageDataOffset,
178
+ messageDataSize: message.length,
179
+ messageInstructionIndex: instructionIndex,
180
+ signature: toBuffer(signature),
181
+ ethAddress: toBuffer(ethAddress),
182
+ recoveryId,
183
+ },
184
+ instructionData,
185
+ );
186
+
187
+ instructionData.fill(toBuffer(message), SECP256K1_INSTRUCTION_LAYOUT.span);
188
+
189
+ return new TransactionInstruction({
190
+ keys: [],
191
+ programId: Secp256k1Program.programId,
192
+ data: instructionData,
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Create an secp256k1 instruction with a private key. The private key
198
+ * must be a buffer that is 32 bytes long.
199
+ */
200
+ static createInstructionWithPrivateKey(
201
+ params: CreateSecp256k1InstructionWithPrivateKeyParams,
202
+ ): TransactionInstruction {
203
+ const {privateKey: pkey, message, instructionIndex} = params;
204
+
205
+ assert(
206
+ pkey.length === PRIVATE_KEY_BYTES,
207
+ `Private key must be ${PRIVATE_KEY_BYTES} bytes but received ${pkey.length} bytes`,
208
+ );
209
+
210
+ try {
211
+ const privateKey = toBuffer(pkey);
212
+ const publicKey = publicKeyCreate(privateKey, false).slice(1); // throw away leading byte
213
+ const messageHash = Buffer.from(
214
+ sha3.keccak_256.update(toBuffer(message)).digest(),
215
+ );
216
+ const {signature, recid: recoveryId} = ecdsaSign(messageHash, privateKey);
217
+
218
+ return this.createInstructionWithPublicKey({
219
+ publicKey,
220
+ message,
221
+ signature,
222
+ recoveryId,
223
+ instructionIndex,
224
+ });
225
+ } catch (error) {
226
+ throw new Error(`Error creating instruction; ${error}`);
227
+ }
228
+ }
229
+ }