@solana/web3.js 0.0.0-development → 0.0.0-pr-29130
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/README.md +18 -16
- package/lib/index.browser.cjs.js +1955 -1660
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +2058 -1770
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +4733 -1870
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +3451 -2821
- package/lib/index.esm.js +4761 -1909
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +5212 -5553
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +7 -14
- package/lib/index.iife.min.js.map +1 -1
- package/lib/index.native.js +1955 -1660
- package/lib/index.native.js.map +1 -1
- package/package.json +18 -21
- package/src/account.ts +19 -10
- package/src/bpf-loader.ts +2 -2
- package/src/connection.ts +1377 -185
- package/src/epoch-schedule.ts +1 -1
- package/src/keypair.ts +20 -25
- package/src/layout.ts +29 -0
- package/src/message/account-keys.ts +79 -0
- package/src/message/compiled-keys.ts +165 -0
- package/src/message/index.ts +21 -6
- package/src/message/legacy.ts +103 -16
- package/src/message/v0.ts +496 -0
- package/src/message/versioned.ts +36 -0
- package/src/nonce-account.ts +7 -3
- package/src/programs/address-lookup-table/state.ts +1 -1
- package/src/programs/compute-budget.ts +3 -0
- package/src/programs/ed25519.ts +2 -2
- package/src/programs/secp256k1.ts +5 -7
- package/src/programs/vote.ts +109 -2
- package/src/publickey.ts +25 -73
- package/src/transaction/constants.ts +2 -0
- package/src/transaction/expiry-custom-errors.ts +13 -0
- package/src/transaction/index.ts +2 -0
- package/src/transaction/legacy.ts +46 -9
- package/src/transaction/message.ts +140 -0
- package/src/transaction/versioned.ts +126 -0
- package/src/utils/ed25519.ts +46 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/send-and-confirm-raw-transaction.ts +13 -0
- package/src/utils/send-and-confirm-transaction.ts +53 -19
- package/src/agent-manager.ts +0 -44
package/lib/index.browser.esm.js
CHANGED
|
@@ -1,15 +1,53 @@
|
|
|
1
|
-
import nacl from 'tweetnacl';
|
|
2
1
|
import { Buffer } from 'buffer';
|
|
2
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
3
|
+
import * as ed25519 from '@noble/ed25519';
|
|
3
4
|
import BN from 'bn.js';
|
|
4
5
|
import bs58 from 'bs58';
|
|
6
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
5
7
|
import { serialize, deserialize, deserializeUnchecked } from 'borsh';
|
|
6
8
|
import * as BufferLayout from '@solana/buffer-layout';
|
|
7
9
|
import { blob } from '@solana/buffer-layout';
|
|
8
10
|
import { toBigIntLE, toBufferLE } from 'bigint-buffer';
|
|
9
|
-
import { coerce, instance, string, tuple, literal, unknown, union, type, optional, any, number
|
|
11
|
+
import { coerce, instance, string, tuple, literal, unknown, union, type, optional, any, number, array, nullable, create, boolean, record, assert as assert$1 } from 'superstruct';
|
|
10
12
|
import { Client } from 'rpc-websockets';
|
|
11
13
|
import RpcClient from 'jayson/lib/client/browser';
|
|
12
|
-
import
|
|
14
|
+
import { keccak_256 } from '@noble/hashes/sha3';
|
|
15
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
16
|
+
import * as secp256k1 from '@noble/secp256k1';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A 64 byte secret key, the first 32 bytes of which is the
|
|
20
|
+
* private scalar and the last 32 bytes is the public key.
|
|
21
|
+
* Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
ed25519.utils.sha512Sync = (...m) => sha512(ed25519.utils.concatBytes(...m));
|
|
25
|
+
|
|
26
|
+
const generatePrivateKey = ed25519.utils.randomPrivateKey;
|
|
27
|
+
const generateKeypair = () => {
|
|
28
|
+
const privateScalar = ed25519.utils.randomPrivateKey();
|
|
29
|
+
const publicKey = getPublicKey(privateScalar);
|
|
30
|
+
const secretKey = new Uint8Array(64);
|
|
31
|
+
secretKey.set(privateScalar);
|
|
32
|
+
secretKey.set(publicKey, 32);
|
|
33
|
+
return {
|
|
34
|
+
publicKey,
|
|
35
|
+
secretKey
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const getPublicKey = ed25519.sync.getPublicKey;
|
|
39
|
+
function isOnCurve(publicKey) {
|
|
40
|
+
try {
|
|
41
|
+
ed25519.Point.fromHex(publicKey, true
|
|
42
|
+
/* strict */
|
|
43
|
+
);
|
|
44
|
+
return true;
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const sign = (message, secretKey) => ed25519.sync.sign(message, secretKey.slice(0, 32));
|
|
50
|
+
const verify = ed25519.sync.verify;
|
|
13
51
|
|
|
14
52
|
const toBuffer = arr => {
|
|
15
53
|
if (Buffer.isBuffer(arr)) {
|
|
@@ -21,298 +59,6 @@ const toBuffer = arr => {
|
|
|
21
59
|
}
|
|
22
60
|
};
|
|
23
61
|
|
|
24
|
-
function number(n) {
|
|
25
|
-
if (!Number.isSafeInteger(n) || n < 0)
|
|
26
|
-
throw new Error(`Wrong positive integer: ${n}`);
|
|
27
|
-
}
|
|
28
|
-
function bool(b) {
|
|
29
|
-
if (typeof b !== 'boolean')
|
|
30
|
-
throw new Error(`Expected boolean, not ${b}`);
|
|
31
|
-
}
|
|
32
|
-
function bytes(b, ...lengths) {
|
|
33
|
-
if (!(b instanceof Uint8Array))
|
|
34
|
-
throw new TypeError('Expected Uint8Array');
|
|
35
|
-
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
36
|
-
throw new TypeError(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
|
|
37
|
-
}
|
|
38
|
-
function hash(hash) {
|
|
39
|
-
if (typeof hash !== 'function' || typeof hash.create !== 'function')
|
|
40
|
-
throw new Error('Hash should be wrapped by utils.wrapConstructor');
|
|
41
|
-
number(hash.outputLen);
|
|
42
|
-
number(hash.blockLen);
|
|
43
|
-
}
|
|
44
|
-
function exists(instance, checkFinished = true) {
|
|
45
|
-
if (instance.destroyed)
|
|
46
|
-
throw new Error('Hash instance has been destroyed');
|
|
47
|
-
if (checkFinished && instance.finished)
|
|
48
|
-
throw new Error('Hash#digest() has already been called');
|
|
49
|
-
}
|
|
50
|
-
function output(out, instance) {
|
|
51
|
-
bytes(out);
|
|
52
|
-
const min = instance.outputLen;
|
|
53
|
-
if (out.length < min) {
|
|
54
|
-
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const assert$1 = {
|
|
58
|
-
number,
|
|
59
|
-
bool,
|
|
60
|
-
bytes,
|
|
61
|
-
hash,
|
|
62
|
-
exists,
|
|
63
|
-
output,
|
|
64
|
-
};
|
|
65
|
-
var assert$2 = assert$1;
|
|
66
|
-
|
|
67
|
-
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
68
|
-
// Cast array to view
|
|
69
|
-
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
70
|
-
// The rotate right (circular right shift) operation for uint32
|
|
71
|
-
const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
|
|
72
|
-
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
|
|
73
|
-
// There is almost no big endian hardware, but js typed arrays uses platform specific endianness.
|
|
74
|
-
// So, just to be sure not to corrupt anything.
|
|
75
|
-
if (!isLE)
|
|
76
|
-
throw new Error('Non little-endian hardware is not supported');
|
|
77
|
-
Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
|
78
|
-
function utf8ToBytes(str) {
|
|
79
|
-
if (typeof str !== 'string') {
|
|
80
|
-
throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);
|
|
81
|
-
}
|
|
82
|
-
return new TextEncoder().encode(str);
|
|
83
|
-
}
|
|
84
|
-
function toBytes(data) {
|
|
85
|
-
if (typeof data === 'string')
|
|
86
|
-
data = utf8ToBytes(data);
|
|
87
|
-
if (!(data instanceof Uint8Array))
|
|
88
|
-
throw new TypeError(`Expected input type is Uint8Array (got ${typeof data})`);
|
|
89
|
-
return data;
|
|
90
|
-
}
|
|
91
|
-
// For runtime check if class implements interface
|
|
92
|
-
class Hash {
|
|
93
|
-
// Safe version that clones internal state
|
|
94
|
-
clone() {
|
|
95
|
-
return this._cloneInto();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function wrapConstructor(hashConstructor) {
|
|
99
|
-
const hashC = (message) => hashConstructor().update(toBytes(message)).digest();
|
|
100
|
-
const tmp = hashConstructor();
|
|
101
|
-
hashC.outputLen = tmp.outputLen;
|
|
102
|
-
hashC.blockLen = tmp.blockLen;
|
|
103
|
-
hashC.create = () => hashConstructor();
|
|
104
|
-
return hashC;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Polyfill for Safari 14
|
|
108
|
-
function setBigUint64(view, byteOffset, value, isLE) {
|
|
109
|
-
if (typeof view.setBigUint64 === 'function')
|
|
110
|
-
return view.setBigUint64(byteOffset, value, isLE);
|
|
111
|
-
const _32n = BigInt(32);
|
|
112
|
-
const _u32_max = BigInt(0xffffffff);
|
|
113
|
-
const wh = Number((value >> _32n) & _u32_max);
|
|
114
|
-
const wl = Number(value & _u32_max);
|
|
115
|
-
const h = isLE ? 4 : 0;
|
|
116
|
-
const l = isLE ? 0 : 4;
|
|
117
|
-
view.setUint32(byteOffset + h, wh, isLE);
|
|
118
|
-
view.setUint32(byteOffset + l, wl, isLE);
|
|
119
|
-
}
|
|
120
|
-
// Base SHA2 class (RFC 6234)
|
|
121
|
-
class SHA2 extends Hash {
|
|
122
|
-
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
123
|
-
super();
|
|
124
|
-
this.blockLen = blockLen;
|
|
125
|
-
this.outputLen = outputLen;
|
|
126
|
-
this.padOffset = padOffset;
|
|
127
|
-
this.isLE = isLE;
|
|
128
|
-
this.finished = false;
|
|
129
|
-
this.length = 0;
|
|
130
|
-
this.pos = 0;
|
|
131
|
-
this.destroyed = false;
|
|
132
|
-
this.buffer = new Uint8Array(blockLen);
|
|
133
|
-
this.view = createView(this.buffer);
|
|
134
|
-
}
|
|
135
|
-
update(data) {
|
|
136
|
-
assert$2.exists(this);
|
|
137
|
-
const { view, buffer, blockLen } = this;
|
|
138
|
-
data = toBytes(data);
|
|
139
|
-
const len = data.length;
|
|
140
|
-
for (let pos = 0; pos < len;) {
|
|
141
|
-
const take = Math.min(blockLen - this.pos, len - pos);
|
|
142
|
-
// Fast path: we have at least one block in input, cast it to view and process
|
|
143
|
-
if (take === blockLen) {
|
|
144
|
-
const dataView = createView(data);
|
|
145
|
-
for (; blockLen <= len - pos; pos += blockLen)
|
|
146
|
-
this.process(dataView, pos);
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
150
|
-
this.pos += take;
|
|
151
|
-
pos += take;
|
|
152
|
-
if (this.pos === blockLen) {
|
|
153
|
-
this.process(view, 0);
|
|
154
|
-
this.pos = 0;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
this.length += data.length;
|
|
158
|
-
this.roundClean();
|
|
159
|
-
return this;
|
|
160
|
-
}
|
|
161
|
-
digestInto(out) {
|
|
162
|
-
assert$2.exists(this);
|
|
163
|
-
assert$2.output(out, this);
|
|
164
|
-
this.finished = true;
|
|
165
|
-
// Padding
|
|
166
|
-
// We can avoid allocation of buffer for padding completely if it
|
|
167
|
-
// was previously not allocated here. But it won't change performance.
|
|
168
|
-
const { buffer, view, blockLen, isLE } = this;
|
|
169
|
-
let { pos } = this;
|
|
170
|
-
// append the bit '1' to the message
|
|
171
|
-
buffer[pos++] = 0b10000000;
|
|
172
|
-
this.buffer.subarray(pos).fill(0);
|
|
173
|
-
// we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
|
|
174
|
-
if (this.padOffset > blockLen - pos) {
|
|
175
|
-
this.process(view, 0);
|
|
176
|
-
pos = 0;
|
|
177
|
-
}
|
|
178
|
-
// Pad until full block byte with zeros
|
|
179
|
-
for (let i = pos; i < blockLen; i++)
|
|
180
|
-
buffer[i] = 0;
|
|
181
|
-
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
|
|
182
|
-
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
|
|
183
|
-
// So we just write lowest 64 bits of that value.
|
|
184
|
-
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
|
|
185
|
-
this.process(view, 0);
|
|
186
|
-
const oview = createView(out);
|
|
187
|
-
this.get().forEach((v, i) => oview.setUint32(4 * i, v, isLE));
|
|
188
|
-
}
|
|
189
|
-
digest() {
|
|
190
|
-
const { buffer, outputLen } = this;
|
|
191
|
-
this.digestInto(buffer);
|
|
192
|
-
const res = buffer.slice(0, outputLen);
|
|
193
|
-
this.destroy();
|
|
194
|
-
return res;
|
|
195
|
-
}
|
|
196
|
-
_cloneInto(to) {
|
|
197
|
-
to || (to = new this.constructor());
|
|
198
|
-
to.set(...this.get());
|
|
199
|
-
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
200
|
-
to.length = length;
|
|
201
|
-
to.pos = pos;
|
|
202
|
-
to.finished = finished;
|
|
203
|
-
to.destroyed = destroyed;
|
|
204
|
-
if (length % blockLen)
|
|
205
|
-
to.buffer.set(buffer);
|
|
206
|
-
return to;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Choice: a ? b : c
|
|
211
|
-
const Chi = (a, b, c) => (a & b) ^ (~a & c);
|
|
212
|
-
// Majority function, true if any two inpust is true
|
|
213
|
-
const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
|
|
214
|
-
// Round constants:
|
|
215
|
-
// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
|
216
|
-
// prettier-ignore
|
|
217
|
-
const SHA256_K = new Uint32Array([
|
|
218
|
-
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
219
|
-
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
220
|
-
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
221
|
-
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
222
|
-
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
223
|
-
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
224
|
-
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
225
|
-
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
226
|
-
]);
|
|
227
|
-
// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
|
|
228
|
-
// prettier-ignore
|
|
229
|
-
const IV = new Uint32Array([
|
|
230
|
-
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
231
|
-
]);
|
|
232
|
-
// Temporary buffer, not used to store anything between runs
|
|
233
|
-
// Named this way because it matches specification.
|
|
234
|
-
const SHA256_W = new Uint32Array(64);
|
|
235
|
-
class SHA256 extends SHA2 {
|
|
236
|
-
constructor() {
|
|
237
|
-
super(64, 32, 8, false);
|
|
238
|
-
// We cannot use array here since array allows indexing by variable
|
|
239
|
-
// which means optimizer/compiler cannot use registers.
|
|
240
|
-
this.A = IV[0] | 0;
|
|
241
|
-
this.B = IV[1] | 0;
|
|
242
|
-
this.C = IV[2] | 0;
|
|
243
|
-
this.D = IV[3] | 0;
|
|
244
|
-
this.E = IV[4] | 0;
|
|
245
|
-
this.F = IV[5] | 0;
|
|
246
|
-
this.G = IV[6] | 0;
|
|
247
|
-
this.H = IV[7] | 0;
|
|
248
|
-
}
|
|
249
|
-
get() {
|
|
250
|
-
const { A, B, C, D, E, F, G, H } = this;
|
|
251
|
-
return [A, B, C, D, E, F, G, H];
|
|
252
|
-
}
|
|
253
|
-
// prettier-ignore
|
|
254
|
-
set(A, B, C, D, E, F, G, H) {
|
|
255
|
-
this.A = A | 0;
|
|
256
|
-
this.B = B | 0;
|
|
257
|
-
this.C = C | 0;
|
|
258
|
-
this.D = D | 0;
|
|
259
|
-
this.E = E | 0;
|
|
260
|
-
this.F = F | 0;
|
|
261
|
-
this.G = G | 0;
|
|
262
|
-
this.H = H | 0;
|
|
263
|
-
}
|
|
264
|
-
process(view, offset) {
|
|
265
|
-
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
|
|
266
|
-
for (let i = 0; i < 16; i++, offset += 4)
|
|
267
|
-
SHA256_W[i] = view.getUint32(offset, false);
|
|
268
|
-
for (let i = 16; i < 64; i++) {
|
|
269
|
-
const W15 = SHA256_W[i - 15];
|
|
270
|
-
const W2 = SHA256_W[i - 2];
|
|
271
|
-
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
|
|
272
|
-
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
|
|
273
|
-
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
|
|
274
|
-
}
|
|
275
|
-
// Compression function main loop, 64 rounds
|
|
276
|
-
let { A, B, C, D, E, F, G, H } = this;
|
|
277
|
-
for (let i = 0; i < 64; i++) {
|
|
278
|
-
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
279
|
-
const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
|
|
280
|
-
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
281
|
-
const T2 = (sigma0 + Maj(A, B, C)) | 0;
|
|
282
|
-
H = G;
|
|
283
|
-
G = F;
|
|
284
|
-
F = E;
|
|
285
|
-
E = (D + T1) | 0;
|
|
286
|
-
D = C;
|
|
287
|
-
C = B;
|
|
288
|
-
B = A;
|
|
289
|
-
A = (T1 + T2) | 0;
|
|
290
|
-
}
|
|
291
|
-
// Add the compressed chunk to the current hash value
|
|
292
|
-
A = (A + this.A) | 0;
|
|
293
|
-
B = (B + this.B) | 0;
|
|
294
|
-
C = (C + this.C) | 0;
|
|
295
|
-
D = (D + this.D) | 0;
|
|
296
|
-
E = (E + this.E) | 0;
|
|
297
|
-
F = (F + this.F) | 0;
|
|
298
|
-
G = (G + this.G) | 0;
|
|
299
|
-
H = (H + this.H) | 0;
|
|
300
|
-
this.set(A, B, C, D, E, F, G, H);
|
|
301
|
-
}
|
|
302
|
-
roundClean() {
|
|
303
|
-
SHA256_W.fill(0);
|
|
304
|
-
}
|
|
305
|
-
destroy() {
|
|
306
|
-
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
307
|
-
this.buffer.fill(0);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* SHA2-256 hash function
|
|
312
|
-
* @param message - data that would be hashed
|
|
313
|
-
*/
|
|
314
|
-
const sha256 = wrapConstructor(() => new SHA256());
|
|
315
|
-
|
|
316
62
|
class Struct {
|
|
317
63
|
constructor(properties) {
|
|
318
64
|
Object.assign(this, properties);
|
|
@@ -366,12 +112,14 @@ const PUBLIC_KEY_LENGTH = 32;
|
|
|
366
112
|
|
|
367
113
|
function isPublicKeyData(value) {
|
|
368
114
|
return value._bn !== undefined;
|
|
369
|
-
}
|
|
115
|
+
} // local counter used by PublicKey.unique()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
let uniquePublicKeyCounter = 1;
|
|
370
119
|
/**
|
|
371
120
|
* A public key
|
|
372
121
|
*/
|
|
373
122
|
|
|
374
|
-
|
|
375
123
|
class PublicKey extends Struct {
|
|
376
124
|
/** @internal */
|
|
377
125
|
|
|
@@ -399,13 +147,24 @@ class PublicKey extends Struct {
|
|
|
399
147
|
this._bn = new BN(value);
|
|
400
148
|
}
|
|
401
149
|
|
|
402
|
-
if (this._bn.byteLength() >
|
|
150
|
+
if (this._bn.byteLength() > PUBLIC_KEY_LENGTH) {
|
|
403
151
|
throw new Error(`Invalid public key input`);
|
|
404
152
|
}
|
|
405
153
|
}
|
|
406
154
|
}
|
|
407
155
|
/**
|
|
408
|
-
*
|
|
156
|
+
* Returns a unique PublicKey for tests and benchmarks using a counter
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
static unique() {
|
|
161
|
+
const key = new PublicKey(uniquePublicKeyCounter);
|
|
162
|
+
uniquePublicKeyCounter += 1;
|
|
163
|
+
return new PublicKey(key.toBuffer());
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Default public key value. The base58-encoded string representation is all ones (as seen below)
|
|
167
|
+
* The underlying BN number is 32 bytes that are all zeros
|
|
409
168
|
*/
|
|
410
169
|
|
|
411
170
|
|
|
@@ -470,8 +229,8 @@ class PublicKey extends Struct {
|
|
|
470
229
|
|
|
471
230
|
static async createWithSeed(fromPublicKey, seed, programId) {
|
|
472
231
|
const buffer = Buffer.concat([fromPublicKey.toBuffer(), Buffer.from(seed), programId.toBuffer()]);
|
|
473
|
-
const
|
|
474
|
-
return new PublicKey(
|
|
232
|
+
const publicKeyBytes = sha256(buffer);
|
|
233
|
+
return new PublicKey(publicKeyBytes);
|
|
475
234
|
}
|
|
476
235
|
/**
|
|
477
236
|
* Derive a program address from seeds and a program ID.
|
|
@@ -490,10 +249,9 @@ class PublicKey extends Struct {
|
|
|
490
249
|
buffer = Buffer.concat([buffer, toBuffer(seed)]);
|
|
491
250
|
});
|
|
492
251
|
buffer = Buffer.concat([buffer, programId.toBuffer(), Buffer.from('ProgramDerivedAddress')]);
|
|
493
|
-
const
|
|
494
|
-
let publicKeyBytes = new BN(hash, 16).toArray(undefined, 32);
|
|
252
|
+
const publicKeyBytes = sha256(buffer);
|
|
495
253
|
|
|
496
|
-
if (
|
|
254
|
+
if (isOnCurve(publicKeyBytes)) {
|
|
497
255
|
throw new Error(`Invalid seeds, address must fall off the curve`);
|
|
498
256
|
}
|
|
499
257
|
|
|
@@ -502,6 +260,8 @@ class PublicKey extends Struct {
|
|
|
502
260
|
/**
|
|
503
261
|
* Async version of createProgramAddressSync
|
|
504
262
|
* For backwards compatibility
|
|
263
|
+
*
|
|
264
|
+
* @deprecated Use {@link createProgramAddressSync} instead
|
|
505
265
|
*/
|
|
506
266
|
|
|
507
267
|
/* eslint-disable require-await */
|
|
@@ -544,6 +304,8 @@ class PublicKey extends Struct {
|
|
|
544
304
|
/**
|
|
545
305
|
* Async version of findProgramAddressSync
|
|
546
306
|
* For backwards compatibility
|
|
307
|
+
*
|
|
308
|
+
* @deprecated Use {@link findProgramAddressSync} instead
|
|
547
309
|
*/
|
|
548
310
|
|
|
549
311
|
|
|
@@ -557,7 +319,7 @@ class PublicKey extends Struct {
|
|
|
557
319
|
|
|
558
320
|
static isOnCurve(pubkeyData) {
|
|
559
321
|
const pubkey = new PublicKey(pubkeyData);
|
|
560
|
-
return
|
|
322
|
+
return isOnCurve(pubkey.toBytes());
|
|
561
323
|
}
|
|
562
324
|
|
|
563
325
|
}
|
|
@@ -565,56 +327,7 @@ PublicKey.default = new PublicKey('11111111111111111111111111111111');
|
|
|
565
327
|
SOLANA_SCHEMA.set(PublicKey, {
|
|
566
328
|
kind: 'struct',
|
|
567
329
|
fields: [['_bn', 'u256']]
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
let naclLowLevel = nacl.lowlevel; // Check that a pubkey is on the curve.
|
|
571
|
-
// This function and its dependents were sourced from:
|
|
572
|
-
// https://github.com/dchest/tweetnacl-js/blob/f1ec050ceae0861f34280e62498b1d3ed9c350c6/nacl.js#L792
|
|
573
|
-
|
|
574
|
-
function is_on_curve(p) {
|
|
575
|
-
var r = [naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf()];
|
|
576
|
-
var t = naclLowLevel.gf(),
|
|
577
|
-
chk = naclLowLevel.gf(),
|
|
578
|
-
num = naclLowLevel.gf(),
|
|
579
|
-
den = naclLowLevel.gf(),
|
|
580
|
-
den2 = naclLowLevel.gf(),
|
|
581
|
-
den4 = naclLowLevel.gf(),
|
|
582
|
-
den6 = naclLowLevel.gf();
|
|
583
|
-
naclLowLevel.set25519(r[2], gf1);
|
|
584
|
-
naclLowLevel.unpack25519(r[1], p);
|
|
585
|
-
naclLowLevel.S(num, r[1]);
|
|
586
|
-
naclLowLevel.M(den, num, naclLowLevel.D);
|
|
587
|
-
naclLowLevel.Z(num, num, r[2]);
|
|
588
|
-
naclLowLevel.A(den, r[2], den);
|
|
589
|
-
naclLowLevel.S(den2, den);
|
|
590
|
-
naclLowLevel.S(den4, den2);
|
|
591
|
-
naclLowLevel.M(den6, den4, den2);
|
|
592
|
-
naclLowLevel.M(t, den6, num);
|
|
593
|
-
naclLowLevel.M(t, t, den);
|
|
594
|
-
naclLowLevel.pow2523(t, t);
|
|
595
|
-
naclLowLevel.M(t, t, num);
|
|
596
|
-
naclLowLevel.M(t, t, den);
|
|
597
|
-
naclLowLevel.M(t, t, den);
|
|
598
|
-
naclLowLevel.M(r[0], t, den);
|
|
599
|
-
naclLowLevel.S(chk, r[0]);
|
|
600
|
-
naclLowLevel.M(chk, chk, den);
|
|
601
|
-
if (neq25519(chk, num)) naclLowLevel.M(r[0], r[0], I);
|
|
602
|
-
naclLowLevel.S(chk, r[0]);
|
|
603
|
-
naclLowLevel.M(chk, chk, den);
|
|
604
|
-
if (neq25519(chk, num)) return 0;
|
|
605
|
-
return 1;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
let gf1 = naclLowLevel.gf([1]);
|
|
609
|
-
let I = naclLowLevel.gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
|
|
610
|
-
|
|
611
|
-
function neq25519(a, b) {
|
|
612
|
-
var c = new Uint8Array(32),
|
|
613
|
-
d = new Uint8Array(32);
|
|
614
|
-
naclLowLevel.pack25519(c, a);
|
|
615
|
-
naclLowLevel.pack25519(d, b);
|
|
616
|
-
return naclLowLevel.crypto_verify_32(c, 0, d, 0);
|
|
617
|
-
}
|
|
330
|
+
});
|
|
618
331
|
|
|
619
332
|
/**
|
|
620
333
|
* An account key pair (public and secret keys).
|
|
@@ -625,6 +338,8 @@ function neq25519(a, b) {
|
|
|
625
338
|
class Account {
|
|
626
339
|
/** @internal */
|
|
627
340
|
|
|
341
|
+
/** @internal */
|
|
342
|
+
|
|
628
343
|
/**
|
|
629
344
|
* Create a new Account object
|
|
630
345
|
*
|
|
@@ -634,12 +349,21 @@ class Account {
|
|
|
634
349
|
* @param secretKey Secret key for the account
|
|
635
350
|
*/
|
|
636
351
|
constructor(secretKey) {
|
|
637
|
-
this.
|
|
352
|
+
this._publicKey = void 0;
|
|
353
|
+
this._secretKey = void 0;
|
|
638
354
|
|
|
639
355
|
if (secretKey) {
|
|
640
|
-
|
|
356
|
+
const secretKeyBuffer = toBuffer(secretKey);
|
|
357
|
+
|
|
358
|
+
if (secretKey.length !== 64) {
|
|
359
|
+
throw new Error('bad secret key size');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
this._publicKey = secretKeyBuffer.slice(32, 64);
|
|
363
|
+
this._secretKey = secretKeyBuffer.slice(0, 32);
|
|
641
364
|
} else {
|
|
642
|
-
this.
|
|
365
|
+
this._secretKey = toBuffer(generatePrivateKey());
|
|
366
|
+
this._publicKey = toBuffer(getPublicKey(this._secretKey));
|
|
643
367
|
}
|
|
644
368
|
}
|
|
645
369
|
/**
|
|
@@ -648,15 +372,17 @@ class Account {
|
|
|
648
372
|
|
|
649
373
|
|
|
650
374
|
get publicKey() {
|
|
651
|
-
return new PublicKey(this.
|
|
375
|
+
return new PublicKey(this._publicKey);
|
|
652
376
|
}
|
|
653
377
|
/**
|
|
654
|
-
* The **unencrypted** secret key for this account
|
|
378
|
+
* The **unencrypted** secret key for this account. The first 32 bytes
|
|
379
|
+
* is the private scalar and the last 32 bytes is the public key.
|
|
380
|
+
* Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
|
|
655
381
|
*/
|
|
656
382
|
|
|
657
383
|
|
|
658
384
|
get secretKey() {
|
|
659
|
-
return
|
|
385
|
+
return Buffer.concat([this._secretKey, this._publicKey], 64);
|
|
660
386
|
}
|
|
661
387
|
|
|
662
388
|
}
|
|
@@ -671,6 +397,7 @@ const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader111111111111111
|
|
|
671
397
|
* 8 bytes is the size of the fragment header
|
|
672
398
|
*/
|
|
673
399
|
const PACKET_DATA_SIZE = 1280 - 40 - 8;
|
|
400
|
+
const VERSION_PREFIX_MASK = 0x7f;
|
|
674
401
|
const SIGNATURE_LENGTH_IN_BYTES = 64;
|
|
675
402
|
|
|
676
403
|
class TransactionExpiredBlockheightExceededError extends Error {
|
|
@@ -695,14 +422,96 @@ class TransactionExpiredTimeoutError extends Error {
|
|
|
695
422
|
Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', {
|
|
696
423
|
value: 'TransactionExpiredTimeoutError'
|
|
697
424
|
});
|
|
425
|
+
class TransactionExpiredNonceInvalidError extends Error {
|
|
426
|
+
constructor(signature) {
|
|
427
|
+
super(`Signature ${signature} has expired: the nonce is no longer valid.`);
|
|
428
|
+
this.signature = void 0;
|
|
429
|
+
this.signature = signature;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
}
|
|
433
|
+
Object.defineProperty(TransactionExpiredNonceInvalidError.prototype, 'name', {
|
|
434
|
+
value: 'TransactionExpiredNonceInvalidError'
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
class MessageAccountKeys {
|
|
438
|
+
constructor(staticAccountKeys, accountKeysFromLookups) {
|
|
439
|
+
this.staticAccountKeys = void 0;
|
|
440
|
+
this.accountKeysFromLookups = void 0;
|
|
441
|
+
this.staticAccountKeys = staticAccountKeys;
|
|
442
|
+
this.accountKeysFromLookups = accountKeysFromLookups;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
keySegments() {
|
|
446
|
+
const keySegments = [this.staticAccountKeys];
|
|
447
|
+
|
|
448
|
+
if (this.accountKeysFromLookups) {
|
|
449
|
+
keySegments.push(this.accountKeysFromLookups.writable);
|
|
450
|
+
keySegments.push(this.accountKeysFromLookups.readonly);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return keySegments;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
get(index) {
|
|
457
|
+
for (const keySegment of this.keySegments()) {
|
|
458
|
+
if (index < keySegment.length) {
|
|
459
|
+
return keySegment[index];
|
|
460
|
+
} else {
|
|
461
|
+
index -= keySegment.length;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
get length() {
|
|
469
|
+
return this.keySegments().flat().length;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
compileInstructions(instructions) {
|
|
473
|
+
// Bail early if any account indexes would overflow a u8
|
|
474
|
+
const U8_MAX = 255;
|
|
475
|
+
|
|
476
|
+
if (this.length > U8_MAX + 1) {
|
|
477
|
+
throw new Error('Account index overflow encountered during compilation');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const keyIndexMap = new Map();
|
|
481
|
+
this.keySegments().flat().forEach((key, index) => {
|
|
482
|
+
keyIndexMap.set(key.toBase58(), index);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
const findKeyIndex = key => {
|
|
486
|
+
const keyIndex = keyIndexMap.get(key.toBase58());
|
|
487
|
+
if (keyIndex === undefined) throw new Error('Encountered an unknown instruction account key during compilation');
|
|
488
|
+
return keyIndex;
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
return instructions.map(instruction => {
|
|
492
|
+
return {
|
|
493
|
+
programIdIndex: findKeyIndex(instruction.programId),
|
|
494
|
+
accountKeyIndexes: instruction.keys.map(meta => findKeyIndex(meta.pubkey)),
|
|
495
|
+
data: instruction.data
|
|
496
|
+
};
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
}
|
|
698
501
|
|
|
699
502
|
/**
|
|
700
503
|
* Layout for a public key
|
|
701
504
|
*/
|
|
702
|
-
|
|
703
505
|
const publicKey = (property = 'publicKey') => {
|
|
704
506
|
return BufferLayout.blob(32, property);
|
|
705
507
|
};
|
|
508
|
+
/**
|
|
509
|
+
* Layout for a signature
|
|
510
|
+
*/
|
|
511
|
+
|
|
512
|
+
const signature = (property = 'signature') => {
|
|
513
|
+
return BufferLayout.blob(64, property);
|
|
514
|
+
};
|
|
706
515
|
|
|
707
516
|
/**
|
|
708
517
|
* Layout for a Rust String type
|
|
@@ -756,6 +565,13 @@ const lockup = (property = 'lockup') => {
|
|
|
756
565
|
const voteInit = (property = 'voteInit') => {
|
|
757
566
|
return BufferLayout.struct([publicKey('nodePubkey'), publicKey('authorizedVoter'), publicKey('authorizedWithdrawer'), BufferLayout.u8('commission')], property);
|
|
758
567
|
};
|
|
568
|
+
/**
|
|
569
|
+
* Layout for a VoteAuthorizeWithSeedArgs object
|
|
570
|
+
*/
|
|
571
|
+
|
|
572
|
+
const voteAuthorizeWithSeedArgs = (property = 'voteAuthorizeWithSeedArgs') => {
|
|
573
|
+
return BufferLayout.struct([BufferLayout.u32('voteAuthorizationType'), publicKey('currentAuthorityDerivedKeyOwnerPubkey'), rustString('currentAuthorityDerivedKeySeed'), publicKey('newAuthorized')], property);
|
|
574
|
+
};
|
|
759
575
|
function getAlloc(type, fields) {
|
|
760
576
|
const getItemAlloc = item => {
|
|
761
577
|
if (item.span >= 0) {
|
|
@@ -768,6 +584,11 @@ function getAlloc(type, fields) {
|
|
|
768
584
|
if (Array.isArray(field)) {
|
|
769
585
|
return field.length * getItemAlloc(item.elementLayout);
|
|
770
586
|
}
|
|
587
|
+
} else if ('fields' in item) {
|
|
588
|
+
// This is a `Structure` whose size needs to be recursively measured.
|
|
589
|
+
return getAlloc({
|
|
590
|
+
layout: item
|
|
591
|
+
}, fields[item.property]);
|
|
771
592
|
} // Couldn't determine allocated size of layout
|
|
772
593
|
|
|
773
594
|
|
|
@@ -814,6 +635,129 @@ function encodeLength(bytes, len) {
|
|
|
814
635
|
}
|
|
815
636
|
}
|
|
816
637
|
|
|
638
|
+
function assert (condition, message) {
|
|
639
|
+
if (!condition) {
|
|
640
|
+
throw new Error(message || 'Assertion failed');
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
class CompiledKeys {
|
|
645
|
+
constructor(payer, keyMetaMap) {
|
|
646
|
+
this.payer = void 0;
|
|
647
|
+
this.keyMetaMap = void 0;
|
|
648
|
+
this.payer = payer;
|
|
649
|
+
this.keyMetaMap = keyMetaMap;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
static compile(instructions, payer) {
|
|
653
|
+
const keyMetaMap = new Map();
|
|
654
|
+
|
|
655
|
+
const getOrInsertDefault = pubkey => {
|
|
656
|
+
const address = pubkey.toBase58();
|
|
657
|
+
let keyMeta = keyMetaMap.get(address);
|
|
658
|
+
|
|
659
|
+
if (keyMeta === undefined) {
|
|
660
|
+
keyMeta = {
|
|
661
|
+
isSigner: false,
|
|
662
|
+
isWritable: false,
|
|
663
|
+
isInvoked: false
|
|
664
|
+
};
|
|
665
|
+
keyMetaMap.set(address, keyMeta);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return keyMeta;
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
const payerKeyMeta = getOrInsertDefault(payer);
|
|
672
|
+
payerKeyMeta.isSigner = true;
|
|
673
|
+
payerKeyMeta.isWritable = true;
|
|
674
|
+
|
|
675
|
+
for (const ix of instructions) {
|
|
676
|
+
getOrInsertDefault(ix.programId).isInvoked = true;
|
|
677
|
+
|
|
678
|
+
for (const accountMeta of ix.keys) {
|
|
679
|
+
const keyMeta = getOrInsertDefault(accountMeta.pubkey);
|
|
680
|
+
keyMeta.isSigner || (keyMeta.isSigner = accountMeta.isSigner);
|
|
681
|
+
keyMeta.isWritable || (keyMeta.isWritable = accountMeta.isWritable);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
return new CompiledKeys(payer, keyMetaMap);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
getMessageComponents() {
|
|
689
|
+
const mapEntries = [...this.keyMetaMap.entries()];
|
|
690
|
+
assert(mapEntries.length <= 256, 'Max static account keys length exceeded');
|
|
691
|
+
const writableSigners = mapEntries.filter(([, meta]) => meta.isSigner && meta.isWritable);
|
|
692
|
+
const readonlySigners = mapEntries.filter(([, meta]) => meta.isSigner && !meta.isWritable);
|
|
693
|
+
const writableNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && meta.isWritable);
|
|
694
|
+
const readonlyNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && !meta.isWritable);
|
|
695
|
+
const header = {
|
|
696
|
+
numRequiredSignatures: writableSigners.length + readonlySigners.length,
|
|
697
|
+
numReadonlySignedAccounts: readonlySigners.length,
|
|
698
|
+
numReadonlyUnsignedAccounts: readonlyNonSigners.length
|
|
699
|
+
}; // sanity checks
|
|
700
|
+
|
|
701
|
+
{
|
|
702
|
+
assert(writableSigners.length > 0, 'Expected at least one writable signer key');
|
|
703
|
+
const [payerAddress] = writableSigners[0];
|
|
704
|
+
assert(payerAddress === this.payer.toBase58(), 'Expected first writable signer key to be the fee payer');
|
|
705
|
+
}
|
|
706
|
+
const staticAccountKeys = [...writableSigners.map(([address]) => new PublicKey(address)), ...readonlySigners.map(([address]) => new PublicKey(address)), ...writableNonSigners.map(([address]) => new PublicKey(address)), ...readonlyNonSigners.map(([address]) => new PublicKey(address))];
|
|
707
|
+
return [header, staticAccountKeys];
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
extractTableLookup(lookupTable) {
|
|
711
|
+
const [writableIndexes, drainedWritableKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && keyMeta.isWritable);
|
|
712
|
+
const [readonlyIndexes, drainedReadonlyKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && !keyMeta.isWritable); // Don't extract lookup if no keys were found
|
|
713
|
+
|
|
714
|
+
if (writableIndexes.length === 0 && readonlyIndexes.length === 0) {
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
return [{
|
|
719
|
+
accountKey: lookupTable.key,
|
|
720
|
+
writableIndexes,
|
|
721
|
+
readonlyIndexes
|
|
722
|
+
}, {
|
|
723
|
+
writable: drainedWritableKeys,
|
|
724
|
+
readonly: drainedReadonlyKeys
|
|
725
|
+
}];
|
|
726
|
+
}
|
|
727
|
+
/** @internal */
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
drainKeysFoundInLookupTable(lookupTableEntries, keyMetaFilter) {
|
|
731
|
+
const lookupTableIndexes = new Array();
|
|
732
|
+
const drainedKeys = new Array();
|
|
733
|
+
|
|
734
|
+
for (const [address, keyMeta] of this.keyMetaMap.entries()) {
|
|
735
|
+
if (keyMetaFilter(keyMeta)) {
|
|
736
|
+
const key = new PublicKey(address);
|
|
737
|
+
const lookupTableIndex = lookupTableEntries.findIndex(entry => entry.equals(key));
|
|
738
|
+
|
|
739
|
+
if (lookupTableIndex >= 0) {
|
|
740
|
+
assert(lookupTableIndex < 256, 'Max lookup table index exceeded');
|
|
741
|
+
lookupTableIndexes.push(lookupTableIndex);
|
|
742
|
+
drainedKeys.push(key);
|
|
743
|
+
this.keyMetaMap.delete(address);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return [lookupTableIndexes, drainedKeys];
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* An instruction to execute by a program
|
|
755
|
+
*
|
|
756
|
+
* @property {number} programIdIndex
|
|
757
|
+
* @property {number[]} accounts
|
|
758
|
+
* @property {string} data
|
|
759
|
+
*/
|
|
760
|
+
|
|
817
761
|
/**
|
|
818
762
|
* List of instructions to be processed atomically
|
|
819
763
|
*/
|
|
@@ -831,12 +775,63 @@ class Message {
|
|
|
831
775
|
this.instructions.forEach(ix => this.indexToProgramIds.set(ix.programIdIndex, this.accountKeys[ix.programIdIndex]));
|
|
832
776
|
}
|
|
833
777
|
|
|
778
|
+
get version() {
|
|
779
|
+
return 'legacy';
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
get staticAccountKeys() {
|
|
783
|
+
return this.accountKeys;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
get compiledInstructions() {
|
|
787
|
+
return this.instructions.map(ix => ({
|
|
788
|
+
programIdIndex: ix.programIdIndex,
|
|
789
|
+
accountKeyIndexes: ix.accounts,
|
|
790
|
+
data: bs58.decode(ix.data)
|
|
791
|
+
}));
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
get addressTableLookups() {
|
|
795
|
+
return [];
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
getAccountKeys() {
|
|
799
|
+
return new MessageAccountKeys(this.staticAccountKeys);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
static compile(args) {
|
|
803
|
+
const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey);
|
|
804
|
+
const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
|
|
805
|
+
const accountKeys = new MessageAccountKeys(staticAccountKeys);
|
|
806
|
+
const instructions = accountKeys.compileInstructions(args.instructions).map(ix => ({
|
|
807
|
+
programIdIndex: ix.programIdIndex,
|
|
808
|
+
accounts: ix.accountKeyIndexes,
|
|
809
|
+
data: bs58.encode(ix.data)
|
|
810
|
+
}));
|
|
811
|
+
return new Message({
|
|
812
|
+
header,
|
|
813
|
+
accountKeys: staticAccountKeys,
|
|
814
|
+
recentBlockhash: args.recentBlockhash,
|
|
815
|
+
instructions
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
|
|
834
819
|
isAccountSigner(index) {
|
|
835
820
|
return index < this.header.numRequiredSignatures;
|
|
836
821
|
}
|
|
837
822
|
|
|
838
823
|
isAccountWritable(index) {
|
|
839
|
-
|
|
824
|
+
const numSignedAccounts = this.header.numRequiredSignatures;
|
|
825
|
+
|
|
826
|
+
if (index >= this.header.numRequiredSignatures) {
|
|
827
|
+
const unsignedAccountIndex = index - numSignedAccounts;
|
|
828
|
+
const numUnsignedAccounts = this.accountKeys.length - numSignedAccounts;
|
|
829
|
+
const numWritableUnsignedAccounts = numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
|
|
830
|
+
return unsignedAccountIndex < numWritableUnsignedAccounts;
|
|
831
|
+
} else {
|
|
832
|
+
const numWritableSignedAccounts = numSignedAccounts - this.header.numReadonlySignedAccounts;
|
|
833
|
+
return index < numWritableSignedAccounts;
|
|
834
|
+
}
|
|
840
835
|
}
|
|
841
836
|
|
|
842
837
|
isProgramId(index) {
|
|
@@ -907,6 +902,11 @@ class Message {
|
|
|
907
902
|
// Slice up wire data
|
|
908
903
|
let byteArray = [...buffer];
|
|
909
904
|
const numRequiredSignatures = byteArray.shift();
|
|
905
|
+
|
|
906
|
+
if (numRequiredSignatures !== (numRequiredSignatures & VERSION_PREFIX_MASK)) {
|
|
907
|
+
throw new Error('Versioned messages must be deserialized with VersionedMessage.deserialize()');
|
|
908
|
+
}
|
|
909
|
+
|
|
910
910
|
const numReadonlySignedAccounts = byteArray.shift();
|
|
911
911
|
const numReadonlyUnsignedAccounts = byteArray.shift();
|
|
912
912
|
const accountCount = decodeLength(byteArray);
|
|
@@ -915,7 +915,7 @@ class Message {
|
|
|
915
915
|
for (let i = 0; i < accountCount; i++) {
|
|
916
916
|
const account = byteArray.slice(0, PUBLIC_KEY_LENGTH);
|
|
917
917
|
byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
|
|
918
|
-
accountKeys.push(
|
|
918
|
+
accountKeys.push(new PublicKey(Buffer.from(account)));
|
|
919
919
|
}
|
|
920
920
|
|
|
921
921
|
const recentBlockhash = byteArray.slice(0, PUBLIC_KEY_LENGTH);
|
|
@@ -954,12 +954,313 @@ class Message {
|
|
|
954
954
|
|
|
955
955
|
}
|
|
956
956
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
957
|
+
/**
|
|
958
|
+
* Message constructor arguments
|
|
959
|
+
*/
|
|
960
|
+
|
|
961
|
+
class MessageV0 {
|
|
962
|
+
constructor(args) {
|
|
963
|
+
this.header = void 0;
|
|
964
|
+
this.staticAccountKeys = void 0;
|
|
965
|
+
this.recentBlockhash = void 0;
|
|
966
|
+
this.compiledInstructions = void 0;
|
|
967
|
+
this.addressTableLookups = void 0;
|
|
968
|
+
this.header = args.header;
|
|
969
|
+
this.staticAccountKeys = args.staticAccountKeys;
|
|
970
|
+
this.recentBlockhash = args.recentBlockhash;
|
|
971
|
+
this.compiledInstructions = args.compiledInstructions;
|
|
972
|
+
this.addressTableLookups = args.addressTableLookups;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
get version() {
|
|
976
|
+
return 0;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
get numAccountKeysFromLookups() {
|
|
980
|
+
let count = 0;
|
|
981
|
+
|
|
982
|
+
for (const lookup of this.addressTableLookups) {
|
|
983
|
+
count += lookup.readonlyIndexes.length + lookup.writableIndexes.length;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
return count;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
getAccountKeys(args) {
|
|
990
|
+
let accountKeysFromLookups;
|
|
991
|
+
|
|
992
|
+
if (args && 'accountKeysFromLookups' in args && args.accountKeysFromLookups) {
|
|
993
|
+
if (this.numAccountKeysFromLookups != args.accountKeysFromLookups.writable.length + args.accountKeysFromLookups.readonly.length) {
|
|
994
|
+
throw new Error('Failed to get account keys because of a mismatch in the number of account keys from lookups');
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
accountKeysFromLookups = args.accountKeysFromLookups;
|
|
998
|
+
} else if (args && 'addressLookupTableAccounts' in args && args.addressLookupTableAccounts) {
|
|
999
|
+
accountKeysFromLookups = this.resolveAddressTableLookups(args.addressLookupTableAccounts);
|
|
1000
|
+
} else if (this.addressTableLookups.length > 0) {
|
|
1001
|
+
throw new Error('Failed to get account keys because address table lookups were not resolved');
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
return new MessageAccountKeys(this.staticAccountKeys, accountKeysFromLookups);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
isAccountSigner(index) {
|
|
1008
|
+
return index < this.header.numRequiredSignatures;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
isAccountWritable(index) {
|
|
1012
|
+
const numSignedAccounts = this.header.numRequiredSignatures;
|
|
1013
|
+
const numStaticAccountKeys = this.staticAccountKeys.length;
|
|
1014
|
+
|
|
1015
|
+
if (index >= numStaticAccountKeys) {
|
|
1016
|
+
const lookupAccountKeysIndex = index - numStaticAccountKeys;
|
|
1017
|
+
const numWritableLookupAccountKeys = this.addressTableLookups.reduce((count, lookup) => count + lookup.writableIndexes.length, 0);
|
|
1018
|
+
return lookupAccountKeysIndex < numWritableLookupAccountKeys;
|
|
1019
|
+
} else if (index >= this.header.numRequiredSignatures) {
|
|
1020
|
+
const unsignedAccountIndex = index - numSignedAccounts;
|
|
1021
|
+
const numUnsignedAccounts = numStaticAccountKeys - numSignedAccounts;
|
|
1022
|
+
const numWritableUnsignedAccounts = numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
|
|
1023
|
+
return unsignedAccountIndex < numWritableUnsignedAccounts;
|
|
1024
|
+
} else {
|
|
1025
|
+
const numWritableSignedAccounts = numSignedAccounts - this.header.numReadonlySignedAccounts;
|
|
1026
|
+
return index < numWritableSignedAccounts;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
resolveAddressTableLookups(addressLookupTableAccounts) {
|
|
1031
|
+
const accountKeysFromLookups = {
|
|
1032
|
+
writable: [],
|
|
1033
|
+
readonly: []
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
for (const tableLookup of this.addressTableLookups) {
|
|
1037
|
+
const tableAccount = addressLookupTableAccounts.find(account => account.key.equals(tableLookup.accountKey));
|
|
1038
|
+
|
|
1039
|
+
if (!tableAccount) {
|
|
1040
|
+
throw new Error(`Failed to find address lookup table account for table key ${tableLookup.accountKey.toBase58()}`);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
for (const index of tableLookup.writableIndexes) {
|
|
1044
|
+
if (index < tableAccount.state.addresses.length) {
|
|
1045
|
+
accountKeysFromLookups.writable.push(tableAccount.state.addresses[index]);
|
|
1046
|
+
} else {
|
|
1047
|
+
throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
for (const index of tableLookup.readonlyIndexes) {
|
|
1052
|
+
if (index < tableAccount.state.addresses.length) {
|
|
1053
|
+
accountKeysFromLookups.readonly.push(tableAccount.state.addresses[index]);
|
|
1054
|
+
} else {
|
|
1055
|
+
throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
return accountKeysFromLookups;
|
|
960
1061
|
}
|
|
1062
|
+
|
|
1063
|
+
static compile(args) {
|
|
1064
|
+
const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey);
|
|
1065
|
+
const addressTableLookups = new Array();
|
|
1066
|
+
const accountKeysFromLookups = {
|
|
1067
|
+
writable: new Array(),
|
|
1068
|
+
readonly: new Array()
|
|
1069
|
+
};
|
|
1070
|
+
const lookupTableAccounts = args.addressLookupTableAccounts || [];
|
|
1071
|
+
|
|
1072
|
+
for (const lookupTable of lookupTableAccounts) {
|
|
1073
|
+
const extractResult = compiledKeys.extractTableLookup(lookupTable);
|
|
1074
|
+
|
|
1075
|
+
if (extractResult !== undefined) {
|
|
1076
|
+
const [addressTableLookup, {
|
|
1077
|
+
writable,
|
|
1078
|
+
readonly
|
|
1079
|
+
}] = extractResult;
|
|
1080
|
+
addressTableLookups.push(addressTableLookup);
|
|
1081
|
+
accountKeysFromLookups.writable.push(...writable);
|
|
1082
|
+
accountKeysFromLookups.readonly.push(...readonly);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
|
|
1087
|
+
const accountKeys = new MessageAccountKeys(staticAccountKeys, accountKeysFromLookups);
|
|
1088
|
+
const compiledInstructions = accountKeys.compileInstructions(args.instructions);
|
|
1089
|
+
return new MessageV0({
|
|
1090
|
+
header,
|
|
1091
|
+
staticAccountKeys,
|
|
1092
|
+
recentBlockhash: args.recentBlockhash,
|
|
1093
|
+
compiledInstructions,
|
|
1094
|
+
addressTableLookups
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
serialize() {
|
|
1099
|
+
const encodedStaticAccountKeysLength = Array();
|
|
1100
|
+
encodeLength(encodedStaticAccountKeysLength, this.staticAccountKeys.length);
|
|
1101
|
+
const serializedInstructions = this.serializeInstructions();
|
|
1102
|
+
const encodedInstructionsLength = Array();
|
|
1103
|
+
encodeLength(encodedInstructionsLength, this.compiledInstructions.length);
|
|
1104
|
+
const serializedAddressTableLookups = this.serializeAddressTableLookups();
|
|
1105
|
+
const encodedAddressTableLookupsLength = Array();
|
|
1106
|
+
encodeLength(encodedAddressTableLookupsLength, this.addressTableLookups.length);
|
|
1107
|
+
const messageLayout = BufferLayout.struct([BufferLayout.u8('prefix'), BufferLayout.struct([BufferLayout.u8('numRequiredSignatures'), BufferLayout.u8('numReadonlySignedAccounts'), BufferLayout.u8('numReadonlyUnsignedAccounts')], 'header'), BufferLayout.blob(encodedStaticAccountKeysLength.length, 'staticAccountKeysLength'), BufferLayout.seq(publicKey(), this.staticAccountKeys.length, 'staticAccountKeys'), publicKey('recentBlockhash'), BufferLayout.blob(encodedInstructionsLength.length, 'instructionsLength'), BufferLayout.blob(serializedInstructions.length, 'serializedInstructions'), BufferLayout.blob(encodedAddressTableLookupsLength.length, 'addressTableLookupsLength'), BufferLayout.blob(serializedAddressTableLookups.length, 'serializedAddressTableLookups')]);
|
|
1108
|
+
const serializedMessage = new Uint8Array(PACKET_DATA_SIZE);
|
|
1109
|
+
const MESSAGE_VERSION_0_PREFIX = 1 << 7;
|
|
1110
|
+
const serializedMessageLength = messageLayout.encode({
|
|
1111
|
+
prefix: MESSAGE_VERSION_0_PREFIX,
|
|
1112
|
+
header: this.header,
|
|
1113
|
+
staticAccountKeysLength: new Uint8Array(encodedStaticAccountKeysLength),
|
|
1114
|
+
staticAccountKeys: this.staticAccountKeys.map(key => key.toBytes()),
|
|
1115
|
+
recentBlockhash: bs58.decode(this.recentBlockhash),
|
|
1116
|
+
instructionsLength: new Uint8Array(encodedInstructionsLength),
|
|
1117
|
+
serializedInstructions,
|
|
1118
|
+
addressTableLookupsLength: new Uint8Array(encodedAddressTableLookupsLength),
|
|
1119
|
+
serializedAddressTableLookups
|
|
1120
|
+
}, serializedMessage);
|
|
1121
|
+
return serializedMessage.slice(0, serializedMessageLength);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
serializeInstructions() {
|
|
1125
|
+
let serializedLength = 0;
|
|
1126
|
+
const serializedInstructions = new Uint8Array(PACKET_DATA_SIZE);
|
|
1127
|
+
|
|
1128
|
+
for (const instruction of this.compiledInstructions) {
|
|
1129
|
+
const encodedAccountKeyIndexesLength = Array();
|
|
1130
|
+
encodeLength(encodedAccountKeyIndexesLength, instruction.accountKeyIndexes.length);
|
|
1131
|
+
const encodedDataLength = Array();
|
|
1132
|
+
encodeLength(encodedDataLength, instruction.data.length);
|
|
1133
|
+
const instructionLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(encodedAccountKeyIndexesLength.length, 'encodedAccountKeyIndexesLength'), BufferLayout.seq(BufferLayout.u8(), instruction.accountKeyIndexes.length, 'accountKeyIndexes'), BufferLayout.blob(encodedDataLength.length, 'encodedDataLength'), BufferLayout.blob(instruction.data.length, 'data')]);
|
|
1134
|
+
serializedLength += instructionLayout.encode({
|
|
1135
|
+
programIdIndex: instruction.programIdIndex,
|
|
1136
|
+
encodedAccountKeyIndexesLength: new Uint8Array(encodedAccountKeyIndexesLength),
|
|
1137
|
+
accountKeyIndexes: instruction.accountKeyIndexes,
|
|
1138
|
+
encodedDataLength: new Uint8Array(encodedDataLength),
|
|
1139
|
+
data: instruction.data
|
|
1140
|
+
}, serializedInstructions, serializedLength);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
return serializedInstructions.slice(0, serializedLength);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
serializeAddressTableLookups() {
|
|
1147
|
+
let serializedLength = 0;
|
|
1148
|
+
const serializedAddressTableLookups = new Uint8Array(PACKET_DATA_SIZE);
|
|
1149
|
+
|
|
1150
|
+
for (const lookup of this.addressTableLookups) {
|
|
1151
|
+
const encodedWritableIndexesLength = Array();
|
|
1152
|
+
encodeLength(encodedWritableIndexesLength, lookup.writableIndexes.length);
|
|
1153
|
+
const encodedReadonlyIndexesLength = Array();
|
|
1154
|
+
encodeLength(encodedReadonlyIndexesLength, lookup.readonlyIndexes.length);
|
|
1155
|
+
const addressTableLookupLayout = BufferLayout.struct([publicKey('accountKey'), BufferLayout.blob(encodedWritableIndexesLength.length, 'encodedWritableIndexesLength'), BufferLayout.seq(BufferLayout.u8(), lookup.writableIndexes.length, 'writableIndexes'), BufferLayout.blob(encodedReadonlyIndexesLength.length, 'encodedReadonlyIndexesLength'), BufferLayout.seq(BufferLayout.u8(), lookup.readonlyIndexes.length, 'readonlyIndexes')]);
|
|
1156
|
+
serializedLength += addressTableLookupLayout.encode({
|
|
1157
|
+
accountKey: lookup.accountKey.toBytes(),
|
|
1158
|
+
encodedWritableIndexesLength: new Uint8Array(encodedWritableIndexesLength),
|
|
1159
|
+
writableIndexes: lookup.writableIndexes,
|
|
1160
|
+
encodedReadonlyIndexesLength: new Uint8Array(encodedReadonlyIndexesLength),
|
|
1161
|
+
readonlyIndexes: lookup.readonlyIndexes
|
|
1162
|
+
}, serializedAddressTableLookups, serializedLength);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
return serializedAddressTableLookups.slice(0, serializedLength);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
static deserialize(serializedMessage) {
|
|
1169
|
+
let byteArray = [...serializedMessage];
|
|
1170
|
+
const prefix = byteArray.shift();
|
|
1171
|
+
const maskedPrefix = prefix & VERSION_PREFIX_MASK;
|
|
1172
|
+
assert(prefix !== maskedPrefix, `Expected versioned message but received legacy message`);
|
|
1173
|
+
const version = maskedPrefix;
|
|
1174
|
+
assert(version === 0, `Expected versioned message with version 0 but found version ${version}`);
|
|
1175
|
+
const header = {
|
|
1176
|
+
numRequiredSignatures: byteArray.shift(),
|
|
1177
|
+
numReadonlySignedAccounts: byteArray.shift(),
|
|
1178
|
+
numReadonlyUnsignedAccounts: byteArray.shift()
|
|
1179
|
+
};
|
|
1180
|
+
const staticAccountKeys = [];
|
|
1181
|
+
const staticAccountKeysLength = decodeLength(byteArray);
|
|
1182
|
+
|
|
1183
|
+
for (let i = 0; i < staticAccountKeysLength; i++) {
|
|
1184
|
+
staticAccountKeys.push(new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH)));
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
const recentBlockhash = bs58.encode(byteArray.splice(0, PUBLIC_KEY_LENGTH));
|
|
1188
|
+
const instructionCount = decodeLength(byteArray);
|
|
1189
|
+
const compiledInstructions = [];
|
|
1190
|
+
|
|
1191
|
+
for (let i = 0; i < instructionCount; i++) {
|
|
1192
|
+
const programIdIndex = byteArray.shift();
|
|
1193
|
+
const accountKeyIndexesLength = decodeLength(byteArray);
|
|
1194
|
+
const accountKeyIndexes = byteArray.splice(0, accountKeyIndexesLength);
|
|
1195
|
+
const dataLength = decodeLength(byteArray);
|
|
1196
|
+
const data = new Uint8Array(byteArray.splice(0, dataLength));
|
|
1197
|
+
compiledInstructions.push({
|
|
1198
|
+
programIdIndex,
|
|
1199
|
+
accountKeyIndexes,
|
|
1200
|
+
data
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
const addressTableLookupsCount = decodeLength(byteArray);
|
|
1205
|
+
const addressTableLookups = [];
|
|
1206
|
+
|
|
1207
|
+
for (let i = 0; i < addressTableLookupsCount; i++) {
|
|
1208
|
+
const accountKey = new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH));
|
|
1209
|
+
const writableIndexesLength = decodeLength(byteArray);
|
|
1210
|
+
const writableIndexes = byteArray.splice(0, writableIndexesLength);
|
|
1211
|
+
const readonlyIndexesLength = decodeLength(byteArray);
|
|
1212
|
+
const readonlyIndexes = byteArray.splice(0, readonlyIndexesLength);
|
|
1213
|
+
addressTableLookups.push({
|
|
1214
|
+
accountKey,
|
|
1215
|
+
writableIndexes,
|
|
1216
|
+
readonlyIndexes
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
return new MessageV0({
|
|
1221
|
+
header,
|
|
1222
|
+
staticAccountKeys,
|
|
1223
|
+
recentBlockhash,
|
|
1224
|
+
compiledInstructions,
|
|
1225
|
+
addressTableLookups
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
|
|
961
1229
|
}
|
|
962
1230
|
|
|
1231
|
+
// eslint-disable-next-line no-redeclare
|
|
1232
|
+
const VersionedMessage = {
|
|
1233
|
+
deserializeMessageVersion(serializedMessage) {
|
|
1234
|
+
const prefix = serializedMessage[0];
|
|
1235
|
+
const maskedPrefix = prefix & VERSION_PREFIX_MASK; // if the highest bit of the prefix is not set, the message is not versioned
|
|
1236
|
+
|
|
1237
|
+
if (maskedPrefix === prefix) {
|
|
1238
|
+
return 'legacy';
|
|
1239
|
+
} // the lower 7 bits of the prefix indicate the message version
|
|
1240
|
+
|
|
1241
|
+
|
|
1242
|
+
return maskedPrefix;
|
|
1243
|
+
},
|
|
1244
|
+
|
|
1245
|
+
deserialize: serializedMessage => {
|
|
1246
|
+
const version = VersionedMessage.deserializeMessageVersion(serializedMessage);
|
|
1247
|
+
|
|
1248
|
+
if (version === 'legacy') {
|
|
1249
|
+
return Message.from(serializedMessage);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
if (version === 0) {
|
|
1253
|
+
return MessageV0.deserialize(serializedMessage);
|
|
1254
|
+
} else {
|
|
1255
|
+
throw new Error(`Transaction message version ${version} deserialization is not supported`);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Transaction signature as base-58 encoded string
|
|
1262
|
+
*/
|
|
1263
|
+
|
|
963
1264
|
let TransactionStatus;
|
|
964
1265
|
/**
|
|
965
1266
|
* Default (empty) signature
|
|
@@ -969,6 +1270,7 @@ let TransactionStatus;
|
|
|
969
1270
|
TransactionStatus[TransactionStatus["BLOCKHEIGHT_EXCEEDED"] = 0] = "BLOCKHEIGHT_EXCEEDED";
|
|
970
1271
|
TransactionStatus[TransactionStatus["PROCESSED"] = 1] = "PROCESSED";
|
|
971
1272
|
TransactionStatus[TransactionStatus["TIMED_OUT"] = 2] = "TIMED_OUT";
|
|
1273
|
+
TransactionStatus[TransactionStatus["NONCE_INVALID"] = 3] = "NONCE_INVALID";
|
|
972
1274
|
})(TransactionStatus || (TransactionStatus = {}));
|
|
973
1275
|
|
|
974
1276
|
const DEFAULT_SIGNATURE = Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
|
|
@@ -1063,6 +1365,7 @@ class Transaction {
|
|
|
1063
1365
|
this.recentBlockhash = void 0;
|
|
1064
1366
|
this.lastValidBlockHeight = void 0;
|
|
1065
1367
|
this.nonceInfo = void 0;
|
|
1368
|
+
this.minNonceContextSlot = void 0;
|
|
1066
1369
|
this._message = void 0;
|
|
1067
1370
|
this._json = void 0;
|
|
1068
1371
|
|
|
@@ -1078,7 +1381,14 @@ class Transaction {
|
|
|
1078
1381
|
this.signatures = opts.signatures;
|
|
1079
1382
|
}
|
|
1080
1383
|
|
|
1081
|
-
if (Object.prototype.hasOwnProperty.call(opts, '
|
|
1384
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'nonceInfo')) {
|
|
1385
|
+
const {
|
|
1386
|
+
minContextSlot,
|
|
1387
|
+
nonceInfo
|
|
1388
|
+
} = opts;
|
|
1389
|
+
this.minNonceContextSlot = minContextSlot;
|
|
1390
|
+
this.nonceInfo = nonceInfo;
|
|
1391
|
+
} else if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) {
|
|
1082
1392
|
const {
|
|
1083
1393
|
blockhash,
|
|
1084
1394
|
lastValidBlockHeight
|
|
@@ -1485,7 +1795,7 @@ class Transaction {
|
|
|
1485
1795
|
_partialSign(message, ...signers) {
|
|
1486
1796
|
const signData = message.serialize();
|
|
1487
1797
|
signers.forEach(signer => {
|
|
1488
|
-
const signature =
|
|
1798
|
+
const signature = sign(signData, signer.secretKey);
|
|
1489
1799
|
|
|
1490
1800
|
this._addSignature(signer.publicKey, toBuffer(signature));
|
|
1491
1801
|
});
|
|
@@ -1541,7 +1851,7 @@ class Transaction {
|
|
|
1541
1851
|
return false;
|
|
1542
1852
|
}
|
|
1543
1853
|
} else {
|
|
1544
|
-
if (!
|
|
1854
|
+
if (!verify(signature, signData, publicKey.toBytes())) {
|
|
1545
1855
|
return false;
|
|
1546
1856
|
}
|
|
1547
1857
|
}
|
|
@@ -1688,6 +1998,184 @@ class Transaction {
|
|
|
1688
1998
|
|
|
1689
1999
|
}
|
|
1690
2000
|
|
|
2001
|
+
class TransactionMessage {
|
|
2002
|
+
constructor(args) {
|
|
2003
|
+
this.payerKey = void 0;
|
|
2004
|
+
this.instructions = void 0;
|
|
2005
|
+
this.recentBlockhash = void 0;
|
|
2006
|
+
this.payerKey = args.payerKey;
|
|
2007
|
+
this.instructions = args.instructions;
|
|
2008
|
+
this.recentBlockhash = args.recentBlockhash;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
static decompile(message, args) {
|
|
2012
|
+
const {
|
|
2013
|
+
header,
|
|
2014
|
+
compiledInstructions,
|
|
2015
|
+
recentBlockhash
|
|
2016
|
+
} = message;
|
|
2017
|
+
const {
|
|
2018
|
+
numRequiredSignatures,
|
|
2019
|
+
numReadonlySignedAccounts,
|
|
2020
|
+
numReadonlyUnsignedAccounts
|
|
2021
|
+
} = header;
|
|
2022
|
+
const numWritableSignedAccounts = numRequiredSignatures - numReadonlySignedAccounts;
|
|
2023
|
+
assert(numWritableSignedAccounts > 0, 'Message header is invalid');
|
|
2024
|
+
const numWritableUnsignedAccounts = message.staticAccountKeys.length - numRequiredSignatures - numReadonlyUnsignedAccounts;
|
|
2025
|
+
assert(numWritableUnsignedAccounts >= 0, 'Message header is invalid');
|
|
2026
|
+
const accountKeys = message.getAccountKeys(args);
|
|
2027
|
+
const payerKey = accountKeys.get(0);
|
|
2028
|
+
|
|
2029
|
+
if (payerKey === undefined) {
|
|
2030
|
+
throw new Error('Failed to decompile message because no account keys were found');
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
const instructions = [];
|
|
2034
|
+
|
|
2035
|
+
for (const compiledIx of compiledInstructions) {
|
|
2036
|
+
const keys = [];
|
|
2037
|
+
|
|
2038
|
+
for (const keyIndex of compiledIx.accountKeyIndexes) {
|
|
2039
|
+
const pubkey = accountKeys.get(keyIndex);
|
|
2040
|
+
|
|
2041
|
+
if (pubkey === undefined) {
|
|
2042
|
+
throw new Error(`Failed to find key for account key index ${keyIndex}`);
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
const isSigner = keyIndex < numRequiredSignatures;
|
|
2046
|
+
let isWritable;
|
|
2047
|
+
|
|
2048
|
+
if (isSigner) {
|
|
2049
|
+
isWritable = keyIndex < numWritableSignedAccounts;
|
|
2050
|
+
} else if (keyIndex < accountKeys.staticAccountKeys.length) {
|
|
2051
|
+
isWritable = keyIndex - numRequiredSignatures < numWritableUnsignedAccounts;
|
|
2052
|
+
} else {
|
|
2053
|
+
isWritable = keyIndex - accountKeys.staticAccountKeys.length < // accountKeysFromLookups cannot be undefined because we already found a pubkey for this index above
|
|
2054
|
+
accountKeys.accountKeysFromLookups.writable.length;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
keys.push({
|
|
2058
|
+
pubkey,
|
|
2059
|
+
isSigner: keyIndex < header.numRequiredSignatures,
|
|
2060
|
+
isWritable
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
const programId = accountKeys.get(compiledIx.programIdIndex);
|
|
2065
|
+
|
|
2066
|
+
if (programId === undefined) {
|
|
2067
|
+
throw new Error(`Failed to find program id for program id index ${compiledIx.programIdIndex}`);
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
instructions.push(new TransactionInstruction({
|
|
2071
|
+
programId,
|
|
2072
|
+
data: toBuffer(compiledIx.data),
|
|
2073
|
+
keys
|
|
2074
|
+
}));
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
return new TransactionMessage({
|
|
2078
|
+
payerKey,
|
|
2079
|
+
instructions,
|
|
2080
|
+
recentBlockhash
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
compileToLegacyMessage() {
|
|
2085
|
+
return Message.compile({
|
|
2086
|
+
payerKey: this.payerKey,
|
|
2087
|
+
recentBlockhash: this.recentBlockhash,
|
|
2088
|
+
instructions: this.instructions
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
compileToV0Message(addressLookupTableAccounts) {
|
|
2093
|
+
return MessageV0.compile({
|
|
2094
|
+
payerKey: this.payerKey,
|
|
2095
|
+
recentBlockhash: this.recentBlockhash,
|
|
2096
|
+
instructions: this.instructions,
|
|
2097
|
+
addressLookupTableAccounts
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
/**
|
|
2104
|
+
* Versioned transaction class
|
|
2105
|
+
*/
|
|
2106
|
+
class VersionedTransaction {
|
|
2107
|
+
get version() {
|
|
2108
|
+
return this.message.version;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
constructor(message, signatures) {
|
|
2112
|
+
this.signatures = void 0;
|
|
2113
|
+
this.message = void 0;
|
|
2114
|
+
|
|
2115
|
+
if (signatures !== undefined) {
|
|
2116
|
+
assert(signatures.length === message.header.numRequiredSignatures, 'Expected signatures length to be equal to the number of required signatures');
|
|
2117
|
+
this.signatures = signatures;
|
|
2118
|
+
} else {
|
|
2119
|
+
const defaultSignatures = [];
|
|
2120
|
+
|
|
2121
|
+
for (let i = 0; i < message.header.numRequiredSignatures; i++) {
|
|
2122
|
+
defaultSignatures.push(new Uint8Array(SIGNATURE_LENGTH_IN_BYTES));
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
this.signatures = defaultSignatures;
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
this.message = message;
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
serialize() {
|
|
2132
|
+
const serializedMessage = this.message.serialize();
|
|
2133
|
+
const encodedSignaturesLength = Array();
|
|
2134
|
+
encodeLength(encodedSignaturesLength, this.signatures.length);
|
|
2135
|
+
const transactionLayout = BufferLayout.struct([BufferLayout.blob(encodedSignaturesLength.length, 'encodedSignaturesLength'), BufferLayout.seq(signature(), this.signatures.length, 'signatures'), BufferLayout.blob(serializedMessage.length, 'serializedMessage')]);
|
|
2136
|
+
const serializedTransaction = new Uint8Array(2048);
|
|
2137
|
+
const serializedTransactionLength = transactionLayout.encode({
|
|
2138
|
+
encodedSignaturesLength: new Uint8Array(encodedSignaturesLength),
|
|
2139
|
+
signatures: this.signatures,
|
|
2140
|
+
serializedMessage
|
|
2141
|
+
}, serializedTransaction);
|
|
2142
|
+
return serializedTransaction.slice(0, serializedTransactionLength);
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
static deserialize(serializedTransaction) {
|
|
2146
|
+
let byteArray = [...serializedTransaction];
|
|
2147
|
+
const signatures = [];
|
|
2148
|
+
const signaturesLength = decodeLength(byteArray);
|
|
2149
|
+
|
|
2150
|
+
for (let i = 0; i < signaturesLength; i++) {
|
|
2151
|
+
signatures.push(new Uint8Array(byteArray.splice(0, SIGNATURE_LENGTH_IN_BYTES)));
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
const message = VersionedMessage.deserialize(new Uint8Array(byteArray));
|
|
2155
|
+
return new VersionedTransaction(message, signatures);
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
sign(signers) {
|
|
2159
|
+
const messageData = this.message.serialize();
|
|
2160
|
+
const signerPubkeys = this.message.staticAccountKeys.slice(0, this.message.header.numRequiredSignatures);
|
|
2161
|
+
|
|
2162
|
+
for (const signer of signers) {
|
|
2163
|
+
const signerIndex = signerPubkeys.findIndex(pubkey => pubkey.equals(signer.publicKey));
|
|
2164
|
+
assert(signerIndex >= 0, `Cannot sign with non signer key ${signer.publicKey.toBase58()}`);
|
|
2165
|
+
this.signatures[signerIndex] = sign(messageData, signer.secretKey);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
addSignature(publicKey, signature) {
|
|
2170
|
+
assert(signature.byteLength === 64, 'Signature must be 64 bytes long');
|
|
2171
|
+
const signerPubkeys = this.message.staticAccountKeys.slice(0, this.message.header.numRequiredSignatures);
|
|
2172
|
+
const signerIndex = signerPubkeys.findIndex(pubkey => pubkey.equals(publicKey));
|
|
2173
|
+
assert(signerIndex >= 0, `Can not add signature; \`${publicKey.toBase58()}\` is not required to sign this transaction`);
|
|
2174
|
+
this.signatures[signerIndex] = signature;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
}
|
|
2178
|
+
|
|
1691
2179
|
const SYSVAR_CLOCK_PUBKEY = new PublicKey('SysvarC1ock11111111111111111111111111111111');
|
|
1692
2180
|
const SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey('SysvarEpochSchedu1e111111111111111111111111');
|
|
1693
2181
|
const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey('Sysvar1nstructions1111111111111111111111111');
|
|
@@ -1717,11 +2205,34 @@ async function sendAndConfirmTransaction(connection, transaction, signers, optio
|
|
|
1717
2205
|
minContextSlot: options.minContextSlot
|
|
1718
2206
|
};
|
|
1719
2207
|
const signature = await connection.sendTransaction(transaction, signers, sendOptions);
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
2208
|
+
let status;
|
|
2209
|
+
|
|
2210
|
+
if (transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null) {
|
|
2211
|
+
status = (await connection.confirmTransaction({
|
|
2212
|
+
abortSignal: options === null || options === void 0 ? void 0 : options.abortSignal,
|
|
2213
|
+
signature: signature,
|
|
2214
|
+
blockhash: transaction.recentBlockhash,
|
|
2215
|
+
lastValidBlockHeight: transaction.lastValidBlockHeight
|
|
2216
|
+
}, options && options.commitment)).value;
|
|
2217
|
+
} else if (transaction.minNonceContextSlot != null && transaction.nonceInfo != null) {
|
|
2218
|
+
const {
|
|
2219
|
+
nonceInstruction
|
|
2220
|
+
} = transaction.nonceInfo;
|
|
2221
|
+
const nonceAccountPubkey = nonceInstruction.keys[0].pubkey;
|
|
2222
|
+
status = (await connection.confirmTransaction({
|
|
2223
|
+
abortSignal: options === null || options === void 0 ? void 0 : options.abortSignal,
|
|
2224
|
+
minContextSlot: transaction.minNonceContextSlot,
|
|
2225
|
+
nonceAccountPubkey,
|
|
2226
|
+
nonceValue: transaction.nonceInfo.nonce,
|
|
2227
|
+
signature
|
|
2228
|
+
}, options && options.commitment)).value;
|
|
2229
|
+
} else {
|
|
2230
|
+
if ((options === null || options === void 0 ? void 0 : options.abortSignal) != null) {
|
|
2231
|
+
console.warn('sendAndConfirmTransaction(): A transaction with a deprecated confirmation strategy was ' + 'supplied along with an `abortSignal`. Only transactions having `lastValidBlockHeight` ' + 'or a combination of `nonceInfo` and `minNonceContextSlot` are abortable.');
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
status = (await connection.confirmTransaction(signature, options && options.commitment)).value;
|
|
2235
|
+
}
|
|
1725
2236
|
|
|
1726
2237
|
if (status.err) {
|
|
1727
2238
|
throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`);
|
|
@@ -1790,6 +2301,9 @@ const FeeCalculatorLayout = BufferLayout.nu64('lamportsPerSignature');
|
|
|
1790
2301
|
|
|
1791
2302
|
const NonceAccountLayout = BufferLayout.struct([BufferLayout.u32('version'), BufferLayout.u32('state'), publicKey('authorizedPubkey'), publicKey('nonce'), BufferLayout.struct([FeeCalculatorLayout], 'feeCalculator')]);
|
|
1792
2303
|
const NONCE_ACCOUNT_LENGTH = NonceAccountLayout.span;
|
|
2304
|
+
/**
|
|
2305
|
+
* A durable nonce is a 32 byte value encoded as a base58 string.
|
|
2306
|
+
*/
|
|
1793
2307
|
|
|
1794
2308
|
/**
|
|
1795
2309
|
* NonceAccount class
|
|
@@ -2759,12 +3273,12 @@ class BpfLoader {
|
|
|
2759
3273
|
return Loader.getMinNumSignatures(dataLength);
|
|
2760
3274
|
}
|
|
2761
3275
|
/**
|
|
2762
|
-
* Load a
|
|
3276
|
+
* Load a SBF program
|
|
2763
3277
|
*
|
|
2764
3278
|
* @param connection The connection to use
|
|
2765
3279
|
* @param payer Account that will pay program loading fees
|
|
2766
3280
|
* @param program Account to load the program into
|
|
2767
|
-
* @param elf The entire ELF containing the
|
|
3281
|
+
* @param elf The entire ELF containing the SBF program
|
|
2768
3282
|
* @param loaderProgramId The program id of the BPF loader to use
|
|
2769
3283
|
* @return true if program was loaded successfully, false if program was already loaded
|
|
2770
3284
|
*/
|
|
@@ -2880,7 +3394,7 @@ function nextPowerOfTwo(n) {
|
|
|
2880
3394
|
/**
|
|
2881
3395
|
* Epoch schedule
|
|
2882
3396
|
* (see https://docs.solana.com/terminology#epoch)
|
|
2883
|
-
* Can be retrieved with the {@link
|
|
3397
|
+
* Can be retrieved with the {@link Connection.getEpochSchedule} method
|
|
2884
3398
|
*/
|
|
2885
3399
|
|
|
2886
3400
|
|
|
@@ -3052,7 +3566,7 @@ class AddressLookupTableAccount {
|
|
|
3052
3566
|
}
|
|
3053
3567
|
|
|
3054
3568
|
isActive() {
|
|
3055
|
-
const U64_MAX =
|
|
3569
|
+
const U64_MAX = BigInt('0xffffffffffffffff');
|
|
3056
3570
|
return this.state.deactivationSlot === U64_MAX;
|
|
3057
3571
|
}
|
|
3058
3572
|
|
|
@@ -3196,7 +3710,7 @@ function jsonRpcResult(schema) {
|
|
|
3196
3710
|
function jsonRpcResultAndContext(value) {
|
|
3197
3711
|
return jsonRpcResult(type({
|
|
3198
3712
|
context: type({
|
|
3199
|
-
slot: number
|
|
3713
|
+
slot: number()
|
|
3200
3714
|
}),
|
|
3201
3715
|
value
|
|
3202
3716
|
}));
|
|
@@ -3209,11 +3723,33 @@ function jsonRpcResultAndContext(value) {
|
|
|
3209
3723
|
function notificationResultAndContext(value) {
|
|
3210
3724
|
return type({
|
|
3211
3725
|
context: type({
|
|
3212
|
-
slot: number
|
|
3726
|
+
slot: number()
|
|
3213
3727
|
}),
|
|
3214
3728
|
value
|
|
3215
3729
|
});
|
|
3216
3730
|
}
|
|
3731
|
+
/**
|
|
3732
|
+
* @internal
|
|
3733
|
+
*/
|
|
3734
|
+
|
|
3735
|
+
|
|
3736
|
+
function versionedMessageFromResponse(version, response) {
|
|
3737
|
+
if (version === 0) {
|
|
3738
|
+
return new MessageV0({
|
|
3739
|
+
header: response.header,
|
|
3740
|
+
staticAccountKeys: response.accountKeys.map(accountKey => new PublicKey(accountKey)),
|
|
3741
|
+
recentBlockhash: response.recentBlockhash,
|
|
3742
|
+
compiledInstructions: response.instructions.map(ix => ({
|
|
3743
|
+
programIdIndex: ix.programIdIndex,
|
|
3744
|
+
accountKeyIndexes: ix.accounts,
|
|
3745
|
+
data: bs58.decode(ix.data)
|
|
3746
|
+
})),
|
|
3747
|
+
addressTableLookups: response.addressTableLookups
|
|
3748
|
+
});
|
|
3749
|
+
} else {
|
|
3750
|
+
return new Message(response);
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3217
3753
|
/**
|
|
3218
3754
|
* The level of commitment desired when querying state
|
|
3219
3755
|
* <pre>
|
|
@@ -3225,11 +3761,11 @@ function notificationResultAndContext(value) {
|
|
|
3225
3761
|
|
|
3226
3762
|
|
|
3227
3763
|
const GetInflationGovernorResult = type({
|
|
3228
|
-
foundation: number
|
|
3229
|
-
foundationTerm: number
|
|
3230
|
-
initial: number
|
|
3231
|
-
taper: number
|
|
3232
|
-
terminal: number
|
|
3764
|
+
foundation: number(),
|
|
3765
|
+
foundationTerm: number(),
|
|
3766
|
+
initial: number(),
|
|
3767
|
+
taper: number(),
|
|
3768
|
+
terminal: number()
|
|
3233
3769
|
});
|
|
3234
3770
|
/**
|
|
3235
3771
|
* The inflation reward for an epoch
|
|
@@ -3239,36 +3775,36 @@ const GetInflationGovernorResult = type({
|
|
|
3239
3775
|
* Expected JSON RPC response for the "getInflationReward" message
|
|
3240
3776
|
*/
|
|
3241
3777
|
const GetInflationRewardResult = jsonRpcResult(array(nullable(type({
|
|
3242
|
-
epoch: number
|
|
3243
|
-
effectiveSlot: number
|
|
3244
|
-
amount: number
|
|
3245
|
-
postBalance: number
|
|
3778
|
+
epoch: number(),
|
|
3779
|
+
effectiveSlot: number(),
|
|
3780
|
+
amount: number(),
|
|
3781
|
+
postBalance: number()
|
|
3246
3782
|
}))));
|
|
3247
3783
|
/**
|
|
3248
3784
|
* Information about the current epoch
|
|
3249
3785
|
*/
|
|
3250
3786
|
|
|
3251
3787
|
const GetEpochInfoResult = type({
|
|
3252
|
-
epoch: number
|
|
3253
|
-
slotIndex: number
|
|
3254
|
-
slotsInEpoch: number
|
|
3255
|
-
absoluteSlot: number
|
|
3256
|
-
blockHeight: optional(number
|
|
3257
|
-
transactionCount: optional(number
|
|
3788
|
+
epoch: number(),
|
|
3789
|
+
slotIndex: number(),
|
|
3790
|
+
slotsInEpoch: number(),
|
|
3791
|
+
absoluteSlot: number(),
|
|
3792
|
+
blockHeight: optional(number()),
|
|
3793
|
+
transactionCount: optional(number())
|
|
3258
3794
|
});
|
|
3259
3795
|
const GetEpochScheduleResult = type({
|
|
3260
|
-
slotsPerEpoch: number
|
|
3261
|
-
leaderScheduleSlotOffset: number
|
|
3796
|
+
slotsPerEpoch: number(),
|
|
3797
|
+
leaderScheduleSlotOffset: number(),
|
|
3262
3798
|
warmup: boolean(),
|
|
3263
|
-
firstNormalEpoch: number
|
|
3264
|
-
firstNormalSlot: number
|
|
3799
|
+
firstNormalEpoch: number(),
|
|
3800
|
+
firstNormalSlot: number()
|
|
3265
3801
|
});
|
|
3266
3802
|
/**
|
|
3267
3803
|
* Leader schedule
|
|
3268
3804
|
* (see https://docs.solana.com/terminology#leader-schedule)
|
|
3269
3805
|
*/
|
|
3270
3806
|
|
|
3271
|
-
const GetLeaderScheduleResult = record(string(), array(number
|
|
3807
|
+
const GetLeaderScheduleResult = record(string(), array(number()));
|
|
3272
3808
|
/**
|
|
3273
3809
|
* Transaction error or null
|
|
3274
3810
|
*/
|
|
@@ -3292,7 +3828,7 @@ const SignatureReceivedResult = literal('receivedSignature');
|
|
|
3292
3828
|
|
|
3293
3829
|
const VersionResult = type({
|
|
3294
3830
|
'solana-core': string(),
|
|
3295
|
-
'feature-set': optional(number
|
|
3831
|
+
'feature-set': optional(number())
|
|
3296
3832
|
});
|
|
3297
3833
|
const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(type({
|
|
3298
3834
|
err: nullable(union([type({}), string()])),
|
|
@@ -3300,11 +3836,11 @@ const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(type({
|
|
|
3300
3836
|
accounts: optional(nullable(array(nullable(type({
|
|
3301
3837
|
executable: boolean(),
|
|
3302
3838
|
owner: string(),
|
|
3303
|
-
lamports: number
|
|
3839
|
+
lamports: number(),
|
|
3304
3840
|
data: array(string()),
|
|
3305
|
-
rentEpoch: optional(number
|
|
3841
|
+
rentEpoch: optional(number())
|
|
3306
3842
|
}))))),
|
|
3307
|
-
unitsConsumed: optional(number
|
|
3843
|
+
unitsConsumed: optional(number()),
|
|
3308
3844
|
returnData: optional(nullable(type({
|
|
3309
3845
|
programId: string(),
|
|
3310
3846
|
data: tuple([string(), literal('base64')])
|
|
@@ -3315,18 +3851,25 @@ const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(type({
|
|
|
3315
3851
|
* Expected JSON RPC response for the "getBlockProduction" message
|
|
3316
3852
|
*/
|
|
3317
3853
|
const BlockProductionResponseStruct = jsonRpcResultAndContext(type({
|
|
3318
|
-
byIdentity: record(string(), array(number
|
|
3854
|
+
byIdentity: record(string(), array(number())),
|
|
3319
3855
|
range: type({
|
|
3320
|
-
firstSlot: number
|
|
3321
|
-
lastSlot: number
|
|
3856
|
+
firstSlot: number(),
|
|
3857
|
+
lastSlot: number()
|
|
3322
3858
|
})
|
|
3323
3859
|
}));
|
|
3324
3860
|
/**
|
|
3325
3861
|
* A performance sample
|
|
3326
3862
|
*/
|
|
3327
3863
|
|
|
3328
|
-
function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disableRetryOnRateLimit) {
|
|
3864
|
+
function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disableRetryOnRateLimit, httpAgent) {
|
|
3329
3865
|
const fetch = customFetch ? customFetch : fetchImpl;
|
|
3866
|
+
let agent;
|
|
3867
|
+
|
|
3868
|
+
{
|
|
3869
|
+
if (httpAgent != null) {
|
|
3870
|
+
console.warn('You have supplied an `httpAgent` when creating a `Connection` in a browser environment.' + 'It has been ignored; `httpAgent` is only used in Node environments.');
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3330
3873
|
|
|
3331
3874
|
let fetchWithMiddleware;
|
|
3332
3875
|
|
|
@@ -3344,7 +3887,6 @@ function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disable
|
|
|
3344
3887
|
}
|
|
3345
3888
|
|
|
3346
3889
|
const clientBrowser = new RpcClient(async (request, callback) => {
|
|
3347
|
-
const agent = undefined;
|
|
3348
3890
|
const options = {
|
|
3349
3891
|
method: 'POST',
|
|
3350
3892
|
body: request,
|
|
@@ -3396,7 +3938,6 @@ function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disable
|
|
|
3396
3938
|
}
|
|
3397
3939
|
} catch (err) {
|
|
3398
3940
|
if (err instanceof Error) callback(err);
|
|
3399
|
-
} finally {
|
|
3400
3941
|
}
|
|
3401
3942
|
}, {});
|
|
3402
3943
|
return clientBrowser;
|
|
@@ -3461,7 +4002,7 @@ const GetLeaderScheduleRpcResult = jsonRpcResult(GetLeaderScheduleResult);
|
|
|
3461
4002
|
* Expected JSON RPC response for the "minimumLedgerSlot" and "getFirstAvailableBlock" messages
|
|
3462
4003
|
*/
|
|
3463
4004
|
|
|
3464
|
-
const SlotRpcResult = jsonRpcResult(number
|
|
4005
|
+
const SlotRpcResult = jsonRpcResult(number());
|
|
3465
4006
|
/**
|
|
3466
4007
|
* Supply
|
|
3467
4008
|
*/
|
|
@@ -3470,9 +4011,9 @@ const SlotRpcResult = jsonRpcResult(number$1());
|
|
|
3470
4011
|
* Expected JSON RPC response for the "getSupply" message
|
|
3471
4012
|
*/
|
|
3472
4013
|
const GetSupplyRpcResult = jsonRpcResultAndContext(type({
|
|
3473
|
-
total: number
|
|
3474
|
-
circulating: number
|
|
3475
|
-
nonCirculating: number
|
|
4014
|
+
total: number(),
|
|
4015
|
+
circulating: number(),
|
|
4016
|
+
nonCirculating: number(),
|
|
3476
4017
|
nonCirculatingAccounts: array(PublicKeyFromString)
|
|
3477
4018
|
}));
|
|
3478
4019
|
/**
|
|
@@ -3485,8 +4026,8 @@ const GetSupplyRpcResult = jsonRpcResultAndContext(type({
|
|
|
3485
4026
|
*/
|
|
3486
4027
|
const TokenAmountResult = type({
|
|
3487
4028
|
amount: string(),
|
|
3488
|
-
uiAmount: nullable(number
|
|
3489
|
-
decimals: number
|
|
4029
|
+
uiAmount: nullable(number()),
|
|
4030
|
+
decimals: number(),
|
|
3490
4031
|
uiAmountString: optional(string())
|
|
3491
4032
|
});
|
|
3492
4033
|
/**
|
|
@@ -3499,8 +4040,8 @@ const TokenAmountResult = type({
|
|
|
3499
4040
|
const GetTokenLargestAccountsResult = jsonRpcResultAndContext(array(type({
|
|
3500
4041
|
address: PublicKeyFromString,
|
|
3501
4042
|
amount: string(),
|
|
3502
|
-
uiAmount: nullable(number
|
|
3503
|
-
decimals: number
|
|
4043
|
+
uiAmount: nullable(number()),
|
|
4044
|
+
decimals: number(),
|
|
3504
4045
|
uiAmountString: optional(string())
|
|
3505
4046
|
})));
|
|
3506
4047
|
/**
|
|
@@ -3512,15 +4053,15 @@ const GetTokenAccountsByOwner = jsonRpcResultAndContext(array(type({
|
|
|
3512
4053
|
account: type({
|
|
3513
4054
|
executable: boolean(),
|
|
3514
4055
|
owner: PublicKeyFromString,
|
|
3515
|
-
lamports: number
|
|
4056
|
+
lamports: number(),
|
|
3516
4057
|
data: BufferFromRawAccountData,
|
|
3517
|
-
rentEpoch: number
|
|
4058
|
+
rentEpoch: number()
|
|
3518
4059
|
})
|
|
3519
4060
|
})));
|
|
3520
4061
|
const ParsedAccountDataResult = type({
|
|
3521
4062
|
program: string(),
|
|
3522
4063
|
parsed: unknown(),
|
|
3523
|
-
space: number
|
|
4064
|
+
space: number()
|
|
3524
4065
|
});
|
|
3525
4066
|
/**
|
|
3526
4067
|
* Expected JSON RPC response for the "getTokenAccountsByOwner" message with parsed data
|
|
@@ -3531,9 +4072,9 @@ const GetParsedTokenAccountsByOwner = jsonRpcResultAndContext(array(type({
|
|
|
3531
4072
|
account: type({
|
|
3532
4073
|
executable: boolean(),
|
|
3533
4074
|
owner: PublicKeyFromString,
|
|
3534
|
-
lamports: number
|
|
4075
|
+
lamports: number(),
|
|
3535
4076
|
data: ParsedAccountDataResult,
|
|
3536
|
-
rentEpoch: number
|
|
4077
|
+
rentEpoch: number()
|
|
3537
4078
|
})
|
|
3538
4079
|
})));
|
|
3539
4080
|
/**
|
|
@@ -3544,7 +4085,7 @@ const GetParsedTokenAccountsByOwner = jsonRpcResultAndContext(array(type({
|
|
|
3544
4085
|
* Expected JSON RPC response for the "getLargestAccounts" message
|
|
3545
4086
|
*/
|
|
3546
4087
|
const GetLargestAccountsRpcResult = jsonRpcResultAndContext(array(type({
|
|
3547
|
-
lamports: number
|
|
4088
|
+
lamports: number(),
|
|
3548
4089
|
address: PublicKeyFromString
|
|
3549
4090
|
})));
|
|
3550
4091
|
/**
|
|
@@ -3554,9 +4095,9 @@ const GetLargestAccountsRpcResult = jsonRpcResultAndContext(array(type({
|
|
|
3554
4095
|
const AccountInfoResult = type({
|
|
3555
4096
|
executable: boolean(),
|
|
3556
4097
|
owner: PublicKeyFromString,
|
|
3557
|
-
lamports: number
|
|
4098
|
+
lamports: number(),
|
|
3558
4099
|
data: BufferFromRawAccountData,
|
|
3559
|
-
rentEpoch: number
|
|
4100
|
+
rentEpoch: number()
|
|
3560
4101
|
});
|
|
3561
4102
|
/**
|
|
3562
4103
|
* @internal
|
|
@@ -3580,9 +4121,9 @@ const ParsedOrRawAccountData = coerce(union([instance(Buffer), ParsedAccountData
|
|
|
3580
4121
|
const ParsedAccountInfoResult = type({
|
|
3581
4122
|
executable: boolean(),
|
|
3582
4123
|
owner: PublicKeyFromString,
|
|
3583
|
-
lamports: number
|
|
4124
|
+
lamports: number(),
|
|
3584
4125
|
data: ParsedOrRawAccountData,
|
|
3585
|
-
rentEpoch: number
|
|
4126
|
+
rentEpoch: number()
|
|
3586
4127
|
});
|
|
3587
4128
|
const KeyedParsedAccountInfoResult = type({
|
|
3588
4129
|
pubkey: PublicKeyFromString,
|
|
@@ -3594,8 +4135,8 @@ const KeyedParsedAccountInfoResult = type({
|
|
|
3594
4135
|
|
|
3595
4136
|
const StakeActivationResult = type({
|
|
3596
4137
|
state: union([literal('active'), literal('inactive'), literal('activating'), literal('deactivating')]),
|
|
3597
|
-
active: number
|
|
3598
|
-
inactive: number
|
|
4138
|
+
active: number(),
|
|
4139
|
+
inactive: number()
|
|
3599
4140
|
});
|
|
3600
4141
|
/**
|
|
3601
4142
|
* Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message
|
|
@@ -3603,10 +4144,10 @@ const StakeActivationResult = type({
|
|
|
3603
4144
|
|
|
3604
4145
|
const GetConfirmedSignaturesForAddress2RpcResult = jsonRpcResult(array(type({
|
|
3605
4146
|
signature: string(),
|
|
3606
|
-
slot: number
|
|
4147
|
+
slot: number(),
|
|
3607
4148
|
err: TransactionErrorResult,
|
|
3608
4149
|
memo: nullable(string()),
|
|
3609
|
-
blockTime: optional(nullable(number
|
|
4150
|
+
blockTime: optional(nullable(number()))
|
|
3610
4151
|
})));
|
|
3611
4152
|
/**
|
|
3612
4153
|
* Expected JSON RPC response for the "getSignaturesForAddress" message
|
|
@@ -3614,17 +4155,17 @@ const GetConfirmedSignaturesForAddress2RpcResult = jsonRpcResult(array(type({
|
|
|
3614
4155
|
|
|
3615
4156
|
const GetSignaturesForAddressRpcResult = jsonRpcResult(array(type({
|
|
3616
4157
|
signature: string(),
|
|
3617
|
-
slot: number
|
|
4158
|
+
slot: number(),
|
|
3618
4159
|
err: TransactionErrorResult,
|
|
3619
4160
|
memo: nullable(string()),
|
|
3620
|
-
blockTime: optional(nullable(number
|
|
4161
|
+
blockTime: optional(nullable(number()))
|
|
3621
4162
|
})));
|
|
3622
4163
|
/***
|
|
3623
4164
|
* Expected JSON RPC response for the "accountNotification" message
|
|
3624
4165
|
*/
|
|
3625
4166
|
|
|
3626
4167
|
const AccountNotificationResult = type({
|
|
3627
|
-
subscription: number
|
|
4168
|
+
subscription: number(),
|
|
3628
4169
|
result: notificationResultAndContext(AccountInfoResult)
|
|
3629
4170
|
});
|
|
3630
4171
|
/**
|
|
@@ -3640,7 +4181,7 @@ const ProgramAccountInfoResult = type({
|
|
|
3640
4181
|
*/
|
|
3641
4182
|
|
|
3642
4183
|
const ProgramAccountNotificationResult = type({
|
|
3643
|
-
subscription: number
|
|
4184
|
+
subscription: number(),
|
|
3644
4185
|
result: notificationResultAndContext(ProgramAccountInfoResult)
|
|
3645
4186
|
});
|
|
3646
4187
|
/**
|
|
@@ -3648,16 +4189,16 @@ const ProgramAccountNotificationResult = type({
|
|
|
3648
4189
|
*/
|
|
3649
4190
|
|
|
3650
4191
|
const SlotInfoResult = type({
|
|
3651
|
-
parent: number
|
|
3652
|
-
slot: number
|
|
3653
|
-
root: number
|
|
4192
|
+
parent: number(),
|
|
4193
|
+
slot: number(),
|
|
4194
|
+
root: number()
|
|
3654
4195
|
});
|
|
3655
4196
|
/**
|
|
3656
4197
|
* Expected JSON RPC response for the "slotNotification" message
|
|
3657
4198
|
*/
|
|
3658
4199
|
|
|
3659
4200
|
const SlotNotificationResult = type({
|
|
3660
|
-
subscription: number
|
|
4201
|
+
subscription: number(),
|
|
3661
4202
|
result: SlotInfoResult
|
|
3662
4203
|
});
|
|
3663
4204
|
/**
|
|
@@ -3680,27 +4221,27 @@ const SlotNotificationResult = type({
|
|
|
3680
4221
|
*/
|
|
3681
4222
|
const SlotUpdateResult = union([type({
|
|
3682
4223
|
type: union([literal('firstShredReceived'), literal('completed'), literal('optimisticConfirmation'), literal('root')]),
|
|
3683
|
-
slot: number
|
|
3684
|
-
timestamp: number
|
|
4224
|
+
slot: number(),
|
|
4225
|
+
timestamp: number()
|
|
3685
4226
|
}), type({
|
|
3686
4227
|
type: literal('createdBank'),
|
|
3687
|
-
parent: number
|
|
3688
|
-
slot: number
|
|
3689
|
-
timestamp: number
|
|
4228
|
+
parent: number(),
|
|
4229
|
+
slot: number(),
|
|
4230
|
+
timestamp: number()
|
|
3690
4231
|
}), type({
|
|
3691
4232
|
type: literal('frozen'),
|
|
3692
|
-
slot: number
|
|
3693
|
-
timestamp: number
|
|
4233
|
+
slot: number(),
|
|
4234
|
+
timestamp: number(),
|
|
3694
4235
|
stats: type({
|
|
3695
|
-
numTransactionEntries: number
|
|
3696
|
-
numSuccessfulTransactions: number
|
|
3697
|
-
numFailedTransactions: number
|
|
3698
|
-
maxTransactionsPerEntry: number
|
|
4236
|
+
numTransactionEntries: number(),
|
|
4237
|
+
numSuccessfulTransactions: number(),
|
|
4238
|
+
numFailedTransactions: number(),
|
|
4239
|
+
maxTransactionsPerEntry: number()
|
|
3699
4240
|
})
|
|
3700
4241
|
}), type({
|
|
3701
4242
|
type: literal('dead'),
|
|
3702
|
-
slot: number
|
|
3703
|
-
timestamp: number
|
|
4243
|
+
slot: number(),
|
|
4244
|
+
timestamp: number(),
|
|
3704
4245
|
err: string()
|
|
3705
4246
|
})]);
|
|
3706
4247
|
/**
|
|
@@ -3708,7 +4249,7 @@ const SlotUpdateResult = union([type({
|
|
|
3708
4249
|
*/
|
|
3709
4250
|
|
|
3710
4251
|
const SlotUpdateNotificationResult = type({
|
|
3711
|
-
subscription: number
|
|
4252
|
+
subscription: number(),
|
|
3712
4253
|
result: SlotUpdateResult
|
|
3713
4254
|
});
|
|
3714
4255
|
/**
|
|
@@ -3716,7 +4257,7 @@ const SlotUpdateNotificationResult = type({
|
|
|
3716
4257
|
*/
|
|
3717
4258
|
|
|
3718
4259
|
const SignatureNotificationResult = type({
|
|
3719
|
-
subscription: number
|
|
4260
|
+
subscription: number(),
|
|
3720
4261
|
result: notificationResultAndContext(union([SignatureStatusResult, SignatureReceivedResult]))
|
|
3721
4262
|
});
|
|
3722
4263
|
/**
|
|
@@ -3724,8 +4265,8 @@ const SignatureNotificationResult = type({
|
|
|
3724
4265
|
*/
|
|
3725
4266
|
|
|
3726
4267
|
const RootNotificationResult = type({
|
|
3727
|
-
subscription: number
|
|
3728
|
-
result: number
|
|
4268
|
+
subscription: number(),
|
|
4269
|
+
result: number()
|
|
3729
4270
|
});
|
|
3730
4271
|
const ContactInfoResult = type({
|
|
3731
4272
|
pubkey: string(),
|
|
@@ -3737,12 +4278,12 @@ const ContactInfoResult = type({
|
|
|
3737
4278
|
const VoteAccountInfoResult = type({
|
|
3738
4279
|
votePubkey: string(),
|
|
3739
4280
|
nodePubkey: string(),
|
|
3740
|
-
activatedStake: number
|
|
4281
|
+
activatedStake: number(),
|
|
3741
4282
|
epochVoteAccount: boolean(),
|
|
3742
|
-
epochCredits: array(tuple([number
|
|
3743
|
-
commission: number
|
|
3744
|
-
lastVote: number
|
|
3745
|
-
rootSlot: nullable(number
|
|
4283
|
+
epochCredits: array(tuple([number(), number(), number()])),
|
|
4284
|
+
commission: number(),
|
|
4285
|
+
lastVote: number(),
|
|
4286
|
+
rootSlot: nullable(number())
|
|
3746
4287
|
});
|
|
3747
4288
|
/**
|
|
3748
4289
|
* Expected JSON RPC response for the "getVoteAccounts" message
|
|
@@ -3754,8 +4295,8 @@ const GetVoteAccounts = jsonRpcResult(type({
|
|
|
3754
4295
|
}));
|
|
3755
4296
|
const ConfirmationStatus = union([literal('processed'), literal('confirmed'), literal('finalized')]);
|
|
3756
4297
|
const SignatureStatusResponse = type({
|
|
3757
|
-
slot: number
|
|
3758
|
-
confirmations: nullable(number
|
|
4298
|
+
slot: number(),
|
|
4299
|
+
confirmations: nullable(number()),
|
|
3759
4300
|
err: TransactionErrorResult,
|
|
3760
4301
|
confirmationStatus: optional(ConfirmationStatus)
|
|
3761
4302
|
});
|
|
@@ -3768,24 +4309,40 @@ const GetSignatureStatusesRpcResult = jsonRpcResultAndContext(array(nullable(Sig
|
|
|
3768
4309
|
* Expected JSON RPC response for the "getMinimumBalanceForRentExemption" message
|
|
3769
4310
|
*/
|
|
3770
4311
|
|
|
3771
|
-
const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult(number
|
|
4312
|
+
const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult(number());
|
|
4313
|
+
const AddressTableLookupStruct = type({
|
|
4314
|
+
accountKey: PublicKeyFromString,
|
|
4315
|
+
writableIndexes: array(number()),
|
|
4316
|
+
readonlyIndexes: array(number())
|
|
4317
|
+
});
|
|
3772
4318
|
const ConfirmedTransactionResult = type({
|
|
3773
4319
|
signatures: array(string()),
|
|
3774
4320
|
message: type({
|
|
3775
4321
|
accountKeys: array(string()),
|
|
3776
4322
|
header: type({
|
|
3777
|
-
numRequiredSignatures: number
|
|
3778
|
-
numReadonlySignedAccounts: number
|
|
3779
|
-
numReadonlyUnsignedAccounts: number
|
|
4323
|
+
numRequiredSignatures: number(),
|
|
4324
|
+
numReadonlySignedAccounts: number(),
|
|
4325
|
+
numReadonlyUnsignedAccounts: number()
|
|
3780
4326
|
}),
|
|
3781
4327
|
instructions: array(type({
|
|
3782
|
-
accounts: array(number
|
|
4328
|
+
accounts: array(number()),
|
|
3783
4329
|
data: string(),
|
|
3784
|
-
programIdIndex: number
|
|
4330
|
+
programIdIndex: number()
|
|
3785
4331
|
})),
|
|
3786
|
-
recentBlockhash: string()
|
|
4332
|
+
recentBlockhash: string(),
|
|
4333
|
+
addressTableLookups: optional(array(AddressTableLookupStruct))
|
|
3787
4334
|
})
|
|
3788
4335
|
});
|
|
4336
|
+
const AnnotatedAccountKey = type({
|
|
4337
|
+
pubkey: PublicKeyFromString,
|
|
4338
|
+
signer: boolean(),
|
|
4339
|
+
writable: boolean(),
|
|
4340
|
+
source: optional(union([literal('transaction'), literal('lookupTable')]))
|
|
4341
|
+
});
|
|
4342
|
+
const ConfirmedTransactionAccountsModeResult = type({
|
|
4343
|
+
accountKeys: array(AnnotatedAccountKey),
|
|
4344
|
+
signatures: array(string())
|
|
4345
|
+
});
|
|
3789
4346
|
const ParsedInstructionResult = type({
|
|
3790
4347
|
parsed: unknown(),
|
|
3791
4348
|
program: string(),
|
|
@@ -3820,17 +4377,14 @@ const ParsedOrRawInstruction = coerce(InstructionResult, UnknownInstructionResul
|
|
|
3820
4377
|
const ParsedConfirmedTransactionResult = type({
|
|
3821
4378
|
signatures: array(string()),
|
|
3822
4379
|
message: type({
|
|
3823
|
-
accountKeys: array(
|
|
3824
|
-
pubkey: PublicKeyFromString,
|
|
3825
|
-
signer: boolean(),
|
|
3826
|
-
writable: boolean()
|
|
3827
|
-
})),
|
|
4380
|
+
accountKeys: array(AnnotatedAccountKey),
|
|
3828
4381
|
instructions: array(ParsedOrRawInstruction),
|
|
3829
|
-
recentBlockhash: string()
|
|
4382
|
+
recentBlockhash: string(),
|
|
4383
|
+
addressTableLookups: optional(nullable(array(AddressTableLookupStruct)))
|
|
3830
4384
|
})
|
|
3831
4385
|
});
|
|
3832
4386
|
const TokenBalanceResult = type({
|
|
3833
|
-
accountIndex: number
|
|
4387
|
+
accountIndex: number(),
|
|
3834
4388
|
mint: string(),
|
|
3835
4389
|
owner: optional(string()),
|
|
3836
4390
|
uiTokenAmount: TokenAmountResult
|
|
@@ -3845,21 +4399,22 @@ const LoadedAddressesResult = type({
|
|
|
3845
4399
|
|
|
3846
4400
|
const ConfirmedTransactionMetaResult = type({
|
|
3847
4401
|
err: TransactionErrorResult,
|
|
3848
|
-
fee: number
|
|
4402
|
+
fee: number(),
|
|
3849
4403
|
innerInstructions: optional(nullable(array(type({
|
|
3850
|
-
index: number
|
|
4404
|
+
index: number(),
|
|
3851
4405
|
instructions: array(type({
|
|
3852
|
-
accounts: array(number
|
|
4406
|
+
accounts: array(number()),
|
|
3853
4407
|
data: string(),
|
|
3854
|
-
programIdIndex: number
|
|
4408
|
+
programIdIndex: number()
|
|
3855
4409
|
}))
|
|
3856
4410
|
})))),
|
|
3857
|
-
preBalances: array(number
|
|
3858
|
-
postBalances: array(number
|
|
4411
|
+
preBalances: array(number()),
|
|
4412
|
+
postBalances: array(number()),
|
|
3859
4413
|
logMessages: optional(nullable(array(string()))),
|
|
3860
4414
|
preTokenBalances: optional(nullable(array(TokenBalanceResult))),
|
|
3861
4415
|
postTokenBalances: optional(nullable(array(TokenBalanceResult))),
|
|
3862
|
-
loadedAddresses: optional(LoadedAddressesResult)
|
|
4416
|
+
loadedAddresses: optional(LoadedAddressesResult),
|
|
4417
|
+
computeUnitsConsumed: optional(number())
|
|
3863
4418
|
});
|
|
3864
4419
|
/**
|
|
3865
4420
|
* @internal
|
|
@@ -3867,17 +4422,27 @@ const ConfirmedTransactionMetaResult = type({
|
|
|
3867
4422
|
|
|
3868
4423
|
const ParsedConfirmedTransactionMetaResult = type({
|
|
3869
4424
|
err: TransactionErrorResult,
|
|
3870
|
-
fee: number
|
|
4425
|
+
fee: number(),
|
|
3871
4426
|
innerInstructions: optional(nullable(array(type({
|
|
3872
|
-
index: number
|
|
4427
|
+
index: number(),
|
|
3873
4428
|
instructions: array(ParsedOrRawInstruction)
|
|
3874
4429
|
})))),
|
|
3875
|
-
preBalances: array(number
|
|
3876
|
-
postBalances: array(number
|
|
4430
|
+
preBalances: array(number()),
|
|
4431
|
+
postBalances: array(number()),
|
|
3877
4432
|
logMessages: optional(nullable(array(string()))),
|
|
3878
4433
|
preTokenBalances: optional(nullable(array(TokenBalanceResult))),
|
|
3879
4434
|
postTokenBalances: optional(nullable(array(TokenBalanceResult))),
|
|
3880
|
-
loadedAddresses: optional(LoadedAddressesResult)
|
|
4435
|
+
loadedAddresses: optional(LoadedAddressesResult),
|
|
4436
|
+
computeUnitsConsumed: optional(number())
|
|
4437
|
+
});
|
|
4438
|
+
const TransactionVersionStruct = union([literal(0), literal('legacy')]);
|
|
4439
|
+
/** @internal */
|
|
4440
|
+
|
|
4441
|
+
const RewardsResult = type({
|
|
4442
|
+
pubkey: string(),
|
|
4443
|
+
lamports: number(),
|
|
4444
|
+
postBalance: nullable(number()),
|
|
4445
|
+
rewardType: nullable(string())
|
|
3881
4446
|
});
|
|
3882
4447
|
/**
|
|
3883
4448
|
* Expected JSON RPC response for the "getBlock" message
|
|
@@ -3886,19 +4451,90 @@ const ParsedConfirmedTransactionMetaResult = type({
|
|
|
3886
4451
|
const GetBlockRpcResult = jsonRpcResult(nullable(type({
|
|
3887
4452
|
blockhash: string(),
|
|
3888
4453
|
previousBlockhash: string(),
|
|
3889
|
-
parentSlot: number
|
|
4454
|
+
parentSlot: number(),
|
|
3890
4455
|
transactions: array(type({
|
|
3891
4456
|
transaction: ConfirmedTransactionResult,
|
|
3892
|
-
meta: nullable(ConfirmedTransactionMetaResult)
|
|
4457
|
+
meta: nullable(ConfirmedTransactionMetaResult),
|
|
4458
|
+
version: optional(TransactionVersionStruct)
|
|
4459
|
+
})),
|
|
4460
|
+
rewards: optional(array(RewardsResult)),
|
|
4461
|
+
blockTime: nullable(number()),
|
|
4462
|
+
blockHeight: nullable(number())
|
|
4463
|
+
})));
|
|
4464
|
+
/**
|
|
4465
|
+
* Expected JSON RPC response for the "getBlock" message when `transactionDetails` is `none`
|
|
4466
|
+
*/
|
|
4467
|
+
|
|
4468
|
+
const GetNoneModeBlockRpcResult = jsonRpcResult(nullable(type({
|
|
4469
|
+
blockhash: string(),
|
|
4470
|
+
previousBlockhash: string(),
|
|
4471
|
+
parentSlot: number(),
|
|
4472
|
+
rewards: optional(array(RewardsResult)),
|
|
4473
|
+
blockTime: nullable(number()),
|
|
4474
|
+
blockHeight: nullable(number())
|
|
4475
|
+
})));
|
|
4476
|
+
/**
|
|
4477
|
+
* Expected JSON RPC response for the "getBlock" message when `transactionDetails` is `accounts`
|
|
4478
|
+
*/
|
|
4479
|
+
|
|
4480
|
+
const GetAccountsModeBlockRpcResult = jsonRpcResult(nullable(type({
|
|
4481
|
+
blockhash: string(),
|
|
4482
|
+
previousBlockhash: string(),
|
|
4483
|
+
parentSlot: number(),
|
|
4484
|
+
transactions: array(type({
|
|
4485
|
+
transaction: ConfirmedTransactionAccountsModeResult,
|
|
4486
|
+
meta: nullable(ConfirmedTransactionMetaResult),
|
|
4487
|
+
version: optional(TransactionVersionStruct)
|
|
4488
|
+
})),
|
|
4489
|
+
rewards: optional(array(RewardsResult)),
|
|
4490
|
+
blockTime: nullable(number()),
|
|
4491
|
+
blockHeight: nullable(number())
|
|
4492
|
+
})));
|
|
4493
|
+
/**
|
|
4494
|
+
* Expected parsed JSON RPC response for the "getBlock" message
|
|
4495
|
+
*/
|
|
4496
|
+
|
|
4497
|
+
const GetParsedBlockRpcResult = jsonRpcResult(nullable(type({
|
|
4498
|
+
blockhash: string(),
|
|
4499
|
+
previousBlockhash: string(),
|
|
4500
|
+
parentSlot: number(),
|
|
4501
|
+
transactions: array(type({
|
|
4502
|
+
transaction: ParsedConfirmedTransactionResult,
|
|
4503
|
+
meta: nullable(ParsedConfirmedTransactionMetaResult),
|
|
4504
|
+
version: optional(TransactionVersionStruct)
|
|
4505
|
+
})),
|
|
4506
|
+
rewards: optional(array(RewardsResult)),
|
|
4507
|
+
blockTime: nullable(number()),
|
|
4508
|
+
blockHeight: nullable(number())
|
|
4509
|
+
})));
|
|
4510
|
+
/**
|
|
4511
|
+
* Expected parsed JSON RPC response for the "getBlock" message when `transactionDetails` is `accounts`
|
|
4512
|
+
*/
|
|
4513
|
+
|
|
4514
|
+
const GetParsedAccountsModeBlockRpcResult = jsonRpcResult(nullable(type({
|
|
4515
|
+
blockhash: string(),
|
|
4516
|
+
previousBlockhash: string(),
|
|
4517
|
+
parentSlot: number(),
|
|
4518
|
+
transactions: array(type({
|
|
4519
|
+
transaction: ConfirmedTransactionAccountsModeResult,
|
|
4520
|
+
meta: nullable(ParsedConfirmedTransactionMetaResult),
|
|
4521
|
+
version: optional(TransactionVersionStruct)
|
|
3893
4522
|
})),
|
|
3894
|
-
rewards: optional(array(
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
4523
|
+
rewards: optional(array(RewardsResult)),
|
|
4524
|
+
blockTime: nullable(number()),
|
|
4525
|
+
blockHeight: nullable(number())
|
|
4526
|
+
})));
|
|
4527
|
+
/**
|
|
4528
|
+
* Expected parsed JSON RPC response for the "getBlock" message when `transactionDetails` is `none`
|
|
4529
|
+
*/
|
|
4530
|
+
|
|
4531
|
+
const GetParsedNoneModeBlockRpcResult = jsonRpcResult(nullable(type({
|
|
4532
|
+
blockhash: string(),
|
|
4533
|
+
previousBlockhash: string(),
|
|
4534
|
+
parentSlot: number(),
|
|
4535
|
+
rewards: optional(array(RewardsResult)),
|
|
4536
|
+
blockTime: nullable(number()),
|
|
4537
|
+
blockHeight: nullable(number())
|
|
3902
4538
|
})));
|
|
3903
4539
|
/**
|
|
3904
4540
|
* Expected JSON RPC response for the "getConfirmedBlock" message
|
|
@@ -3909,18 +4545,13 @@ const GetBlockRpcResult = jsonRpcResult(nullable(type({
|
|
|
3909
4545
|
const GetConfirmedBlockRpcResult = jsonRpcResult(nullable(type({
|
|
3910
4546
|
blockhash: string(),
|
|
3911
4547
|
previousBlockhash: string(),
|
|
3912
|
-
parentSlot: number
|
|
4548
|
+
parentSlot: number(),
|
|
3913
4549
|
transactions: array(type({
|
|
3914
4550
|
transaction: ConfirmedTransactionResult,
|
|
3915
4551
|
meta: nullable(ConfirmedTransactionMetaResult)
|
|
3916
4552
|
})),
|
|
3917
|
-
rewards: optional(array(
|
|
3918
|
-
|
|
3919
|
-
lamports: number$1(),
|
|
3920
|
-
postBalance: nullable(number$1()),
|
|
3921
|
-
rewardType: nullable(string())
|
|
3922
|
-
}))),
|
|
3923
|
-
blockTime: nullable(number$1())
|
|
4553
|
+
rewards: optional(array(RewardsResult)),
|
|
4554
|
+
blockTime: nullable(number())
|
|
3924
4555
|
})));
|
|
3925
4556
|
/**
|
|
3926
4557
|
* Expected JSON RPC response for the "getBlock" message
|
|
@@ -3929,29 +4560,31 @@ const GetConfirmedBlockRpcResult = jsonRpcResult(nullable(type({
|
|
|
3929
4560
|
const GetBlockSignaturesRpcResult = jsonRpcResult(nullable(type({
|
|
3930
4561
|
blockhash: string(),
|
|
3931
4562
|
previousBlockhash: string(),
|
|
3932
|
-
parentSlot: number
|
|
4563
|
+
parentSlot: number(),
|
|
3933
4564
|
signatures: array(string()),
|
|
3934
|
-
blockTime: nullable(number
|
|
4565
|
+
blockTime: nullable(number())
|
|
3935
4566
|
})));
|
|
3936
4567
|
/**
|
|
3937
4568
|
* Expected JSON RPC response for the "getTransaction" message
|
|
3938
4569
|
*/
|
|
3939
4570
|
|
|
3940
4571
|
const GetTransactionRpcResult = jsonRpcResult(nullable(type({
|
|
3941
|
-
slot: number
|
|
4572
|
+
slot: number(),
|
|
3942
4573
|
meta: ConfirmedTransactionMetaResult,
|
|
3943
|
-
blockTime: optional(nullable(number
|
|
3944
|
-
transaction: ConfirmedTransactionResult
|
|
4574
|
+
blockTime: optional(nullable(number())),
|
|
4575
|
+
transaction: ConfirmedTransactionResult,
|
|
4576
|
+
version: optional(TransactionVersionStruct)
|
|
3945
4577
|
})));
|
|
3946
4578
|
/**
|
|
3947
4579
|
* Expected parsed JSON RPC response for the "getTransaction" message
|
|
3948
4580
|
*/
|
|
3949
4581
|
|
|
3950
4582
|
const GetParsedTransactionRpcResult = jsonRpcResult(nullable(type({
|
|
3951
|
-
slot: number
|
|
4583
|
+
slot: number(),
|
|
3952
4584
|
transaction: ParsedConfirmedTransactionResult,
|
|
3953
4585
|
meta: nullable(ParsedConfirmedTransactionMetaResult),
|
|
3954
|
-
blockTime: optional(nullable(number
|
|
4586
|
+
blockTime: optional(nullable(number())),
|
|
4587
|
+
version: optional(TransactionVersionStruct)
|
|
3955
4588
|
})));
|
|
3956
4589
|
/**
|
|
3957
4590
|
* Expected JSON RPC response for the "getRecentBlockhash" message
|
|
@@ -3962,7 +4595,7 @@ const GetParsedTransactionRpcResult = jsonRpcResult(nullable(type({
|
|
|
3962
4595
|
const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(type({
|
|
3963
4596
|
blockhash: string(),
|
|
3964
4597
|
feeCalculator: type({
|
|
3965
|
-
lamportsPerSignature: number
|
|
4598
|
+
lamportsPerSignature: number()
|
|
3966
4599
|
})
|
|
3967
4600
|
}));
|
|
3968
4601
|
/**
|
|
@@ -3971,13 +4604,13 @@ const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(type({
|
|
|
3971
4604
|
|
|
3972
4605
|
const GetLatestBlockhashRpcResult = jsonRpcResultAndContext(type({
|
|
3973
4606
|
blockhash: string(),
|
|
3974
|
-
lastValidBlockHeight: number
|
|
4607
|
+
lastValidBlockHeight: number()
|
|
3975
4608
|
}));
|
|
3976
4609
|
const PerfSampleResult = type({
|
|
3977
|
-
slot: number
|
|
3978
|
-
numTransactions: number
|
|
3979
|
-
numSlots: number
|
|
3980
|
-
samplePeriodSecs: number
|
|
4610
|
+
slot: number(),
|
|
4611
|
+
numTransactions: number(),
|
|
4612
|
+
numSlots: number(),
|
|
4613
|
+
samplePeriodSecs: number()
|
|
3981
4614
|
});
|
|
3982
4615
|
/*
|
|
3983
4616
|
* Expected JSON RPC response for "getRecentPerformanceSamples" message
|
|
@@ -3990,7 +4623,7 @@ const GetRecentPerformanceSamplesRpcResult = jsonRpcResult(array(PerfSampleResul
|
|
|
3990
4623
|
|
|
3991
4624
|
const GetFeeCalculatorRpcResult = jsonRpcResultAndContext(nullable(type({
|
|
3992
4625
|
feeCalculator: type({
|
|
3993
|
-
lamportsPerSignature: number
|
|
4626
|
+
lamportsPerSignature: number()
|
|
3994
4627
|
})
|
|
3995
4628
|
})));
|
|
3996
4629
|
/**
|
|
@@ -4024,7 +4657,7 @@ const LogsResult = type({
|
|
|
4024
4657
|
*/
|
|
4025
4658
|
const LogsNotificationResult = type({
|
|
4026
4659
|
result: notificationResultAndContext(LogsResult),
|
|
4027
|
-
subscription: number
|
|
4660
|
+
subscription: number()
|
|
4028
4661
|
});
|
|
4029
4662
|
/**
|
|
4030
4663
|
* Filter for log subscriptions.
|
|
@@ -4083,6 +4716,10 @@ class Connection {
|
|
|
4083
4716
|
|
|
4084
4717
|
/** @internal */
|
|
4085
4718
|
|
|
4719
|
+
/** @internal */
|
|
4720
|
+
|
|
4721
|
+
/** @internal */
|
|
4722
|
+
|
|
4086
4723
|
/**
|
|
4087
4724
|
* Special case.
|
|
4088
4725
|
* After a signature is processed, RPCs automatically dispose of the
|
|
@@ -4128,6 +4765,8 @@ class Connection {
|
|
|
4128
4765
|
};
|
|
4129
4766
|
this._nextClientSubscriptionId = 0;
|
|
4130
4767
|
this._subscriptionDisposeFunctionsByClientSubscriptionId = {};
|
|
4768
|
+
this._subscriptionHashByClientSubscriptionId = {};
|
|
4769
|
+
this._subscriptionStateChangeCallbacksByHash = {};
|
|
4131
4770
|
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
4132
4771
|
this._subscriptionsByHash = {};
|
|
4133
4772
|
this._subscriptionsAutoDisposedByRpc = new Set();
|
|
@@ -4136,6 +4775,7 @@ class Connection {
|
|
|
4136
4775
|
let fetch;
|
|
4137
4776
|
let fetchMiddleware;
|
|
4138
4777
|
let disableRetryOnRateLimit;
|
|
4778
|
+
let httpAgent;
|
|
4139
4779
|
|
|
4140
4780
|
if (commitmentOrConfig && typeof commitmentOrConfig === 'string') {
|
|
4141
4781
|
this._commitment = commitmentOrConfig;
|
|
@@ -4147,11 +4787,12 @@ class Connection {
|
|
|
4147
4787
|
fetch = commitmentOrConfig.fetch;
|
|
4148
4788
|
fetchMiddleware = commitmentOrConfig.fetchMiddleware;
|
|
4149
4789
|
disableRetryOnRateLimit = commitmentOrConfig.disableRetryOnRateLimit;
|
|
4790
|
+
httpAgent = commitmentOrConfig.httpAgent;
|
|
4150
4791
|
}
|
|
4151
4792
|
|
|
4152
4793
|
this._rpcEndpoint = assertEndpointUrl(endpoint);
|
|
4153
4794
|
this._rpcWsEndpoint = wsEndpoint || makeWebsocketUrl(endpoint);
|
|
4154
|
-
this._rpcClient = createRpcClient(endpoint, httpHeaders, fetch, fetchMiddleware, disableRetryOnRateLimit);
|
|
4795
|
+
this._rpcClient = createRpcClient(endpoint, httpHeaders, fetch, fetchMiddleware, disableRetryOnRateLimit, httpAgent);
|
|
4155
4796
|
this._rpcRequest = createRpcRequest(this._rpcClient);
|
|
4156
4797
|
this._rpcBatchRequest = createRpcBatchRequest(this._rpcClient);
|
|
4157
4798
|
this._rpcWebSocket = new Client(this._rpcWsEndpoint, {
|
|
@@ -4212,7 +4853,7 @@ class Connection {
|
|
|
4212
4853
|
, config);
|
|
4213
4854
|
|
|
4214
4855
|
const unsafeRes = await this._rpcRequest('getBalance', args);
|
|
4215
|
-
const res = create(unsafeRes, jsonRpcResultAndContext(number
|
|
4856
|
+
const res = create(unsafeRes, jsonRpcResultAndContext(number()));
|
|
4216
4857
|
|
|
4217
4858
|
if ('error' in res) {
|
|
4218
4859
|
throw new SolanaJSONRPCError(res.error, `failed to get balance for ${publicKey.toBase58()}`);
|
|
@@ -4237,7 +4878,7 @@ class Connection {
|
|
|
4237
4878
|
|
|
4238
4879
|
async getBlockTime(slot) {
|
|
4239
4880
|
const unsafeRes = await this._rpcRequest('getBlockTime', [slot]);
|
|
4240
|
-
const res = create(unsafeRes, jsonRpcResult(nullable(number
|
|
4881
|
+
const res = create(unsafeRes, jsonRpcResult(nullable(number())));
|
|
4241
4882
|
|
|
4242
4883
|
if ('error' in res) {
|
|
4243
4884
|
throw new SolanaJSONRPCError(res.error, `failed to get block time for slot ${slot}`);
|
|
@@ -4253,7 +4894,7 @@ class Connection {
|
|
|
4253
4894
|
|
|
4254
4895
|
async getMinimumLedgerSlot() {
|
|
4255
4896
|
const unsafeRes = await this._rpcRequest('minimumLedgerSlot', []);
|
|
4256
|
-
const res = create(unsafeRes, jsonRpcResult(number
|
|
4897
|
+
const res = create(unsafeRes, jsonRpcResult(number()));
|
|
4257
4898
|
|
|
4258
4899
|
if ('error' in res) {
|
|
4259
4900
|
throw new SolanaJSONRPCError(res.error, 'failed to get minimum ledger slot');
|
|
@@ -4506,6 +5147,29 @@ class Connection {
|
|
|
4506
5147
|
*/
|
|
4507
5148
|
|
|
4508
5149
|
|
|
5150
|
+
async getMultipleParsedAccounts(publicKeys, rawConfig) {
|
|
5151
|
+
const {
|
|
5152
|
+
commitment,
|
|
5153
|
+
config
|
|
5154
|
+
} = extractCommitmentFromConfig(rawConfig);
|
|
5155
|
+
const keys = publicKeys.map(key => key.toBase58());
|
|
5156
|
+
|
|
5157
|
+
const args = this._buildArgs([keys], commitment, 'jsonParsed', config);
|
|
5158
|
+
|
|
5159
|
+
const unsafeRes = await this._rpcRequest('getMultipleAccounts', args);
|
|
5160
|
+
const res = create(unsafeRes, jsonRpcResultAndContext(array(nullable(ParsedAccountInfoResult))));
|
|
5161
|
+
|
|
5162
|
+
if ('error' in res) {
|
|
5163
|
+
throw new SolanaJSONRPCError(res.error, `failed to get info for accounts ${keys}`);
|
|
5164
|
+
}
|
|
5165
|
+
|
|
5166
|
+
return res.result;
|
|
5167
|
+
}
|
|
5168
|
+
/**
|
|
5169
|
+
* Fetch all the account info for multiple accounts specified by an array of public keys, return with context
|
|
5170
|
+
*/
|
|
5171
|
+
|
|
5172
|
+
|
|
4509
5173
|
async getMultipleAccountsInfoAndContext(publicKeys, commitmentOrConfig) {
|
|
4510
5174
|
const {
|
|
4511
5175
|
commitment,
|
|
@@ -4538,193 +5202,515 @@ class Connection {
|
|
|
4538
5202
|
*/
|
|
4539
5203
|
|
|
4540
5204
|
|
|
4541
|
-
async getStakeActivation(publicKey, commitmentOrConfig, epoch) {
|
|
5205
|
+
async getStakeActivation(publicKey, commitmentOrConfig, epoch) {
|
|
5206
|
+
const {
|
|
5207
|
+
commitment,
|
|
5208
|
+
config
|
|
5209
|
+
} = extractCommitmentFromConfig(commitmentOrConfig);
|
|
5210
|
+
|
|
5211
|
+
const args = this._buildArgs([publicKey.toBase58()], commitment, undefined
|
|
5212
|
+
/* encoding */
|
|
5213
|
+
, { ...config,
|
|
5214
|
+
epoch: epoch != null ? epoch : config === null || config === void 0 ? void 0 : config.epoch
|
|
5215
|
+
});
|
|
5216
|
+
|
|
5217
|
+
const unsafeRes = await this._rpcRequest('getStakeActivation', args);
|
|
5218
|
+
const res = create(unsafeRes, jsonRpcResult(StakeActivationResult));
|
|
5219
|
+
|
|
5220
|
+
if ('error' in res) {
|
|
5221
|
+
throw new SolanaJSONRPCError(res.error, `failed to get Stake Activation ${publicKey.toBase58()}`);
|
|
5222
|
+
}
|
|
5223
|
+
|
|
5224
|
+
return res.result;
|
|
5225
|
+
}
|
|
5226
|
+
/**
|
|
5227
|
+
* Fetch all the accounts owned by the specified program id
|
|
5228
|
+
*
|
|
5229
|
+
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>>}
|
|
5230
|
+
*/
|
|
5231
|
+
|
|
5232
|
+
|
|
5233
|
+
async getProgramAccounts(programId, configOrCommitment) {
|
|
5234
|
+
const {
|
|
5235
|
+
commitment,
|
|
5236
|
+
config
|
|
5237
|
+
} = extractCommitmentFromConfig(configOrCommitment);
|
|
5238
|
+
const {
|
|
5239
|
+
encoding,
|
|
5240
|
+
...configWithoutEncoding
|
|
5241
|
+
} = config || {};
|
|
5242
|
+
|
|
5243
|
+
const args = this._buildArgs([programId.toBase58()], commitment, encoding || 'base64', configWithoutEncoding);
|
|
5244
|
+
|
|
5245
|
+
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
|
5246
|
+
const res = create(unsafeRes, jsonRpcResult(array(KeyedAccountInfoResult)));
|
|
5247
|
+
|
|
5248
|
+
if ('error' in res) {
|
|
5249
|
+
throw new SolanaJSONRPCError(res.error, `failed to get accounts owned by program ${programId.toBase58()}`);
|
|
5250
|
+
}
|
|
5251
|
+
|
|
5252
|
+
return res.result;
|
|
5253
|
+
}
|
|
5254
|
+
/**
|
|
5255
|
+
* Fetch and parse all the accounts owned by the specified program id
|
|
5256
|
+
*
|
|
5257
|
+
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer | ParsedAccountData>}>>}
|
|
5258
|
+
*/
|
|
5259
|
+
|
|
5260
|
+
|
|
5261
|
+
async getParsedProgramAccounts(programId, configOrCommitment) {
|
|
5262
|
+
const {
|
|
5263
|
+
commitment,
|
|
5264
|
+
config
|
|
5265
|
+
} = extractCommitmentFromConfig(configOrCommitment);
|
|
5266
|
+
|
|
5267
|
+
const args = this._buildArgs([programId.toBase58()], commitment, 'jsonParsed', config);
|
|
5268
|
+
|
|
5269
|
+
const unsafeRes = await this._rpcRequest('getProgramAccounts', args);
|
|
5270
|
+
const res = create(unsafeRes, jsonRpcResult(array(KeyedParsedAccountInfoResult)));
|
|
5271
|
+
|
|
5272
|
+
if ('error' in res) {
|
|
5273
|
+
throw new SolanaJSONRPCError(res.error, `failed to get accounts owned by program ${programId.toBase58()}`);
|
|
5274
|
+
}
|
|
5275
|
+
|
|
5276
|
+
return res.result;
|
|
5277
|
+
}
|
|
5278
|
+
|
|
5279
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
5280
|
+
async confirmTransaction(strategy, commitment) {
|
|
5281
|
+
let rawSignature;
|
|
5282
|
+
|
|
5283
|
+
if (typeof strategy == 'string') {
|
|
5284
|
+
rawSignature = strategy;
|
|
5285
|
+
} else {
|
|
5286
|
+
var _config$abortSignal;
|
|
5287
|
+
|
|
5288
|
+
const config = strategy;
|
|
5289
|
+
|
|
5290
|
+
if ((_config$abortSignal = config.abortSignal) !== null && _config$abortSignal !== void 0 && _config$abortSignal.aborted) {
|
|
5291
|
+
return Promise.reject(config.abortSignal.reason);
|
|
5292
|
+
}
|
|
5293
|
+
|
|
5294
|
+
rawSignature = config.signature;
|
|
5295
|
+
}
|
|
5296
|
+
|
|
5297
|
+
let decodedSignature;
|
|
5298
|
+
|
|
5299
|
+
try {
|
|
5300
|
+
decodedSignature = bs58.decode(rawSignature);
|
|
5301
|
+
} catch (err) {
|
|
5302
|
+
throw new Error('signature must be base58 encoded: ' + rawSignature);
|
|
5303
|
+
}
|
|
5304
|
+
|
|
5305
|
+
assert(decodedSignature.length === 64, 'signature has invalid length');
|
|
5306
|
+
|
|
5307
|
+
if (typeof strategy === 'string') {
|
|
5308
|
+
return await this.confirmTransactionUsingLegacyTimeoutStrategy({
|
|
5309
|
+
commitment: commitment || this.commitment,
|
|
5310
|
+
signature: rawSignature
|
|
5311
|
+
});
|
|
5312
|
+
} else if ('lastValidBlockHeight' in strategy) {
|
|
5313
|
+
return await this.confirmTransactionUsingBlockHeightExceedanceStrategy({
|
|
5314
|
+
commitment: commitment || this.commitment,
|
|
5315
|
+
strategy
|
|
5316
|
+
});
|
|
5317
|
+
} else {
|
|
5318
|
+
return await this.confirmTransactionUsingDurableNonceStrategy({
|
|
5319
|
+
commitment: commitment || this.commitment,
|
|
5320
|
+
strategy
|
|
5321
|
+
});
|
|
5322
|
+
}
|
|
5323
|
+
}
|
|
5324
|
+
|
|
5325
|
+
getCancellationPromise(signal) {
|
|
5326
|
+
return new Promise((_, reject) => {
|
|
5327
|
+
if (signal == null) {
|
|
5328
|
+
return;
|
|
5329
|
+
}
|
|
5330
|
+
|
|
5331
|
+
if (signal.aborted) {
|
|
5332
|
+
reject(signal.reason);
|
|
5333
|
+
} else {
|
|
5334
|
+
signal.addEventListener('abort', () => {
|
|
5335
|
+
reject(signal.reason);
|
|
5336
|
+
});
|
|
5337
|
+
}
|
|
5338
|
+
});
|
|
5339
|
+
}
|
|
5340
|
+
|
|
5341
|
+
getTransactionConfirmationPromise({
|
|
5342
|
+
commitment,
|
|
5343
|
+
signature
|
|
5344
|
+
}) {
|
|
5345
|
+
let signatureSubscriptionId;
|
|
5346
|
+
let disposeSignatureSubscriptionStateChangeObserver;
|
|
5347
|
+
let done = false;
|
|
5348
|
+
const confirmationPromise = new Promise((resolve, reject) => {
|
|
5349
|
+
try {
|
|
5350
|
+
signatureSubscriptionId = this.onSignature(signature, (result, context) => {
|
|
5351
|
+
signatureSubscriptionId = undefined;
|
|
5352
|
+
const response = {
|
|
5353
|
+
context,
|
|
5354
|
+
value: result
|
|
5355
|
+
};
|
|
5356
|
+
resolve({
|
|
5357
|
+
__type: TransactionStatus.PROCESSED,
|
|
5358
|
+
response
|
|
5359
|
+
});
|
|
5360
|
+
}, commitment);
|
|
5361
|
+
const subscriptionSetupPromise = new Promise(resolveSubscriptionSetup => {
|
|
5362
|
+
if (signatureSubscriptionId == null) {
|
|
5363
|
+
resolveSubscriptionSetup();
|
|
5364
|
+
} else {
|
|
5365
|
+
disposeSignatureSubscriptionStateChangeObserver = this._onSubscriptionStateChange(signatureSubscriptionId, nextState => {
|
|
5366
|
+
if (nextState === 'subscribed') {
|
|
5367
|
+
resolveSubscriptionSetup();
|
|
5368
|
+
}
|
|
5369
|
+
});
|
|
5370
|
+
}
|
|
5371
|
+
});
|
|
5372
|
+
|
|
5373
|
+
(async () => {
|
|
5374
|
+
await subscriptionSetupPromise;
|
|
5375
|
+
if (done) return;
|
|
5376
|
+
const response = await this.getSignatureStatus(signature);
|
|
5377
|
+
if (done) return;
|
|
5378
|
+
|
|
5379
|
+
if (response == null) {
|
|
5380
|
+
return;
|
|
5381
|
+
}
|
|
5382
|
+
|
|
5383
|
+
const {
|
|
5384
|
+
context,
|
|
5385
|
+
value
|
|
5386
|
+
} = response;
|
|
5387
|
+
|
|
5388
|
+
if (value == null) {
|
|
5389
|
+
return;
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5392
|
+
if (value !== null && value !== void 0 && value.err) {
|
|
5393
|
+
reject(value.err);
|
|
5394
|
+
} else {
|
|
5395
|
+
switch (commitment) {
|
|
5396
|
+
case 'confirmed':
|
|
5397
|
+
case 'single':
|
|
5398
|
+
case 'singleGossip':
|
|
5399
|
+
{
|
|
5400
|
+
if (value.confirmationStatus === 'processed') {
|
|
5401
|
+
return;
|
|
5402
|
+
}
|
|
5403
|
+
|
|
5404
|
+
break;
|
|
5405
|
+
}
|
|
5406
|
+
|
|
5407
|
+
case 'finalized':
|
|
5408
|
+
case 'max':
|
|
5409
|
+
case 'root':
|
|
5410
|
+
{
|
|
5411
|
+
if (value.confirmationStatus === 'processed' || value.confirmationStatus === 'confirmed') {
|
|
5412
|
+
return;
|
|
5413
|
+
}
|
|
5414
|
+
|
|
5415
|
+
break;
|
|
5416
|
+
}
|
|
5417
|
+
// exhaust enums to ensure full coverage
|
|
5418
|
+
|
|
5419
|
+
case 'processed':
|
|
5420
|
+
case 'recent':
|
|
5421
|
+
}
|
|
5422
|
+
|
|
5423
|
+
done = true;
|
|
5424
|
+
resolve({
|
|
5425
|
+
__type: TransactionStatus.PROCESSED,
|
|
5426
|
+
response: {
|
|
5427
|
+
context,
|
|
5428
|
+
value
|
|
5429
|
+
}
|
|
5430
|
+
});
|
|
5431
|
+
}
|
|
5432
|
+
})();
|
|
5433
|
+
} catch (err) {
|
|
5434
|
+
reject(err);
|
|
5435
|
+
}
|
|
5436
|
+
});
|
|
5437
|
+
|
|
5438
|
+
const abortConfirmation = () => {
|
|
5439
|
+
if (disposeSignatureSubscriptionStateChangeObserver) {
|
|
5440
|
+
disposeSignatureSubscriptionStateChangeObserver();
|
|
5441
|
+
disposeSignatureSubscriptionStateChangeObserver = undefined;
|
|
5442
|
+
}
|
|
5443
|
+
|
|
5444
|
+
if (signatureSubscriptionId != null) {
|
|
5445
|
+
this.removeSignatureListener(signatureSubscriptionId);
|
|
5446
|
+
signatureSubscriptionId = undefined;
|
|
5447
|
+
}
|
|
5448
|
+
};
|
|
5449
|
+
|
|
5450
|
+
return {
|
|
5451
|
+
abortConfirmation,
|
|
5452
|
+
confirmationPromise
|
|
5453
|
+
};
|
|
5454
|
+
}
|
|
5455
|
+
|
|
5456
|
+
async confirmTransactionUsingBlockHeightExceedanceStrategy({
|
|
5457
|
+
commitment,
|
|
5458
|
+
strategy: {
|
|
5459
|
+
abortSignal,
|
|
5460
|
+
lastValidBlockHeight,
|
|
5461
|
+
signature
|
|
5462
|
+
}
|
|
5463
|
+
}) {
|
|
5464
|
+
let done = false;
|
|
5465
|
+
const expiryPromise = new Promise(resolve => {
|
|
5466
|
+
const checkBlockHeight = async () => {
|
|
5467
|
+
try {
|
|
5468
|
+
const blockHeight = await this.getBlockHeight(commitment);
|
|
5469
|
+
return blockHeight;
|
|
5470
|
+
} catch (_e) {
|
|
5471
|
+
return -1;
|
|
5472
|
+
}
|
|
5473
|
+
};
|
|
5474
|
+
|
|
5475
|
+
(async () => {
|
|
5476
|
+
let currentBlockHeight = await checkBlockHeight();
|
|
5477
|
+
if (done) return;
|
|
5478
|
+
|
|
5479
|
+
while (currentBlockHeight <= lastValidBlockHeight) {
|
|
5480
|
+
await sleep(1000);
|
|
5481
|
+
if (done) return;
|
|
5482
|
+
currentBlockHeight = await checkBlockHeight();
|
|
5483
|
+
if (done) return;
|
|
5484
|
+
}
|
|
5485
|
+
|
|
5486
|
+
resolve({
|
|
5487
|
+
__type: TransactionStatus.BLOCKHEIGHT_EXCEEDED
|
|
5488
|
+
});
|
|
5489
|
+
})();
|
|
5490
|
+
});
|
|
4542
5491
|
const {
|
|
5492
|
+
abortConfirmation,
|
|
5493
|
+
confirmationPromise
|
|
5494
|
+
} = this.getTransactionConfirmationPromise({
|
|
4543
5495
|
commitment,
|
|
4544
|
-
|
|
4545
|
-
} = extractCommitmentFromConfig(commitmentOrConfig);
|
|
4546
|
-
|
|
4547
|
-
const args = this._buildArgs([publicKey.toBase58()], commitment, undefined
|
|
4548
|
-
/* encoding */
|
|
4549
|
-
, { ...config,
|
|
4550
|
-
epoch: epoch != null ? epoch : config === null || config === void 0 ? void 0 : config.epoch
|
|
5496
|
+
signature
|
|
4551
5497
|
});
|
|
5498
|
+
const cancellationPromise = this.getCancellationPromise(abortSignal);
|
|
5499
|
+
let result;
|
|
4552
5500
|
|
|
4553
|
-
|
|
4554
|
-
|
|
5501
|
+
try {
|
|
5502
|
+
const outcome = await Promise.race([cancellationPromise, confirmationPromise, expiryPromise]);
|
|
4555
5503
|
|
|
4556
|
-
|
|
4557
|
-
|
|
5504
|
+
if (outcome.__type === TransactionStatus.PROCESSED) {
|
|
5505
|
+
result = outcome.response;
|
|
5506
|
+
} else {
|
|
5507
|
+
throw new TransactionExpiredBlockheightExceededError(signature);
|
|
5508
|
+
}
|
|
5509
|
+
} finally {
|
|
5510
|
+
done = true;
|
|
5511
|
+
abortConfirmation();
|
|
4558
5512
|
}
|
|
4559
5513
|
|
|
4560
|
-
return
|
|
5514
|
+
return result;
|
|
4561
5515
|
}
|
|
4562
|
-
/**
|
|
4563
|
-
* Fetch all the accounts owned by the specified program id
|
|
4564
|
-
*
|
|
4565
|
-
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer>}>>}
|
|
4566
|
-
*/
|
|
4567
5516
|
|
|
5517
|
+
async confirmTransactionUsingDurableNonceStrategy({
|
|
5518
|
+
commitment,
|
|
5519
|
+
strategy: {
|
|
5520
|
+
abortSignal,
|
|
5521
|
+
minContextSlot,
|
|
5522
|
+
nonceAccountPubkey,
|
|
5523
|
+
nonceValue,
|
|
5524
|
+
signature
|
|
5525
|
+
}
|
|
5526
|
+
}) {
|
|
5527
|
+
let done = false;
|
|
5528
|
+
const expiryPromise = new Promise(resolve => {
|
|
5529
|
+
let currentNonceValue = nonceValue;
|
|
5530
|
+
let lastCheckedSlot = null;
|
|
5531
|
+
|
|
5532
|
+
const getCurrentNonceValue = async () => {
|
|
5533
|
+
try {
|
|
5534
|
+
const {
|
|
5535
|
+
context,
|
|
5536
|
+
value: nonceAccount
|
|
5537
|
+
} = await this.getNonceAndContext(nonceAccountPubkey, {
|
|
5538
|
+
commitment,
|
|
5539
|
+
minContextSlot
|
|
5540
|
+
});
|
|
5541
|
+
lastCheckedSlot = context.slot;
|
|
5542
|
+
return nonceAccount === null || nonceAccount === void 0 ? void 0 : nonceAccount.nonce;
|
|
5543
|
+
} catch (e) {
|
|
5544
|
+
// If for whatever reason we can't reach/read the nonce
|
|
5545
|
+
// account, just keep using the last-known value.
|
|
5546
|
+
return currentNonceValue;
|
|
5547
|
+
}
|
|
5548
|
+
};
|
|
5549
|
+
|
|
5550
|
+
(async () => {
|
|
5551
|
+
currentNonceValue = await getCurrentNonceValue();
|
|
5552
|
+
if (done) return;
|
|
4568
5553
|
|
|
4569
|
-
|
|
5554
|
+
while (true // eslint-disable-line no-constant-condition
|
|
5555
|
+
) {
|
|
5556
|
+
if (nonceValue !== currentNonceValue) {
|
|
5557
|
+
resolve({
|
|
5558
|
+
__type: TransactionStatus.NONCE_INVALID,
|
|
5559
|
+
slotInWhichNonceDidAdvance: lastCheckedSlot
|
|
5560
|
+
});
|
|
5561
|
+
return;
|
|
5562
|
+
}
|
|
5563
|
+
|
|
5564
|
+
await sleep(2000);
|
|
5565
|
+
if (done) return;
|
|
5566
|
+
currentNonceValue = await getCurrentNonceValue();
|
|
5567
|
+
if (done) return;
|
|
5568
|
+
}
|
|
5569
|
+
})();
|
|
5570
|
+
});
|
|
4570
5571
|
const {
|
|
5572
|
+
abortConfirmation,
|
|
5573
|
+
confirmationPromise
|
|
5574
|
+
} = this.getTransactionConfirmationPromise({
|
|
4571
5575
|
commitment,
|
|
4572
|
-
|
|
4573
|
-
}
|
|
4574
|
-
const
|
|
4575
|
-
|
|
4576
|
-
...configWithoutEncoding
|
|
4577
|
-
} = config || {};
|
|
4578
|
-
|
|
4579
|
-
const args = this._buildArgs([programId.toBase58()], commitment, encoding || 'base64', configWithoutEncoding);
|
|
5576
|
+
signature
|
|
5577
|
+
});
|
|
5578
|
+
const cancellationPromise = this.getCancellationPromise(abortSignal);
|
|
5579
|
+
let result;
|
|
4580
5580
|
|
|
4581
|
-
|
|
4582
|
-
|
|
5581
|
+
try {
|
|
5582
|
+
const outcome = await Promise.race([cancellationPromise, confirmationPromise, expiryPromise]);
|
|
4583
5583
|
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
5584
|
+
if (outcome.__type === TransactionStatus.PROCESSED) {
|
|
5585
|
+
result = outcome.response;
|
|
5586
|
+
} else {
|
|
5587
|
+
var _signatureStatus;
|
|
4587
5588
|
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
/**
|
|
4591
|
-
* Fetch and parse all the accounts owned by the specified program id
|
|
4592
|
-
*
|
|
4593
|
-
* @return {Promise<Array<{pubkey: PublicKey, account: AccountInfo<Buffer | ParsedAccountData>}>>}
|
|
4594
|
-
*/
|
|
5589
|
+
// Double check that the transaction is indeed unconfirmed.
|
|
5590
|
+
let signatureStatus;
|
|
4595
5591
|
|
|
5592
|
+
while (true // eslint-disable-line no-constant-condition
|
|
5593
|
+
) {
|
|
5594
|
+
var _outcome$slotInWhichN;
|
|
4596
5595
|
|
|
4597
|
-
|
|
4598
|
-
const {
|
|
4599
|
-
commitment,
|
|
4600
|
-
config
|
|
4601
|
-
} = extractCommitmentFromConfig(configOrCommitment);
|
|
5596
|
+
const status = await this.getSignatureStatus(signature);
|
|
4602
5597
|
|
|
4603
|
-
|
|
5598
|
+
if (status == null) {
|
|
5599
|
+
break;
|
|
5600
|
+
}
|
|
4604
5601
|
|
|
4605
|
-
|
|
4606
|
-
|
|
5602
|
+
if (status.context.slot < ((_outcome$slotInWhichN = outcome.slotInWhichNonceDidAdvance) !== null && _outcome$slotInWhichN !== void 0 ? _outcome$slotInWhichN : minContextSlot)) {
|
|
5603
|
+
await sleep(400);
|
|
5604
|
+
continue;
|
|
5605
|
+
}
|
|
4607
5606
|
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
5607
|
+
signatureStatus = status;
|
|
5608
|
+
break;
|
|
5609
|
+
}
|
|
4611
5610
|
|
|
4612
|
-
|
|
4613
|
-
|
|
5611
|
+
if ((_signatureStatus = signatureStatus) !== null && _signatureStatus !== void 0 && _signatureStatus.value) {
|
|
5612
|
+
const commitmentForStatus = commitment || 'finalized';
|
|
5613
|
+
const {
|
|
5614
|
+
confirmationStatus
|
|
5615
|
+
} = signatureStatus.value;
|
|
5616
|
+
|
|
5617
|
+
switch (commitmentForStatus) {
|
|
5618
|
+
case 'processed':
|
|
5619
|
+
case 'recent':
|
|
5620
|
+
if (confirmationStatus !== 'processed' && confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') {
|
|
5621
|
+
throw new TransactionExpiredNonceInvalidError(signature);
|
|
5622
|
+
}
|
|
4614
5623
|
|
|
4615
|
-
|
|
4616
|
-
async confirmTransaction(strategy, commitment) {
|
|
4617
|
-
let rawSignature;
|
|
5624
|
+
break;
|
|
4618
5625
|
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
5626
|
+
case 'confirmed':
|
|
5627
|
+
case 'single':
|
|
5628
|
+
case 'singleGossip':
|
|
5629
|
+
if (confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') {
|
|
5630
|
+
throw new TransactionExpiredNonceInvalidError(signature);
|
|
5631
|
+
}
|
|
4625
5632
|
|
|
4626
|
-
|
|
5633
|
+
break;
|
|
4627
5634
|
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
5635
|
+
case 'finalized':
|
|
5636
|
+
case 'max':
|
|
5637
|
+
case 'root':
|
|
5638
|
+
if (confirmationStatus !== 'finalized') {
|
|
5639
|
+
throw new TransactionExpiredNonceInvalidError(signature);
|
|
5640
|
+
}
|
|
4633
5641
|
|
|
4634
|
-
assert(decodedSignature.length === 64, 'signature has invalid length');
|
|
4635
|
-
const subscriptionCommitment = commitment || this.commitment;
|
|
4636
|
-
let timeoutId;
|
|
4637
|
-
let subscriptionId;
|
|
4638
|
-
let done = false;
|
|
4639
|
-
const confirmationPromise = new Promise((resolve, reject) => {
|
|
4640
|
-
try {
|
|
4641
|
-
subscriptionId = this.onSignature(rawSignature, (result, context) => {
|
|
4642
|
-
subscriptionId = undefined;
|
|
4643
|
-
const response = {
|
|
4644
|
-
context,
|
|
4645
|
-
value: result
|
|
4646
|
-
};
|
|
4647
|
-
done = true;
|
|
4648
|
-
resolve({
|
|
4649
|
-
__type: TransactionStatus.PROCESSED,
|
|
4650
|
-
response
|
|
4651
|
-
});
|
|
4652
|
-
}, subscriptionCommitment);
|
|
4653
|
-
} catch (err) {
|
|
4654
|
-
reject(err);
|
|
4655
|
-
}
|
|
4656
|
-
});
|
|
4657
|
-
const expiryPromise = new Promise(resolve => {
|
|
4658
|
-
if (typeof strategy === 'string') {
|
|
4659
|
-
let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
|
|
4660
|
-
|
|
4661
|
-
switch (subscriptionCommitment) {
|
|
4662
|
-
case 'processed':
|
|
4663
|
-
case 'recent':
|
|
4664
|
-
case 'single':
|
|
4665
|
-
case 'confirmed':
|
|
4666
|
-
case 'singleGossip':
|
|
4667
|
-
{
|
|
4668
|
-
timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
|
|
4669
5642
|
break;
|
|
4670
|
-
}
|
|
4671
|
-
}
|
|
4672
5643
|
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
} else {
|
|
4678
|
-
let config = strategy;
|
|
5644
|
+
default:
|
|
5645
|
+
// Exhaustive switch.
|
|
5646
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5647
|
+
(_ => {})(commitmentForStatus);
|
|
4679
5648
|
|
|
4680
|
-
const checkBlockHeight = async () => {
|
|
4681
|
-
try {
|
|
4682
|
-
const blockHeight = await this.getBlockHeight(commitment);
|
|
4683
|
-
return blockHeight;
|
|
4684
|
-
} catch (_e) {
|
|
4685
|
-
return -1;
|
|
4686
5649
|
}
|
|
4687
|
-
};
|
|
4688
5650
|
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
5651
|
+
result = {
|
|
5652
|
+
context: signatureStatus.context,
|
|
5653
|
+
value: {
|
|
5654
|
+
err: signatureStatus.value.err
|
|
5655
|
+
}
|
|
5656
|
+
};
|
|
5657
|
+
} else {
|
|
5658
|
+
throw new TransactionExpiredNonceInvalidError(signature);
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
} finally {
|
|
5662
|
+
done = true;
|
|
5663
|
+
abortConfirmation();
|
|
5664
|
+
}
|
|
4692
5665
|
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
if (done) return;
|
|
4696
|
-
currentBlockHeight = await checkBlockHeight();
|
|
4697
|
-
if (done) return;
|
|
4698
|
-
}
|
|
5666
|
+
return result;
|
|
5667
|
+
}
|
|
4699
5668
|
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
5669
|
+
async confirmTransactionUsingLegacyTimeoutStrategy({
|
|
5670
|
+
commitment,
|
|
5671
|
+
signature
|
|
5672
|
+
}) {
|
|
5673
|
+
let timeoutId;
|
|
5674
|
+
const expiryPromise = new Promise(resolve => {
|
|
5675
|
+
let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
|
|
5676
|
+
|
|
5677
|
+
switch (commitment) {
|
|
5678
|
+
case 'processed':
|
|
5679
|
+
case 'recent':
|
|
5680
|
+
case 'single':
|
|
5681
|
+
case 'confirmed':
|
|
5682
|
+
case 'singleGossip':
|
|
5683
|
+
{
|
|
5684
|
+
timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
|
|
5685
|
+
break;
|
|
5686
|
+
}
|
|
4704
5687
|
}
|
|
5688
|
+
|
|
5689
|
+
timeoutId = setTimeout(() => resolve({
|
|
5690
|
+
__type: TransactionStatus.TIMED_OUT,
|
|
5691
|
+
timeoutMs
|
|
5692
|
+
}), timeoutMs);
|
|
5693
|
+
});
|
|
5694
|
+
const {
|
|
5695
|
+
abortConfirmation,
|
|
5696
|
+
confirmationPromise
|
|
5697
|
+
} = this.getTransactionConfirmationPromise({
|
|
5698
|
+
commitment,
|
|
5699
|
+
signature
|
|
4705
5700
|
});
|
|
4706
5701
|
let result;
|
|
4707
5702
|
|
|
4708
5703
|
try {
|
|
4709
5704
|
const outcome = await Promise.race([confirmationPromise, expiryPromise]);
|
|
4710
5705
|
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
case TransactionStatus.PROCESSED:
|
|
4716
|
-
result = outcome.response;
|
|
4717
|
-
break;
|
|
4718
|
-
|
|
4719
|
-
case TransactionStatus.TIMED_OUT:
|
|
4720
|
-
throw new TransactionExpiredTimeoutError(rawSignature, outcome.timeoutMs / 1000);
|
|
5706
|
+
if (outcome.__type === TransactionStatus.PROCESSED) {
|
|
5707
|
+
result = outcome.response;
|
|
5708
|
+
} else {
|
|
5709
|
+
throw new TransactionExpiredTimeoutError(signature, outcome.timeoutMs / 1000);
|
|
4721
5710
|
}
|
|
4722
5711
|
} finally {
|
|
4723
5712
|
clearTimeout(timeoutId);
|
|
4724
|
-
|
|
4725
|
-
if (subscriptionId) {
|
|
4726
|
-
this.removeSignatureListener(subscriptionId);
|
|
4727
|
-
}
|
|
5713
|
+
abortConfirmation();
|
|
4728
5714
|
}
|
|
4729
5715
|
|
|
4730
5716
|
return result;
|
|
@@ -4777,7 +5763,7 @@ class Connection {
|
|
|
4777
5763
|
, config);
|
|
4778
5764
|
|
|
4779
5765
|
const unsafeRes = await this._rpcRequest('getSlot', args);
|
|
4780
|
-
const res = create(unsafeRes, jsonRpcResult(number
|
|
5766
|
+
const res = create(unsafeRes, jsonRpcResult(number()));
|
|
4781
5767
|
|
|
4782
5768
|
if ('error' in res) {
|
|
4783
5769
|
throw new SolanaJSONRPCError(res.error, 'failed to get slot');
|
|
@@ -4882,7 +5868,7 @@ class Connection {
|
|
|
4882
5868
|
, config);
|
|
4883
5869
|
|
|
4884
5870
|
const unsafeRes = await this._rpcRequest('getTransactionCount', args);
|
|
4885
|
-
const res = create(unsafeRes, jsonRpcResult(number
|
|
5871
|
+
const res = create(unsafeRes, jsonRpcResult(number()));
|
|
4886
5872
|
|
|
4887
5873
|
if ('error' in res) {
|
|
4888
5874
|
throw new SolanaJSONRPCError(res.error, 'failed to get transaction count');
|
|
@@ -5090,15 +6076,15 @@ class Connection {
|
|
|
5090
6076
|
|
|
5091
6077
|
|
|
5092
6078
|
async getFeeForMessage(message, commitment) {
|
|
5093
|
-
const wireMessage = message.serialize().toString('base64');
|
|
6079
|
+
const wireMessage = toBuffer(message.serialize()).toString('base64');
|
|
5094
6080
|
|
|
5095
6081
|
const args = this._buildArgs([wireMessage], commitment);
|
|
5096
6082
|
|
|
5097
6083
|
const unsafeRes = await this._rpcRequest('getFeeForMessage', args);
|
|
5098
|
-
const res = create(unsafeRes, jsonRpcResultAndContext(nullable(number
|
|
6084
|
+
const res = create(unsafeRes, jsonRpcResultAndContext(nullable(number())));
|
|
5099
6085
|
|
|
5100
6086
|
if ('error' in res) {
|
|
5101
|
-
throw new SolanaJSONRPCError(res.error, 'failed to get
|
|
6087
|
+
throw new SolanaJSONRPCError(res.error, 'failed to get fee for message');
|
|
5102
6088
|
}
|
|
5103
6089
|
|
|
5104
6090
|
if (res.result === null) {
|
|
@@ -5194,9 +6180,16 @@ class Connection {
|
|
|
5194
6180
|
}
|
|
5195
6181
|
/**
|
|
5196
6182
|
* Fetch a processed block from the cluster.
|
|
6183
|
+
*
|
|
6184
|
+
* @deprecated Instead, call `getBlock` using a `GetVersionedBlockConfig` by
|
|
6185
|
+
* setting the `maxSupportedTransactionVersion` property.
|
|
5197
6186
|
*/
|
|
5198
6187
|
|
|
5199
6188
|
|
|
6189
|
+
/**
|
|
6190
|
+
* Fetch a processed block from the cluster.
|
|
6191
|
+
*/
|
|
6192
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
5200
6193
|
async getBlock(slot, rawConfig) {
|
|
5201
6194
|
const {
|
|
5202
6195
|
commitment,
|
|
@@ -5208,28 +6201,115 @@ class Connection {
|
|
|
5208
6201
|
, config);
|
|
5209
6202
|
|
|
5210
6203
|
const unsafeRes = await this._rpcRequest('getBlock', args);
|
|
5211
|
-
const res = create(unsafeRes, GetBlockRpcResult);
|
|
5212
6204
|
|
|
5213
|
-
|
|
5214
|
-
|
|
6205
|
+
try {
|
|
6206
|
+
switch (config === null || config === void 0 ? void 0 : config.transactionDetails) {
|
|
6207
|
+
case 'accounts':
|
|
6208
|
+
{
|
|
6209
|
+
const res = create(unsafeRes, GetAccountsModeBlockRpcResult);
|
|
6210
|
+
|
|
6211
|
+
if ('error' in res) {
|
|
6212
|
+
throw res.error;
|
|
6213
|
+
}
|
|
6214
|
+
|
|
6215
|
+
return res.result;
|
|
6216
|
+
}
|
|
6217
|
+
|
|
6218
|
+
case 'none':
|
|
6219
|
+
{
|
|
6220
|
+
const res = create(unsafeRes, GetNoneModeBlockRpcResult);
|
|
6221
|
+
|
|
6222
|
+
if ('error' in res) {
|
|
6223
|
+
throw res.error;
|
|
6224
|
+
}
|
|
6225
|
+
|
|
6226
|
+
return res.result;
|
|
6227
|
+
}
|
|
6228
|
+
|
|
6229
|
+
default:
|
|
6230
|
+
{
|
|
6231
|
+
const res = create(unsafeRes, GetBlockRpcResult);
|
|
6232
|
+
|
|
6233
|
+
if ('error' in res) {
|
|
6234
|
+
throw res.error;
|
|
6235
|
+
}
|
|
6236
|
+
|
|
6237
|
+
const {
|
|
6238
|
+
result
|
|
6239
|
+
} = res;
|
|
6240
|
+
return result ? { ...result,
|
|
6241
|
+
transactions: result.transactions.map(({
|
|
6242
|
+
transaction,
|
|
6243
|
+
meta,
|
|
6244
|
+
version
|
|
6245
|
+
}) => ({
|
|
6246
|
+
meta,
|
|
6247
|
+
transaction: { ...transaction,
|
|
6248
|
+
message: versionedMessageFromResponse(version, transaction.message)
|
|
6249
|
+
},
|
|
6250
|
+
version
|
|
6251
|
+
}))
|
|
6252
|
+
} : null;
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
} catch (e) {
|
|
6256
|
+
throw new SolanaJSONRPCError(e, 'failed to get confirmed block');
|
|
5215
6257
|
}
|
|
6258
|
+
}
|
|
6259
|
+
/**
|
|
6260
|
+
* Fetch parsed transaction details for a confirmed or finalized block
|
|
6261
|
+
*/
|
|
5216
6262
|
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
6263
|
+
|
|
6264
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
6265
|
+
async getParsedBlock(slot, rawConfig) {
|
|
6266
|
+
const {
|
|
6267
|
+
commitment,
|
|
6268
|
+
config
|
|
6269
|
+
} = extractCommitmentFromConfig(rawConfig);
|
|
6270
|
+
|
|
6271
|
+
const args = this._buildArgsAtLeastConfirmed([slot], commitment, 'jsonParsed', config);
|
|
6272
|
+
|
|
6273
|
+
const unsafeRes = await this._rpcRequest('getBlock', args);
|
|
6274
|
+
|
|
6275
|
+
try {
|
|
6276
|
+
switch (config === null || config === void 0 ? void 0 : config.transactionDetails) {
|
|
6277
|
+
case 'accounts':
|
|
6278
|
+
{
|
|
6279
|
+
const res = create(unsafeRes, GetParsedAccountsModeBlockRpcResult);
|
|
6280
|
+
|
|
6281
|
+
if ('error' in res) {
|
|
6282
|
+
throw res.error;
|
|
6283
|
+
}
|
|
6284
|
+
|
|
6285
|
+
return res.result;
|
|
5229
6286
|
}
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
6287
|
+
|
|
6288
|
+
case 'none':
|
|
6289
|
+
{
|
|
6290
|
+
const res = create(unsafeRes, GetParsedNoneModeBlockRpcResult);
|
|
6291
|
+
|
|
6292
|
+
if ('error' in res) {
|
|
6293
|
+
throw res.error;
|
|
6294
|
+
}
|
|
6295
|
+
|
|
6296
|
+
return res.result;
|
|
6297
|
+
}
|
|
6298
|
+
|
|
6299
|
+
default:
|
|
6300
|
+
{
|
|
6301
|
+
const res = create(unsafeRes, GetParsedBlockRpcResult);
|
|
6302
|
+
|
|
6303
|
+
if ('error' in res) {
|
|
6304
|
+
throw res.error;
|
|
6305
|
+
}
|
|
6306
|
+
|
|
6307
|
+
return res.result;
|
|
6308
|
+
}
|
|
6309
|
+
}
|
|
6310
|
+
} catch (e) {
|
|
6311
|
+
throw new SolanaJSONRPCError(e, 'failed to get block');
|
|
6312
|
+
}
|
|
5233
6313
|
}
|
|
5234
6314
|
/*
|
|
5235
6315
|
* Returns the current block height of the node
|
|
@@ -5247,7 +6327,7 @@ class Connection {
|
|
|
5247
6327
|
, config);
|
|
5248
6328
|
|
|
5249
6329
|
const unsafeRes = await this._rpcRequest('getBlockHeight', args);
|
|
5250
|
-
const res = create(unsafeRes, jsonRpcResult(number
|
|
6330
|
+
const res = create(unsafeRes, jsonRpcResult(number()));
|
|
5251
6331
|
|
|
5252
6332
|
if ('error' in res) {
|
|
5253
6333
|
throw new SolanaJSONRPCError(res.error, 'failed to get block height information');
|
|
@@ -5288,9 +6368,17 @@ class Connection {
|
|
|
5288
6368
|
}
|
|
5289
6369
|
/**
|
|
5290
6370
|
* Fetch a confirmed or finalized transaction from the cluster.
|
|
6371
|
+
*
|
|
6372
|
+
* @deprecated Instead, call `getTransaction` using a
|
|
6373
|
+
* `GetVersionedTransactionConfig` by setting the
|
|
6374
|
+
* `maxSupportedTransactionVersion` property.
|
|
5291
6375
|
*/
|
|
5292
6376
|
|
|
5293
6377
|
|
|
6378
|
+
/**
|
|
6379
|
+
* Fetch a confirmed or finalized transaction from the cluster.
|
|
6380
|
+
*/
|
|
6381
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
5294
6382
|
async getTransaction(signature, rawConfig) {
|
|
5295
6383
|
const {
|
|
5296
6384
|
commitment,
|
|
@@ -5312,7 +6400,7 @@ class Connection {
|
|
|
5312
6400
|
if (!result) return result;
|
|
5313
6401
|
return { ...result,
|
|
5314
6402
|
transaction: { ...result.transaction,
|
|
5315
|
-
message:
|
|
6403
|
+
message: versionedMessageFromResponse(result.version, result.transaction.message)
|
|
5316
6404
|
}
|
|
5317
6405
|
};
|
|
5318
6406
|
}
|
|
@@ -5371,9 +6459,19 @@ class Connection {
|
|
|
5371
6459
|
/**
|
|
5372
6460
|
* Fetch transaction details for a batch of confirmed transactions.
|
|
5373
6461
|
* Similar to {@link getParsedTransactions} but returns a {@link TransactionResponse}.
|
|
6462
|
+
*
|
|
6463
|
+
* @deprecated Instead, call `getTransactions` using a
|
|
6464
|
+
* `GetVersionedTransactionConfig` by setting the
|
|
6465
|
+
* `maxSupportedTransactionVersion` property.
|
|
5374
6466
|
*/
|
|
5375
6467
|
|
|
5376
6468
|
|
|
6469
|
+
/**
|
|
6470
|
+
* Fetch transaction details for a batch of confirmed transactions.
|
|
6471
|
+
* Similar to {@link getParsedTransactions} but returns a {@link
|
|
6472
|
+
* VersionedTransactionResponse}.
|
|
6473
|
+
*/
|
|
6474
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
5377
6475
|
async getTransactions(signatures, commitmentOrConfig) {
|
|
5378
6476
|
const {
|
|
5379
6477
|
commitment,
|
|
@@ -5401,7 +6499,7 @@ class Connection {
|
|
|
5401
6499
|
if (!result) return result;
|
|
5402
6500
|
return { ...result,
|
|
5403
6501
|
transaction: { ...result.transaction,
|
|
5404
|
-
message:
|
|
6502
|
+
message: versionedMessageFromResponse(result.version, result.transaction.message)
|
|
5405
6503
|
}
|
|
5406
6504
|
};
|
|
5407
6505
|
});
|
|
@@ -5466,7 +6564,7 @@ class Connection {
|
|
|
5466
6564
|
const args = this._buildArgsAtLeastConfirmed(endSlot !== undefined ? [startSlot, endSlot] : [startSlot], commitment);
|
|
5467
6565
|
|
|
5468
6566
|
const unsafeRes = await this._rpcRequest('getBlocks', args);
|
|
5469
|
-
const res = create(unsafeRes, jsonRpcResult(array(number
|
|
6567
|
+
const res = create(unsafeRes, jsonRpcResult(array(number())));
|
|
5470
6568
|
|
|
5471
6569
|
if ('error' in res) {
|
|
5472
6570
|
throw new SolanaJSONRPCError(res.error, 'failed to get blocks');
|
|
@@ -5734,11 +6832,11 @@ class Connection {
|
|
|
5734
6832
|
*/
|
|
5735
6833
|
|
|
5736
6834
|
|
|
5737
|
-
async getNonceAndContext(nonceAccount,
|
|
6835
|
+
async getNonceAndContext(nonceAccount, commitmentOrConfig) {
|
|
5738
6836
|
const {
|
|
5739
6837
|
context,
|
|
5740
6838
|
value: accountInfo
|
|
5741
|
-
} = await this.getAccountInfoAndContext(nonceAccount,
|
|
6839
|
+
} = await this.getAccountInfoAndContext(nonceAccount, commitmentOrConfig);
|
|
5742
6840
|
let value = null;
|
|
5743
6841
|
|
|
5744
6842
|
if (accountInfo !== null) {
|
|
@@ -5755,8 +6853,8 @@ class Connection {
|
|
|
5755
6853
|
*/
|
|
5756
6854
|
|
|
5757
6855
|
|
|
5758
|
-
async getNonce(nonceAccount,
|
|
5759
|
-
return await this.getNonceAndContext(nonceAccount,
|
|
6856
|
+
async getNonce(nonceAccount, commitmentOrConfig) {
|
|
6857
|
+
return await this.getNonceAndContext(nonceAccount, commitmentOrConfig).then(x => x.value).catch(e => {
|
|
5760
6858
|
throw new Error('failed to get nonce for account ' + nonceAccount.toBase58() + ': ' + e);
|
|
5761
6859
|
});
|
|
5762
6860
|
}
|
|
@@ -5858,20 +6956,54 @@ class Connection {
|
|
|
5858
6956
|
const args = this._buildArgs([], commitment, 'base64', configArg);
|
|
5859
6957
|
|
|
5860
6958
|
const unsafeRes = await this._rpcRequest('getStakeMinimumDelegation', args);
|
|
5861
|
-
const res = create(unsafeRes, jsonRpcResultAndContext(number
|
|
6959
|
+
const res = create(unsafeRes, jsonRpcResultAndContext(number()));
|
|
5862
6960
|
|
|
5863
6961
|
if ('error' in res) {
|
|
5864
6962
|
throw new SolanaJSONRPCError(res.error, `failed to get stake minimum delegation`);
|
|
5865
6963
|
}
|
|
5866
6964
|
|
|
5867
|
-
return res.result;
|
|
5868
|
-
}
|
|
6965
|
+
return res.result;
|
|
6966
|
+
}
|
|
6967
|
+
/**
|
|
6968
|
+
* Simulate a transaction
|
|
6969
|
+
*
|
|
6970
|
+
* @deprecated Instead, call {@link simulateTransaction} with {@link
|
|
6971
|
+
* VersionedTransaction} and {@link SimulateTransactionConfig} parameters
|
|
6972
|
+
*/
|
|
6973
|
+
|
|
6974
|
+
|
|
5869
6975
|
/**
|
|
5870
6976
|
* Simulate a transaction
|
|
5871
6977
|
*/
|
|
6978
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
6979
|
+
async simulateTransaction(transactionOrMessage, configOrSigners, includeAccounts) {
|
|
6980
|
+
if ('message' in transactionOrMessage) {
|
|
6981
|
+
const versionedTx = transactionOrMessage;
|
|
6982
|
+
const wireTransaction = versionedTx.serialize();
|
|
6983
|
+
const encodedTransaction = Buffer.from(wireTransaction).toString('base64');
|
|
6984
|
+
|
|
6985
|
+
if (Array.isArray(configOrSigners) || includeAccounts !== undefined) {
|
|
6986
|
+
throw new Error('Invalid arguments');
|
|
6987
|
+
}
|
|
6988
|
+
|
|
6989
|
+
const config = configOrSigners || {};
|
|
6990
|
+
config.encoding = 'base64';
|
|
6991
|
+
|
|
6992
|
+
if (!('commitment' in config)) {
|
|
6993
|
+
config.commitment = this.commitment;
|
|
6994
|
+
}
|
|
6995
|
+
|
|
6996
|
+
const args = [encodedTransaction, config];
|
|
6997
|
+
const unsafeRes = await this._rpcRequest('simulateTransaction', args);
|
|
6998
|
+
const res = create(unsafeRes, SimulatedTransactionResponseStruct);
|
|
5872
6999
|
|
|
7000
|
+
if ('error' in res) {
|
|
7001
|
+
throw new Error('failed to simulate transaction: ' + res.error.message);
|
|
7002
|
+
}
|
|
7003
|
+
|
|
7004
|
+
return res.result;
|
|
7005
|
+
}
|
|
5873
7006
|
|
|
5874
|
-
async simulateTransaction(transactionOrMessage, signers, includeAccounts) {
|
|
5875
7007
|
let transaction;
|
|
5876
7008
|
|
|
5877
7009
|
if (transactionOrMessage instanceof Transaction) {
|
|
@@ -5887,6 +7019,12 @@ class Connection {
|
|
|
5887
7019
|
transaction._message = transaction._json = undefined;
|
|
5888
7020
|
}
|
|
5889
7021
|
|
|
7022
|
+
if (configOrSigners !== undefined && !Array.isArray(configOrSigners)) {
|
|
7023
|
+
throw new Error('Invalid arguments');
|
|
7024
|
+
}
|
|
7025
|
+
|
|
7026
|
+
const signers = configOrSigners;
|
|
7027
|
+
|
|
5890
7028
|
if (transaction.nonceInfo && signers) {
|
|
5891
7029
|
transaction.sign(...signers);
|
|
5892
7030
|
} else {
|
|
@@ -5967,12 +7105,34 @@ class Connection {
|
|
|
5967
7105
|
|
|
5968
7106
|
return res.result;
|
|
5969
7107
|
}
|
|
7108
|
+
/**
|
|
7109
|
+
* Sign and send a transaction
|
|
7110
|
+
*
|
|
7111
|
+
* @deprecated Instead, call {@link sendTransaction} with a {@link
|
|
7112
|
+
* VersionedTransaction}
|
|
7113
|
+
*/
|
|
7114
|
+
|
|
7115
|
+
|
|
5970
7116
|
/**
|
|
5971
7117
|
* Sign and send a transaction
|
|
5972
7118
|
*/
|
|
7119
|
+
// eslint-disable-next-line no-dupe-class-members
|
|
7120
|
+
async sendTransaction(transaction, signersOrOptions, options) {
|
|
7121
|
+
if ('version' in transaction) {
|
|
7122
|
+
if (signersOrOptions && Array.isArray(signersOrOptions)) {
|
|
7123
|
+
throw new Error('Invalid arguments');
|
|
7124
|
+
}
|
|
5973
7125
|
|
|
7126
|
+
const wireTransaction = transaction.serialize();
|
|
7127
|
+
return await this.sendRawTransaction(wireTransaction, options);
|
|
7128
|
+
}
|
|
7129
|
+
|
|
7130
|
+
if (signersOrOptions === undefined || !Array.isArray(signersOrOptions)) {
|
|
7131
|
+
throw new Error('Invalid arguments');
|
|
7132
|
+
}
|
|
7133
|
+
|
|
7134
|
+
const signers = signersOrOptions;
|
|
5974
7135
|
|
|
5975
|
-
async sendTransaction(transaction, signers, options) {
|
|
5976
7136
|
if (transaction.nonceInfo) {
|
|
5977
7137
|
transaction.sign(...signers);
|
|
5978
7138
|
} else {
|
|
@@ -6095,7 +7255,7 @@ class Connection {
|
|
|
6095
7255
|
|
|
6096
7256
|
_wsOnClose(code) {
|
|
6097
7257
|
this._rpcWebSocketConnected = false;
|
|
6098
|
-
this._rpcWebSocketGeneration
|
|
7258
|
+
this._rpcWebSocketGeneration = (this._rpcWebSocketGeneration + 1) % Number.MAX_SAFE_INTEGER;
|
|
6099
7259
|
|
|
6100
7260
|
if (this._rpcWebSocketIdleTimeout) {
|
|
6101
7261
|
clearTimeout(this._rpcWebSocketIdleTimeout);
|
|
@@ -6117,9 +7277,9 @@ class Connection {
|
|
|
6117
7277
|
|
|
6118
7278
|
this._subscriptionCallbacksByServerSubscriptionId = {};
|
|
6119
7279
|
Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => {
|
|
6120
|
-
this.
|
|
7280
|
+
this._setSubscription(hash, { ...subscription,
|
|
6121
7281
|
state: 'pending'
|
|
6122
|
-
};
|
|
7282
|
+
});
|
|
6123
7283
|
});
|
|
6124
7284
|
}
|
|
6125
7285
|
/**
|
|
@@ -6127,6 +7287,53 @@ class Connection {
|
|
|
6127
7287
|
*/
|
|
6128
7288
|
|
|
6129
7289
|
|
|
7290
|
+
_setSubscription(hash, nextSubscription) {
|
|
7291
|
+
var _this$_subscriptionsB;
|
|
7292
|
+
|
|
7293
|
+
const prevState = (_this$_subscriptionsB = this._subscriptionsByHash[hash]) === null || _this$_subscriptionsB === void 0 ? void 0 : _this$_subscriptionsB.state;
|
|
7294
|
+
this._subscriptionsByHash[hash] = nextSubscription;
|
|
7295
|
+
|
|
7296
|
+
if (prevState !== nextSubscription.state) {
|
|
7297
|
+
const stateChangeCallbacks = this._subscriptionStateChangeCallbacksByHash[hash];
|
|
7298
|
+
|
|
7299
|
+
if (stateChangeCallbacks) {
|
|
7300
|
+
stateChangeCallbacks.forEach(cb => {
|
|
7301
|
+
try {
|
|
7302
|
+
cb(nextSubscription.state); // eslint-disable-next-line no-empty
|
|
7303
|
+
} catch {}
|
|
7304
|
+
});
|
|
7305
|
+
}
|
|
7306
|
+
}
|
|
7307
|
+
}
|
|
7308
|
+
/**
|
|
7309
|
+
* @internal
|
|
7310
|
+
*/
|
|
7311
|
+
|
|
7312
|
+
|
|
7313
|
+
_onSubscriptionStateChange(clientSubscriptionId, callback) {
|
|
7314
|
+
var _this$_subscriptionSt;
|
|
7315
|
+
|
|
7316
|
+
const hash = this._subscriptionHashByClientSubscriptionId[clientSubscriptionId];
|
|
7317
|
+
|
|
7318
|
+
if (hash == null) {
|
|
7319
|
+
return () => {};
|
|
7320
|
+
}
|
|
7321
|
+
|
|
7322
|
+
const stateChangeCallbacks = (_this$_subscriptionSt = this._subscriptionStateChangeCallbacksByHash)[hash] || (_this$_subscriptionSt[hash] = new Set());
|
|
7323
|
+
stateChangeCallbacks.add(callback);
|
|
7324
|
+
return () => {
|
|
7325
|
+
stateChangeCallbacks.delete(callback);
|
|
7326
|
+
|
|
7327
|
+
if (stateChangeCallbacks.size === 0) {
|
|
7328
|
+
delete this._subscriptionStateChangeCallbacksByHash[hash];
|
|
7329
|
+
}
|
|
7330
|
+
};
|
|
7331
|
+
}
|
|
7332
|
+
/**
|
|
7333
|
+
* @internal
|
|
7334
|
+
*/
|
|
7335
|
+
|
|
7336
|
+
|
|
6130
7337
|
async _updateSubscriptions() {
|
|
6131
7338
|
if (Object.keys(this._subscriptionsByHash).length === 0) {
|
|
6132
7339
|
if (this._rpcWebSocketConnected) {
|
|
@@ -6212,14 +7419,17 @@ class Connection {
|
|
|
6212
7419
|
} = subscription;
|
|
6213
7420
|
|
|
6214
7421
|
try {
|
|
6215
|
-
this.
|
|
7422
|
+
this._setSubscription(hash, { ...subscription,
|
|
6216
7423
|
state: 'subscribing'
|
|
6217
|
-
};
|
|
7424
|
+
});
|
|
7425
|
+
|
|
6218
7426
|
const serverSubscriptionId = await this._rpcWebSocket.call(method, args);
|
|
6219
|
-
|
|
7427
|
+
|
|
7428
|
+
this._setSubscription(hash, { ...subscription,
|
|
6220
7429
|
serverSubscriptionId,
|
|
6221
7430
|
state: 'subscribed'
|
|
6222
|
-
};
|
|
7431
|
+
});
|
|
7432
|
+
|
|
6223
7433
|
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks;
|
|
6224
7434
|
await this._updateSubscriptions();
|
|
6225
7435
|
} catch (e) {
|
|
@@ -6232,9 +7442,10 @@ class Connection {
|
|
|
6232
7442
|
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
6233
7443
|
|
|
6234
7444
|
|
|
6235
|
-
this.
|
|
7445
|
+
this._setSubscription(hash, { ...subscription,
|
|
6236
7446
|
state: 'pending'
|
|
6237
|
-
};
|
|
7447
|
+
});
|
|
7448
|
+
|
|
6238
7449
|
await this._updateSubscriptions();
|
|
6239
7450
|
}
|
|
6240
7451
|
})();
|
|
@@ -6263,9 +7474,13 @@ class Connection {
|
|
|
6263
7474
|
*/
|
|
6264
7475
|
this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId);
|
|
6265
7476
|
} else {
|
|
6266
|
-
this.
|
|
7477
|
+
this._setSubscription(hash, { ...subscription,
|
|
6267
7478
|
state: 'unsubscribing'
|
|
6268
|
-
};
|
|
7479
|
+
});
|
|
7480
|
+
|
|
7481
|
+
this._setSubscription(hash, { ...subscription,
|
|
7482
|
+
state: 'unsubscribing'
|
|
7483
|
+
});
|
|
6269
7484
|
|
|
6270
7485
|
try {
|
|
6271
7486
|
await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]);
|
|
@@ -6279,17 +7494,19 @@ class Connection {
|
|
|
6279
7494
|
} // TODO: Maybe add an 'errored' state or a retry limit?
|
|
6280
7495
|
|
|
6281
7496
|
|
|
6282
|
-
this.
|
|
7497
|
+
this._setSubscription(hash, { ...subscription,
|
|
6283
7498
|
state: 'subscribed'
|
|
6284
|
-
};
|
|
7499
|
+
});
|
|
7500
|
+
|
|
6285
7501
|
await this._updateSubscriptions();
|
|
6286
7502
|
return;
|
|
6287
7503
|
}
|
|
6288
7504
|
}
|
|
6289
7505
|
|
|
6290
|
-
this.
|
|
7506
|
+
this._setSubscription(hash, { ...subscription,
|
|
6291
7507
|
state: 'unsubscribed'
|
|
6292
|
-
};
|
|
7508
|
+
});
|
|
7509
|
+
|
|
6293
7510
|
await this._updateSubscriptions();
|
|
6294
7511
|
})();
|
|
6295
7512
|
}
|
|
@@ -6382,8 +7599,11 @@ class Connection {
|
|
|
6382
7599
|
existingSubscription.callbacks.add(subscriptionConfig.callback);
|
|
6383
7600
|
}
|
|
6384
7601
|
|
|
7602
|
+
this._subscriptionHashByClientSubscriptionId[clientSubscriptionId] = hash;
|
|
7603
|
+
|
|
6385
7604
|
this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => {
|
|
6386
7605
|
delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId];
|
|
7606
|
+
delete this._subscriptionHashByClientSubscriptionId[clientSubscriptionId];
|
|
6387
7607
|
const subscription = this._subscriptionsByHash[hash];
|
|
6388
7608
|
assert(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`);
|
|
6389
7609
|
subscription.callbacks.delete(subscriptionConfig.callback);
|
|
@@ -6828,12 +8048,7 @@ class Keypair {
|
|
|
6828
8048
|
*/
|
|
6829
8049
|
constructor(keypair) {
|
|
6830
8050
|
this._keypair = void 0;
|
|
6831
|
-
|
|
6832
|
-
if (keypair) {
|
|
6833
|
-
this._keypair = keypair;
|
|
6834
|
-
} else {
|
|
6835
|
-
this._keypair = nacl.sign.keyPair();
|
|
6836
|
-
}
|
|
8051
|
+
this._keypair = keypair !== null && keypair !== void 0 ? keypair : generateKeypair();
|
|
6837
8052
|
}
|
|
6838
8053
|
/**
|
|
6839
8054
|
* Generate a new random keypair
|
|
@@ -6841,7 +8056,7 @@ class Keypair {
|
|
|
6841
8056
|
|
|
6842
8057
|
|
|
6843
8058
|
static generate() {
|
|
6844
|
-
return new Keypair(
|
|
8059
|
+
return new Keypair(generateKeypair());
|
|
6845
8060
|
}
|
|
6846
8061
|
/**
|
|
6847
8062
|
* Create a keypair from a raw secret key byte array.
|
|
@@ -6858,19 +8073,27 @@ class Keypair {
|
|
|
6858
8073
|
|
|
6859
8074
|
|
|
6860
8075
|
static fromSecretKey(secretKey, options) {
|
|
6861
|
-
|
|
8076
|
+
if (secretKey.byteLength !== 64) {
|
|
8077
|
+
throw new Error('bad secret key size');
|
|
8078
|
+
}
|
|
8079
|
+
|
|
8080
|
+
const publicKey = secretKey.slice(32, 64);
|
|
6862
8081
|
|
|
6863
8082
|
if (!options || !options.skipValidation) {
|
|
6864
|
-
const
|
|
6865
|
-
const
|
|
6866
|
-
const signature = nacl.sign.detached(signData, keypair.secretKey);
|
|
8083
|
+
const privateScalar = secretKey.slice(0, 32);
|
|
8084
|
+
const computedPublicKey = getPublicKey(privateScalar);
|
|
6867
8085
|
|
|
6868
|
-
|
|
6869
|
-
|
|
8086
|
+
for (let ii = 0; ii < 32; ii++) {
|
|
8087
|
+
if (publicKey[ii] !== computedPublicKey[ii]) {
|
|
8088
|
+
throw new Error('provided secretKey is invalid');
|
|
8089
|
+
}
|
|
6870
8090
|
}
|
|
6871
8091
|
}
|
|
6872
8092
|
|
|
6873
|
-
return new Keypair(
|
|
8093
|
+
return new Keypair({
|
|
8094
|
+
publicKey,
|
|
8095
|
+
secretKey
|
|
8096
|
+
});
|
|
6874
8097
|
}
|
|
6875
8098
|
/**
|
|
6876
8099
|
* Generate a keypair from a 32 byte seed.
|
|
@@ -6880,7 +8103,14 @@ class Keypair {
|
|
|
6880
8103
|
|
|
6881
8104
|
|
|
6882
8105
|
static fromSeed(seed) {
|
|
6883
|
-
|
|
8106
|
+
const publicKey = getPublicKey(seed);
|
|
8107
|
+
const secretKey = new Uint8Array(64);
|
|
8108
|
+
secretKey.set(seed);
|
|
8109
|
+
secretKey.set(publicKey, 32);
|
|
8110
|
+
return new Keypair({
|
|
8111
|
+
publicKey,
|
|
8112
|
+
secretKey
|
|
8113
|
+
});
|
|
6884
8114
|
}
|
|
6885
8115
|
/**
|
|
6886
8116
|
* The public key for this keypair
|
|
@@ -6896,7 +8126,7 @@ class Keypair {
|
|
|
6896
8126
|
|
|
6897
8127
|
|
|
6898
8128
|
get secretKey() {
|
|
6899
|
-
return this._keypair.secretKey;
|
|
8129
|
+
return new Uint8Array(this._keypair.secretKey);
|
|
6900
8130
|
}
|
|
6901
8131
|
|
|
6902
8132
|
}
|
|
@@ -7311,6 +8541,9 @@ class ComputeBudgetProgram {
|
|
|
7311
8541
|
*/
|
|
7312
8542
|
|
|
7313
8543
|
|
|
8544
|
+
/**
|
|
8545
|
+
* @deprecated Instead, call {@link setComputeUnitLimit} and/or {@link setComputeUnitPrice}
|
|
8546
|
+
*/
|
|
7314
8547
|
static requestUnits(params) {
|
|
7315
8548
|
const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits;
|
|
7316
8549
|
const data = encodeData(type, params);
|
|
@@ -7432,7 +8665,7 @@ class Ed25519Program {
|
|
|
7432
8665
|
try {
|
|
7433
8666
|
const keypair = Keypair.fromSecretKey(privateKey);
|
|
7434
8667
|
const publicKey = keypair.publicKey.toBytes();
|
|
7435
|
-
const signature =
|
|
8668
|
+
const signature = sign(message, keypair.secretKey);
|
|
7436
8669
|
return this.createInstructionWithPublicKey({
|
|
7437
8670
|
publicKey,
|
|
7438
8671
|
message,
|
|
@@ -7447,1042 +8680,20 @@ class Ed25519Program {
|
|
|
7447
8680
|
}
|
|
7448
8681
|
Ed25519Program.programId = new PublicKey('Ed25519SigVerify111111111111111111111111111');
|
|
7449
8682
|
|
|
7450
|
-
// HMAC (RFC 2104)
|
|
7451
|
-
class HMAC extends Hash {
|
|
7452
|
-
constructor(hash, _key) {
|
|
7453
|
-
super();
|
|
7454
|
-
this.finished = false;
|
|
7455
|
-
this.destroyed = false;
|
|
7456
|
-
assert$2.hash(hash);
|
|
7457
|
-
const key = toBytes(_key);
|
|
7458
|
-
this.iHash = hash.create();
|
|
7459
|
-
if (!(this.iHash instanceof Hash))
|
|
7460
|
-
throw new TypeError('Expected instance of class which extends utils.Hash');
|
|
7461
|
-
const blockLen = (this.blockLen = this.iHash.blockLen);
|
|
7462
|
-
this.outputLen = this.iHash.outputLen;
|
|
7463
|
-
const pad = new Uint8Array(blockLen);
|
|
7464
|
-
// blockLen can be bigger than outputLen
|
|
7465
|
-
pad.set(key.length > this.iHash.blockLen ? hash.create().update(key).digest() : key);
|
|
7466
|
-
for (let i = 0; i < pad.length; i++)
|
|
7467
|
-
pad[i] ^= 0x36;
|
|
7468
|
-
this.iHash.update(pad);
|
|
7469
|
-
// By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
|
|
7470
|
-
this.oHash = hash.create();
|
|
7471
|
-
// Undo internal XOR && apply outer XOR
|
|
7472
|
-
for (let i = 0; i < pad.length; i++)
|
|
7473
|
-
pad[i] ^= 0x36 ^ 0x5c;
|
|
7474
|
-
this.oHash.update(pad);
|
|
7475
|
-
pad.fill(0);
|
|
7476
|
-
}
|
|
7477
|
-
update(buf) {
|
|
7478
|
-
assert$2.exists(this);
|
|
7479
|
-
this.iHash.update(buf);
|
|
7480
|
-
return this;
|
|
7481
|
-
}
|
|
7482
|
-
digestInto(out) {
|
|
7483
|
-
assert$2.exists(this);
|
|
7484
|
-
assert$2.bytes(out, this.outputLen);
|
|
7485
|
-
this.finished = true;
|
|
7486
|
-
this.iHash.digestInto(out);
|
|
7487
|
-
this.oHash.update(out);
|
|
7488
|
-
this.oHash.digestInto(out);
|
|
7489
|
-
this.destroy();
|
|
7490
|
-
}
|
|
7491
|
-
digest() {
|
|
7492
|
-
const out = new Uint8Array(this.oHash.outputLen);
|
|
7493
|
-
this.digestInto(out);
|
|
7494
|
-
return out;
|
|
7495
|
-
}
|
|
7496
|
-
_cloneInto(to) {
|
|
7497
|
-
// Create new instance without calling constructor since key already in state and we don't know it.
|
|
7498
|
-
to || (to = Object.create(Object.getPrototypeOf(this), {}));
|
|
7499
|
-
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
|
|
7500
|
-
to = to;
|
|
7501
|
-
to.finished = finished;
|
|
7502
|
-
to.destroyed = destroyed;
|
|
7503
|
-
to.blockLen = blockLen;
|
|
7504
|
-
to.outputLen = outputLen;
|
|
7505
|
-
to.oHash = oHash._cloneInto(to.oHash);
|
|
7506
|
-
to.iHash = iHash._cloneInto(to.iHash);
|
|
7507
|
-
return to;
|
|
7508
|
-
}
|
|
7509
|
-
destroy() {
|
|
7510
|
-
this.destroyed = true;
|
|
7511
|
-
this.oHash.destroy();
|
|
7512
|
-
this.iHash.destroy();
|
|
7513
|
-
}
|
|
7514
|
-
}
|
|
7515
|
-
/**
|
|
7516
|
-
* HMAC: RFC2104 message authentication code.
|
|
7517
|
-
* @param hash - function that would be used e.g. sha256
|
|
7518
|
-
* @param key - message key
|
|
7519
|
-
* @param message - message data
|
|
7520
|
-
*/
|
|
7521
|
-
const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
|
|
7522
|
-
hmac.create = (hash, key) => new HMAC(hash, key);
|
|
7523
|
-
|
|
7524
|
-
var _nodeResolve_empty = {};
|
|
7525
|
-
|
|
7526
|
-
var nodeCrypto = /*#__PURE__*/Object.freeze({
|
|
7527
|
-
__proto__: null,
|
|
7528
|
-
'default': _nodeResolve_empty
|
|
7529
|
-
});
|
|
7530
|
-
|
|
7531
|
-
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */
|
|
7532
|
-
const _0n = BigInt(0);
|
|
7533
|
-
const _1n = BigInt(1);
|
|
7534
|
-
const _2n = BigInt(2);
|
|
7535
|
-
const _3n = BigInt(3);
|
|
7536
|
-
const _8n = BigInt(8);
|
|
7537
|
-
const POW_2_256 = _2n ** BigInt(256);
|
|
7538
|
-
const CURVE = {
|
|
7539
|
-
a: _0n,
|
|
7540
|
-
b: BigInt(7),
|
|
7541
|
-
P: POW_2_256 - _2n ** BigInt(32) - BigInt(977),
|
|
7542
|
-
n: POW_2_256 - BigInt('432420386565659656852420866394968145599'),
|
|
7543
|
-
h: _1n,
|
|
7544
|
-
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
|
7545
|
-
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
|
7546
|
-
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
|
7547
|
-
};
|
|
7548
|
-
function weistrass(x) {
|
|
7549
|
-
const { a, b } = CURVE;
|
|
7550
|
-
const x2 = mod(x * x);
|
|
7551
|
-
const x3 = mod(x2 * x);
|
|
7552
|
-
return mod(x3 + a * x + b);
|
|
7553
|
-
}
|
|
7554
|
-
const USE_ENDOMORPHISM = CURVE.a === _0n;
|
|
7555
|
-
class JacobianPoint {
|
|
7556
|
-
constructor(x, y, z) {
|
|
7557
|
-
this.x = x;
|
|
7558
|
-
this.y = y;
|
|
7559
|
-
this.z = z;
|
|
7560
|
-
}
|
|
7561
|
-
static fromAffine(p) {
|
|
7562
|
-
if (!(p instanceof Point)) {
|
|
7563
|
-
throw new TypeError('JacobianPoint#fromAffine: expected Point');
|
|
7564
|
-
}
|
|
7565
|
-
return new JacobianPoint(p.x, p.y, _1n);
|
|
7566
|
-
}
|
|
7567
|
-
static toAffineBatch(points) {
|
|
7568
|
-
const toInv = invertBatch(points.map((p) => p.z));
|
|
7569
|
-
return points.map((p, i) => p.toAffine(toInv[i]));
|
|
7570
|
-
}
|
|
7571
|
-
static normalizeZ(points) {
|
|
7572
|
-
return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine);
|
|
7573
|
-
}
|
|
7574
|
-
equals(other) {
|
|
7575
|
-
if (!(other instanceof JacobianPoint))
|
|
7576
|
-
throw new TypeError('JacobianPoint expected');
|
|
7577
|
-
const { x: X1, y: Y1, z: Z1 } = this;
|
|
7578
|
-
const { x: X2, y: Y2, z: Z2 } = other;
|
|
7579
|
-
const Z1Z1 = mod(Z1 ** _2n);
|
|
7580
|
-
const Z2Z2 = mod(Z2 ** _2n);
|
|
7581
|
-
const U1 = mod(X1 * Z2Z2);
|
|
7582
|
-
const U2 = mod(X2 * Z1Z1);
|
|
7583
|
-
const S1 = mod(mod(Y1 * Z2) * Z2Z2);
|
|
7584
|
-
const S2 = mod(mod(Y2 * Z1) * Z1Z1);
|
|
7585
|
-
return U1 === U2 && S1 === S2;
|
|
7586
|
-
}
|
|
7587
|
-
negate() {
|
|
7588
|
-
return new JacobianPoint(this.x, mod(-this.y), this.z);
|
|
7589
|
-
}
|
|
7590
|
-
double() {
|
|
7591
|
-
const { x: X1, y: Y1, z: Z1 } = this;
|
|
7592
|
-
const A = mod(X1 ** _2n);
|
|
7593
|
-
const B = mod(Y1 ** _2n);
|
|
7594
|
-
const C = mod(B ** _2n);
|
|
7595
|
-
const D = mod(_2n * (mod((X1 + B) ** _2n) - A - C));
|
|
7596
|
-
const E = mod(_3n * A);
|
|
7597
|
-
const F = mod(E ** _2n);
|
|
7598
|
-
const X3 = mod(F - _2n * D);
|
|
7599
|
-
const Y3 = mod(E * (D - X3) - _8n * C);
|
|
7600
|
-
const Z3 = mod(_2n * Y1 * Z1);
|
|
7601
|
-
return new JacobianPoint(X3, Y3, Z3);
|
|
7602
|
-
}
|
|
7603
|
-
add(other) {
|
|
7604
|
-
if (!(other instanceof JacobianPoint))
|
|
7605
|
-
throw new TypeError('JacobianPoint expected');
|
|
7606
|
-
const { x: X1, y: Y1, z: Z1 } = this;
|
|
7607
|
-
const { x: X2, y: Y2, z: Z2 } = other;
|
|
7608
|
-
if (X2 === _0n || Y2 === _0n)
|
|
7609
|
-
return this;
|
|
7610
|
-
if (X1 === _0n || Y1 === _0n)
|
|
7611
|
-
return other;
|
|
7612
|
-
const Z1Z1 = mod(Z1 ** _2n);
|
|
7613
|
-
const Z2Z2 = mod(Z2 ** _2n);
|
|
7614
|
-
const U1 = mod(X1 * Z2Z2);
|
|
7615
|
-
const U2 = mod(X2 * Z1Z1);
|
|
7616
|
-
const S1 = mod(mod(Y1 * Z2) * Z2Z2);
|
|
7617
|
-
const S2 = mod(mod(Y2 * Z1) * Z1Z1);
|
|
7618
|
-
const H = mod(U2 - U1);
|
|
7619
|
-
const r = mod(S2 - S1);
|
|
7620
|
-
if (H === _0n) {
|
|
7621
|
-
if (r === _0n) {
|
|
7622
|
-
return this.double();
|
|
7623
|
-
}
|
|
7624
|
-
else {
|
|
7625
|
-
return JacobianPoint.ZERO;
|
|
7626
|
-
}
|
|
7627
|
-
}
|
|
7628
|
-
const HH = mod(H ** _2n);
|
|
7629
|
-
const HHH = mod(H * HH);
|
|
7630
|
-
const V = mod(U1 * HH);
|
|
7631
|
-
const X3 = mod(r ** _2n - HHH - _2n * V);
|
|
7632
|
-
const Y3 = mod(r * (V - X3) - S1 * HHH);
|
|
7633
|
-
const Z3 = mod(Z1 * Z2 * H);
|
|
7634
|
-
return new JacobianPoint(X3, Y3, Z3);
|
|
7635
|
-
}
|
|
7636
|
-
subtract(other) {
|
|
7637
|
-
return this.add(other.negate());
|
|
7638
|
-
}
|
|
7639
|
-
multiplyUnsafe(scalar) {
|
|
7640
|
-
const P0 = JacobianPoint.ZERO;
|
|
7641
|
-
if (typeof scalar === 'bigint' && scalar === _0n)
|
|
7642
|
-
return P0;
|
|
7643
|
-
let n = normalizeScalar(scalar);
|
|
7644
|
-
if (n === _1n)
|
|
7645
|
-
return this;
|
|
7646
|
-
if (!USE_ENDOMORPHISM) {
|
|
7647
|
-
let p = P0;
|
|
7648
|
-
let d = this;
|
|
7649
|
-
while (n > _0n) {
|
|
7650
|
-
if (n & _1n)
|
|
7651
|
-
p = p.add(d);
|
|
7652
|
-
d = d.double();
|
|
7653
|
-
n >>= _1n;
|
|
7654
|
-
}
|
|
7655
|
-
return p;
|
|
7656
|
-
}
|
|
7657
|
-
let { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
|
|
7658
|
-
let k1p = P0;
|
|
7659
|
-
let k2p = P0;
|
|
7660
|
-
let d = this;
|
|
7661
|
-
while (k1 > _0n || k2 > _0n) {
|
|
7662
|
-
if (k1 & _1n)
|
|
7663
|
-
k1p = k1p.add(d);
|
|
7664
|
-
if (k2 & _1n)
|
|
7665
|
-
k2p = k2p.add(d);
|
|
7666
|
-
d = d.double();
|
|
7667
|
-
k1 >>= _1n;
|
|
7668
|
-
k2 >>= _1n;
|
|
7669
|
-
}
|
|
7670
|
-
if (k1neg)
|
|
7671
|
-
k1p = k1p.negate();
|
|
7672
|
-
if (k2neg)
|
|
7673
|
-
k2p = k2p.negate();
|
|
7674
|
-
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
|
|
7675
|
-
return k1p.add(k2p);
|
|
7676
|
-
}
|
|
7677
|
-
precomputeWindow(W) {
|
|
7678
|
-
const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1;
|
|
7679
|
-
const points = [];
|
|
7680
|
-
let p = this;
|
|
7681
|
-
let base = p;
|
|
7682
|
-
for (let window = 0; window < windows; window++) {
|
|
7683
|
-
base = p;
|
|
7684
|
-
points.push(base);
|
|
7685
|
-
for (let i = 1; i < 2 ** (W - 1); i++) {
|
|
7686
|
-
base = base.add(p);
|
|
7687
|
-
points.push(base);
|
|
7688
|
-
}
|
|
7689
|
-
p = base.double();
|
|
7690
|
-
}
|
|
7691
|
-
return points;
|
|
7692
|
-
}
|
|
7693
|
-
wNAF(n, affinePoint) {
|
|
7694
|
-
if (!affinePoint && this.equals(JacobianPoint.BASE))
|
|
7695
|
-
affinePoint = Point.BASE;
|
|
7696
|
-
const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;
|
|
7697
|
-
if (256 % W) {
|
|
7698
|
-
throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2');
|
|
7699
|
-
}
|
|
7700
|
-
let precomputes = affinePoint && pointPrecomputes.get(affinePoint);
|
|
7701
|
-
if (!precomputes) {
|
|
7702
|
-
precomputes = this.precomputeWindow(W);
|
|
7703
|
-
if (affinePoint && W !== 1) {
|
|
7704
|
-
precomputes = JacobianPoint.normalizeZ(precomputes);
|
|
7705
|
-
pointPrecomputes.set(affinePoint, precomputes);
|
|
7706
|
-
}
|
|
7707
|
-
}
|
|
7708
|
-
let p = JacobianPoint.ZERO;
|
|
7709
|
-
let f = JacobianPoint.ZERO;
|
|
7710
|
-
const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W);
|
|
7711
|
-
const windowSize = 2 ** (W - 1);
|
|
7712
|
-
const mask = BigInt(2 ** W - 1);
|
|
7713
|
-
const maxNumber = 2 ** W;
|
|
7714
|
-
const shiftBy = BigInt(W);
|
|
7715
|
-
for (let window = 0; window < windows; window++) {
|
|
7716
|
-
const offset = window * windowSize;
|
|
7717
|
-
let wbits = Number(n & mask);
|
|
7718
|
-
n >>= shiftBy;
|
|
7719
|
-
if (wbits > windowSize) {
|
|
7720
|
-
wbits -= maxNumber;
|
|
7721
|
-
n += _1n;
|
|
7722
|
-
}
|
|
7723
|
-
if (wbits === 0) {
|
|
7724
|
-
let pr = precomputes[offset];
|
|
7725
|
-
if (window % 2)
|
|
7726
|
-
pr = pr.negate();
|
|
7727
|
-
f = f.add(pr);
|
|
7728
|
-
}
|
|
7729
|
-
else {
|
|
7730
|
-
let cached = precomputes[offset + Math.abs(wbits) - 1];
|
|
7731
|
-
if (wbits < 0)
|
|
7732
|
-
cached = cached.negate();
|
|
7733
|
-
p = p.add(cached);
|
|
7734
|
-
}
|
|
7735
|
-
}
|
|
7736
|
-
return { p, f };
|
|
7737
|
-
}
|
|
7738
|
-
multiply(scalar, affinePoint) {
|
|
7739
|
-
let n = normalizeScalar(scalar);
|
|
7740
|
-
let point;
|
|
7741
|
-
let fake;
|
|
7742
|
-
if (USE_ENDOMORPHISM) {
|
|
7743
|
-
const { k1neg, k1, k2neg, k2 } = splitScalarEndo(n);
|
|
7744
|
-
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
|
|
7745
|
-
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
|
|
7746
|
-
if (k1neg)
|
|
7747
|
-
k1p = k1p.negate();
|
|
7748
|
-
if (k2neg)
|
|
7749
|
-
k2p = k2p.negate();
|
|
7750
|
-
k2p = new JacobianPoint(mod(k2p.x * CURVE.beta), k2p.y, k2p.z);
|
|
7751
|
-
point = k1p.add(k2p);
|
|
7752
|
-
fake = f1p.add(f2p);
|
|
7753
|
-
}
|
|
7754
|
-
else {
|
|
7755
|
-
const { p, f } = this.wNAF(n, affinePoint);
|
|
7756
|
-
point = p;
|
|
7757
|
-
fake = f;
|
|
7758
|
-
}
|
|
7759
|
-
return JacobianPoint.normalizeZ([point, fake])[0];
|
|
7760
|
-
}
|
|
7761
|
-
toAffine(invZ = invert(this.z)) {
|
|
7762
|
-
const { x, y, z } = this;
|
|
7763
|
-
const iz1 = invZ;
|
|
7764
|
-
const iz2 = mod(iz1 * iz1);
|
|
7765
|
-
const iz3 = mod(iz2 * iz1);
|
|
7766
|
-
const ax = mod(x * iz2);
|
|
7767
|
-
const ay = mod(y * iz3);
|
|
7768
|
-
const zz = mod(z * iz1);
|
|
7769
|
-
if (zz !== _1n)
|
|
7770
|
-
throw new Error('invZ was invalid');
|
|
7771
|
-
return new Point(ax, ay);
|
|
7772
|
-
}
|
|
7773
|
-
}
|
|
7774
|
-
JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n);
|
|
7775
|
-
JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);
|
|
7776
|
-
const pointPrecomputes = new WeakMap();
|
|
7777
|
-
class Point {
|
|
7778
|
-
constructor(x, y) {
|
|
7779
|
-
this.x = x;
|
|
7780
|
-
this.y = y;
|
|
7781
|
-
}
|
|
7782
|
-
_setWindowSize(windowSize) {
|
|
7783
|
-
this._WINDOW_SIZE = windowSize;
|
|
7784
|
-
pointPrecomputes.delete(this);
|
|
7785
|
-
}
|
|
7786
|
-
static fromCompressedHex(bytes) {
|
|
7787
|
-
const isShort = bytes.length === 32;
|
|
7788
|
-
const x = bytesToNumber(isShort ? bytes : bytes.subarray(1));
|
|
7789
|
-
if (!isValidFieldElement(x))
|
|
7790
|
-
throw new Error('Point is not on curve');
|
|
7791
|
-
const y2 = weistrass(x);
|
|
7792
|
-
let y = sqrtMod(y2);
|
|
7793
|
-
const isYOdd = (y & _1n) === _1n;
|
|
7794
|
-
if (isShort) {
|
|
7795
|
-
if (isYOdd)
|
|
7796
|
-
y = mod(-y);
|
|
7797
|
-
}
|
|
7798
|
-
else {
|
|
7799
|
-
const isFirstByteOdd = (bytes[0] & 1) === 1;
|
|
7800
|
-
if (isFirstByteOdd !== isYOdd)
|
|
7801
|
-
y = mod(-y);
|
|
7802
|
-
}
|
|
7803
|
-
const point = new Point(x, y);
|
|
7804
|
-
point.assertValidity();
|
|
7805
|
-
return point;
|
|
7806
|
-
}
|
|
7807
|
-
static fromUncompressedHex(bytes) {
|
|
7808
|
-
const x = bytesToNumber(bytes.subarray(1, 33));
|
|
7809
|
-
const y = bytesToNumber(bytes.subarray(33, 65));
|
|
7810
|
-
const point = new Point(x, y);
|
|
7811
|
-
point.assertValidity();
|
|
7812
|
-
return point;
|
|
7813
|
-
}
|
|
7814
|
-
static fromHex(hex) {
|
|
7815
|
-
const bytes = ensureBytes(hex);
|
|
7816
|
-
const len = bytes.length;
|
|
7817
|
-
const header = bytes[0];
|
|
7818
|
-
if (len === 32 || (len === 33 && (header === 0x02 || header === 0x03))) {
|
|
7819
|
-
return this.fromCompressedHex(bytes);
|
|
7820
|
-
}
|
|
7821
|
-
if (len === 65 && header === 0x04)
|
|
7822
|
-
return this.fromUncompressedHex(bytes);
|
|
7823
|
-
throw new Error(`Point.fromHex: received invalid point. Expected 32-33 compressed bytes or 65 uncompressed bytes, not ${len}`);
|
|
7824
|
-
}
|
|
7825
|
-
static fromPrivateKey(privateKey) {
|
|
7826
|
-
return Point.BASE.multiply(normalizePrivateKey(privateKey));
|
|
7827
|
-
}
|
|
7828
|
-
static fromSignature(msgHash, signature, recovery) {
|
|
7829
|
-
msgHash = ensureBytes(msgHash);
|
|
7830
|
-
const h = truncateHash(msgHash);
|
|
7831
|
-
const { r, s } = normalizeSignature(signature);
|
|
7832
|
-
if (recovery !== 0 && recovery !== 1) {
|
|
7833
|
-
throw new Error('Cannot recover signature: invalid recovery bit');
|
|
7834
|
-
}
|
|
7835
|
-
const prefix = recovery & 1 ? '03' : '02';
|
|
7836
|
-
const R = Point.fromHex(prefix + numTo32bStr(r));
|
|
7837
|
-
const { n } = CURVE;
|
|
7838
|
-
const rinv = invert(r, n);
|
|
7839
|
-
const u1 = mod(-h * rinv, n);
|
|
7840
|
-
const u2 = mod(s * rinv, n);
|
|
7841
|
-
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);
|
|
7842
|
-
if (!Q)
|
|
7843
|
-
throw new Error('Cannot recover signature: point at infinify');
|
|
7844
|
-
Q.assertValidity();
|
|
7845
|
-
return Q;
|
|
7846
|
-
}
|
|
7847
|
-
toRawBytes(isCompressed = false) {
|
|
7848
|
-
return hexToBytes(this.toHex(isCompressed));
|
|
7849
|
-
}
|
|
7850
|
-
toHex(isCompressed = false) {
|
|
7851
|
-
const x = numTo32bStr(this.x);
|
|
7852
|
-
if (isCompressed) {
|
|
7853
|
-
const prefix = this.y & _1n ? '03' : '02';
|
|
7854
|
-
return `${prefix}${x}`;
|
|
7855
|
-
}
|
|
7856
|
-
else {
|
|
7857
|
-
return `04${x}${numTo32bStr(this.y)}`;
|
|
7858
|
-
}
|
|
7859
|
-
}
|
|
7860
|
-
toHexX() {
|
|
7861
|
-
return this.toHex(true).slice(2);
|
|
7862
|
-
}
|
|
7863
|
-
toRawX() {
|
|
7864
|
-
return this.toRawBytes(true).slice(1);
|
|
7865
|
-
}
|
|
7866
|
-
assertValidity() {
|
|
7867
|
-
const msg = 'Point is not on elliptic curve';
|
|
7868
|
-
const { x, y } = this;
|
|
7869
|
-
if (!isValidFieldElement(x) || !isValidFieldElement(y))
|
|
7870
|
-
throw new Error(msg);
|
|
7871
|
-
const left = mod(y * y);
|
|
7872
|
-
const right = weistrass(x);
|
|
7873
|
-
if (mod(left - right) !== _0n)
|
|
7874
|
-
throw new Error(msg);
|
|
7875
|
-
}
|
|
7876
|
-
equals(other) {
|
|
7877
|
-
return this.x === other.x && this.y === other.y;
|
|
7878
|
-
}
|
|
7879
|
-
negate() {
|
|
7880
|
-
return new Point(this.x, mod(-this.y));
|
|
7881
|
-
}
|
|
7882
|
-
double() {
|
|
7883
|
-
return JacobianPoint.fromAffine(this).double().toAffine();
|
|
7884
|
-
}
|
|
7885
|
-
add(other) {
|
|
7886
|
-
return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine();
|
|
7887
|
-
}
|
|
7888
|
-
subtract(other) {
|
|
7889
|
-
return this.add(other.negate());
|
|
7890
|
-
}
|
|
7891
|
-
multiply(scalar) {
|
|
7892
|
-
return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine();
|
|
7893
|
-
}
|
|
7894
|
-
multiplyAndAddUnsafe(Q, a, b) {
|
|
7895
|
-
const P = JacobianPoint.fromAffine(this);
|
|
7896
|
-
const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a);
|
|
7897
|
-
const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b);
|
|
7898
|
-
const sum = aP.add(bQ);
|
|
7899
|
-
return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine();
|
|
7900
|
-
}
|
|
7901
|
-
}
|
|
7902
|
-
Point.BASE = new Point(CURVE.Gx, CURVE.Gy);
|
|
7903
|
-
Point.ZERO = new Point(_0n, _0n);
|
|
7904
|
-
function sliceDER(s) {
|
|
7905
|
-
return Number.parseInt(s[0], 16) >= 8 ? '00' + s : s;
|
|
7906
|
-
}
|
|
7907
|
-
function parseDERInt(data) {
|
|
7908
|
-
if (data.length < 2 || data[0] !== 0x02) {
|
|
7909
|
-
throw new Error(`Invalid signature integer tag: ${bytesToHex(data)}`);
|
|
7910
|
-
}
|
|
7911
|
-
const len = data[1];
|
|
7912
|
-
const res = data.subarray(2, len + 2);
|
|
7913
|
-
if (!len || res.length !== len) {
|
|
7914
|
-
throw new Error(`Invalid signature integer: wrong length`);
|
|
7915
|
-
}
|
|
7916
|
-
if (res[0] === 0x00 && res[1] <= 0x7f) {
|
|
7917
|
-
throw new Error('Invalid signature integer: trailing length');
|
|
7918
|
-
}
|
|
7919
|
-
return { data: bytesToNumber(res), left: data.subarray(len + 2) };
|
|
7920
|
-
}
|
|
7921
|
-
function parseDERSignature(data) {
|
|
7922
|
-
if (data.length < 2 || data[0] != 0x30) {
|
|
7923
|
-
throw new Error(`Invalid signature tag: ${bytesToHex(data)}`);
|
|
7924
|
-
}
|
|
7925
|
-
if (data[1] !== data.length - 2) {
|
|
7926
|
-
throw new Error('Invalid signature: incorrect length');
|
|
7927
|
-
}
|
|
7928
|
-
const { data: r, left: sBytes } = parseDERInt(data.subarray(2));
|
|
7929
|
-
const { data: s, left: rBytesLeft } = parseDERInt(sBytes);
|
|
7930
|
-
if (rBytesLeft.length) {
|
|
7931
|
-
throw new Error(`Invalid signature: left bytes after parsing: ${bytesToHex(rBytesLeft)}`);
|
|
7932
|
-
}
|
|
7933
|
-
return { r, s };
|
|
7934
|
-
}
|
|
7935
|
-
class Signature {
|
|
7936
|
-
constructor(r, s) {
|
|
7937
|
-
this.r = r;
|
|
7938
|
-
this.s = s;
|
|
7939
|
-
this.assertValidity();
|
|
7940
|
-
}
|
|
7941
|
-
static fromCompact(hex) {
|
|
7942
|
-
const arr = isUint8a(hex);
|
|
7943
|
-
const name = 'Signature.fromCompact';
|
|
7944
|
-
if (typeof hex !== 'string' && !arr)
|
|
7945
|
-
throw new TypeError(`${name}: Expected string or Uint8Array`);
|
|
7946
|
-
const str = arr ? bytesToHex(hex) : hex;
|
|
7947
|
-
if (str.length !== 128)
|
|
7948
|
-
throw new Error(`${name}: Expected 64-byte hex`);
|
|
7949
|
-
return new Signature(hexToNumber(str.slice(0, 64)), hexToNumber(str.slice(64, 128)));
|
|
7950
|
-
}
|
|
7951
|
-
static fromDER(hex) {
|
|
7952
|
-
const arr = isUint8a(hex);
|
|
7953
|
-
if (typeof hex !== 'string' && !arr)
|
|
7954
|
-
throw new TypeError(`Signature.fromDER: Expected string or Uint8Array`);
|
|
7955
|
-
const { r, s } = parseDERSignature(arr ? hex : hexToBytes(hex));
|
|
7956
|
-
return new Signature(r, s);
|
|
7957
|
-
}
|
|
7958
|
-
static fromHex(hex) {
|
|
7959
|
-
return this.fromDER(hex);
|
|
7960
|
-
}
|
|
7961
|
-
assertValidity() {
|
|
7962
|
-
const { r, s } = this;
|
|
7963
|
-
if (!isWithinCurveOrder(r))
|
|
7964
|
-
throw new Error('Invalid Signature: r must be 0 < r < n');
|
|
7965
|
-
if (!isWithinCurveOrder(s))
|
|
7966
|
-
throw new Error('Invalid Signature: s must be 0 < s < n');
|
|
7967
|
-
}
|
|
7968
|
-
hasHighS() {
|
|
7969
|
-
const HALF = CURVE.n >> _1n;
|
|
7970
|
-
return this.s > HALF;
|
|
7971
|
-
}
|
|
7972
|
-
normalizeS() {
|
|
7973
|
-
return this.hasHighS() ? new Signature(this.r, CURVE.n - this.s) : this;
|
|
7974
|
-
}
|
|
7975
|
-
toDERRawBytes(isCompressed = false) {
|
|
7976
|
-
return hexToBytes(this.toDERHex(isCompressed));
|
|
7977
|
-
}
|
|
7978
|
-
toDERHex(isCompressed = false) {
|
|
7979
|
-
const sHex = sliceDER(numberToHexUnpadded(this.s));
|
|
7980
|
-
if (isCompressed)
|
|
7981
|
-
return sHex;
|
|
7982
|
-
const rHex = sliceDER(numberToHexUnpadded(this.r));
|
|
7983
|
-
const rLen = numberToHexUnpadded(rHex.length / 2);
|
|
7984
|
-
const sLen = numberToHexUnpadded(sHex.length / 2);
|
|
7985
|
-
const length = numberToHexUnpadded(rHex.length / 2 + sHex.length / 2 + 4);
|
|
7986
|
-
return `30${length}02${rLen}${rHex}02${sLen}${sHex}`;
|
|
7987
|
-
}
|
|
7988
|
-
toRawBytes() {
|
|
7989
|
-
return this.toDERRawBytes();
|
|
7990
|
-
}
|
|
7991
|
-
toHex() {
|
|
7992
|
-
return this.toDERHex();
|
|
7993
|
-
}
|
|
7994
|
-
toCompactRawBytes() {
|
|
7995
|
-
return hexToBytes(this.toCompactHex());
|
|
7996
|
-
}
|
|
7997
|
-
toCompactHex() {
|
|
7998
|
-
return numTo32bStr(this.r) + numTo32bStr(this.s);
|
|
7999
|
-
}
|
|
8000
|
-
}
|
|
8001
|
-
function concatBytes(...arrays) {
|
|
8002
|
-
if (!arrays.every(isUint8a))
|
|
8003
|
-
throw new Error('Uint8Array list expected');
|
|
8004
|
-
if (arrays.length === 1)
|
|
8005
|
-
return arrays[0];
|
|
8006
|
-
const length = arrays.reduce((a, arr) => a + arr.length, 0);
|
|
8007
|
-
const result = new Uint8Array(length);
|
|
8008
|
-
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
8009
|
-
const arr = arrays[i];
|
|
8010
|
-
result.set(arr, pad);
|
|
8011
|
-
pad += arr.length;
|
|
8012
|
-
}
|
|
8013
|
-
return result;
|
|
8014
|
-
}
|
|
8015
|
-
function isUint8a(bytes) {
|
|
8016
|
-
return bytes instanceof Uint8Array;
|
|
8017
|
-
}
|
|
8018
|
-
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
|
|
8019
|
-
function bytesToHex(uint8a) {
|
|
8020
|
-
if (!(uint8a instanceof Uint8Array))
|
|
8021
|
-
throw new Error('Expected Uint8Array');
|
|
8022
|
-
let hex = '';
|
|
8023
|
-
for (let i = 0; i < uint8a.length; i++) {
|
|
8024
|
-
hex += hexes[uint8a[i]];
|
|
8025
|
-
}
|
|
8026
|
-
return hex;
|
|
8027
|
-
}
|
|
8028
|
-
function numTo32bStr(num) {
|
|
8029
|
-
if (num > POW_2_256)
|
|
8030
|
-
throw new Error('Expected number < 2^256');
|
|
8031
|
-
return num.toString(16).padStart(64, '0');
|
|
8032
|
-
}
|
|
8033
|
-
function numTo32b(num) {
|
|
8034
|
-
return hexToBytes(numTo32bStr(num));
|
|
8035
|
-
}
|
|
8036
|
-
function numberToHexUnpadded(num) {
|
|
8037
|
-
const hex = num.toString(16);
|
|
8038
|
-
return hex.length & 1 ? `0${hex}` : hex;
|
|
8039
|
-
}
|
|
8040
|
-
function hexToNumber(hex) {
|
|
8041
|
-
if (typeof hex !== 'string') {
|
|
8042
|
-
throw new TypeError('hexToNumber: expected string, got ' + typeof hex);
|
|
8043
|
-
}
|
|
8044
|
-
return BigInt(`0x${hex}`);
|
|
8045
|
-
}
|
|
8046
|
-
function hexToBytes(hex) {
|
|
8047
|
-
if (typeof hex !== 'string') {
|
|
8048
|
-
throw new TypeError('hexToBytes: expected string, got ' + typeof hex);
|
|
8049
|
-
}
|
|
8050
|
-
if (hex.length % 2)
|
|
8051
|
-
throw new Error('hexToBytes: received invalid unpadded hex' + hex.length);
|
|
8052
|
-
const array = new Uint8Array(hex.length / 2);
|
|
8053
|
-
for (let i = 0; i < array.length; i++) {
|
|
8054
|
-
const j = i * 2;
|
|
8055
|
-
const hexByte = hex.slice(j, j + 2);
|
|
8056
|
-
const byte = Number.parseInt(hexByte, 16);
|
|
8057
|
-
if (Number.isNaN(byte) || byte < 0)
|
|
8058
|
-
throw new Error('Invalid byte sequence');
|
|
8059
|
-
array[i] = byte;
|
|
8060
|
-
}
|
|
8061
|
-
return array;
|
|
8062
|
-
}
|
|
8063
|
-
function bytesToNumber(bytes) {
|
|
8064
|
-
return hexToNumber(bytesToHex(bytes));
|
|
8065
|
-
}
|
|
8066
|
-
function ensureBytes(hex) {
|
|
8067
|
-
return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex);
|
|
8068
|
-
}
|
|
8069
|
-
function normalizeScalar(num) {
|
|
8070
|
-
if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0)
|
|
8071
|
-
return BigInt(num);
|
|
8072
|
-
if (typeof num === 'bigint' && isWithinCurveOrder(num))
|
|
8073
|
-
return num;
|
|
8074
|
-
throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n');
|
|
8075
|
-
}
|
|
8076
|
-
function mod(a, b = CURVE.P) {
|
|
8077
|
-
const result = a % b;
|
|
8078
|
-
return result >= _0n ? result : b + result;
|
|
8079
|
-
}
|
|
8080
|
-
function pow2(x, power) {
|
|
8081
|
-
const { P } = CURVE;
|
|
8082
|
-
let res = x;
|
|
8083
|
-
while (power-- > _0n) {
|
|
8084
|
-
res *= res;
|
|
8085
|
-
res %= P;
|
|
8086
|
-
}
|
|
8087
|
-
return res;
|
|
8088
|
-
}
|
|
8089
|
-
function sqrtMod(x) {
|
|
8090
|
-
const { P } = CURVE;
|
|
8091
|
-
const _6n = BigInt(6);
|
|
8092
|
-
const _11n = BigInt(11);
|
|
8093
|
-
const _22n = BigInt(22);
|
|
8094
|
-
const _23n = BigInt(23);
|
|
8095
|
-
const _44n = BigInt(44);
|
|
8096
|
-
const _88n = BigInt(88);
|
|
8097
|
-
const b2 = (x * x * x) % P;
|
|
8098
|
-
const b3 = (b2 * b2 * x) % P;
|
|
8099
|
-
const b6 = (pow2(b3, _3n) * b3) % P;
|
|
8100
|
-
const b9 = (pow2(b6, _3n) * b3) % P;
|
|
8101
|
-
const b11 = (pow2(b9, _2n) * b2) % P;
|
|
8102
|
-
const b22 = (pow2(b11, _11n) * b11) % P;
|
|
8103
|
-
const b44 = (pow2(b22, _22n) * b22) % P;
|
|
8104
|
-
const b88 = (pow2(b44, _44n) * b44) % P;
|
|
8105
|
-
const b176 = (pow2(b88, _88n) * b88) % P;
|
|
8106
|
-
const b220 = (pow2(b176, _44n) * b44) % P;
|
|
8107
|
-
const b223 = (pow2(b220, _3n) * b3) % P;
|
|
8108
|
-
const t1 = (pow2(b223, _23n) * b22) % P;
|
|
8109
|
-
const t2 = (pow2(t1, _6n) * b2) % P;
|
|
8110
|
-
return pow2(t2, _2n);
|
|
8111
|
-
}
|
|
8112
|
-
function invert(number, modulo = CURVE.P) {
|
|
8113
|
-
if (number === _0n || modulo <= _0n) {
|
|
8114
|
-
throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
|
|
8115
|
-
}
|
|
8116
|
-
let a = mod(number, modulo);
|
|
8117
|
-
let b = modulo;
|
|
8118
|
-
let x = _0n, u = _1n;
|
|
8119
|
-
while (a !== _0n) {
|
|
8120
|
-
const q = b / a;
|
|
8121
|
-
const r = b % a;
|
|
8122
|
-
const m = x - u * q;
|
|
8123
|
-
b = a, a = r, x = u, u = m;
|
|
8124
|
-
}
|
|
8125
|
-
const gcd = b;
|
|
8126
|
-
if (gcd !== _1n)
|
|
8127
|
-
throw new Error('invert: does not exist');
|
|
8128
|
-
return mod(x, modulo);
|
|
8129
|
-
}
|
|
8130
|
-
function invertBatch(nums, p = CURVE.P) {
|
|
8131
|
-
const scratch = new Array(nums.length);
|
|
8132
|
-
const lastMultiplied = nums.reduce((acc, num, i) => {
|
|
8133
|
-
if (num === _0n)
|
|
8134
|
-
return acc;
|
|
8135
|
-
scratch[i] = acc;
|
|
8136
|
-
return mod(acc * num, p);
|
|
8137
|
-
}, _1n);
|
|
8138
|
-
const inverted = invert(lastMultiplied, p);
|
|
8139
|
-
nums.reduceRight((acc, num, i) => {
|
|
8140
|
-
if (num === _0n)
|
|
8141
|
-
return acc;
|
|
8142
|
-
scratch[i] = mod(acc * scratch[i], p);
|
|
8143
|
-
return mod(acc * num, p);
|
|
8144
|
-
}, inverted);
|
|
8145
|
-
return scratch;
|
|
8146
|
-
}
|
|
8147
|
-
const divNearest = (a, b) => (a + b / _2n) / b;
|
|
8148
|
-
const POW_2_128 = _2n ** BigInt(128);
|
|
8149
|
-
function splitScalarEndo(k) {
|
|
8150
|
-
const { n } = CURVE;
|
|
8151
|
-
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
|
|
8152
|
-
const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
|
|
8153
|
-
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
|
|
8154
|
-
const b2 = a1;
|
|
8155
|
-
const c1 = divNearest(b2 * k, n);
|
|
8156
|
-
const c2 = divNearest(-b1 * k, n);
|
|
8157
|
-
let k1 = mod(k - c1 * a1 - c2 * a2, n);
|
|
8158
|
-
let k2 = mod(-c1 * b1 - c2 * b2, n);
|
|
8159
|
-
const k1neg = k1 > POW_2_128;
|
|
8160
|
-
const k2neg = k2 > POW_2_128;
|
|
8161
|
-
if (k1neg)
|
|
8162
|
-
k1 = n - k1;
|
|
8163
|
-
if (k2neg)
|
|
8164
|
-
k2 = n - k2;
|
|
8165
|
-
if (k1 > POW_2_128 || k2 > POW_2_128) {
|
|
8166
|
-
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
|
|
8167
|
-
}
|
|
8168
|
-
return { k1neg, k1, k2neg, k2 };
|
|
8169
|
-
}
|
|
8170
|
-
function truncateHash(hash) {
|
|
8171
|
-
const { n } = CURVE;
|
|
8172
|
-
const byteLength = hash.length;
|
|
8173
|
-
const delta = byteLength * 8 - 256;
|
|
8174
|
-
let h = bytesToNumber(hash);
|
|
8175
|
-
if (delta > 0)
|
|
8176
|
-
h = h >> BigInt(delta);
|
|
8177
|
-
if (h >= n)
|
|
8178
|
-
h -= n;
|
|
8179
|
-
return h;
|
|
8180
|
-
}
|
|
8181
|
-
class HmacDrbg {
|
|
8182
|
-
constructor() {
|
|
8183
|
-
this.v = new Uint8Array(32).fill(1);
|
|
8184
|
-
this.k = new Uint8Array(32).fill(0);
|
|
8185
|
-
this.counter = 0;
|
|
8186
|
-
}
|
|
8187
|
-
hmac(...values) {
|
|
8188
|
-
return utils.hmacSha256(this.k, ...values);
|
|
8189
|
-
}
|
|
8190
|
-
hmacSync(...values) {
|
|
8191
|
-
if (typeof utils.hmacSha256Sync !== 'function')
|
|
8192
|
-
throw new Error('utils.hmacSha256Sync is undefined, you need to set it');
|
|
8193
|
-
const res = utils.hmacSha256Sync(this.k, ...values);
|
|
8194
|
-
if (res instanceof Promise)
|
|
8195
|
-
throw new Error('To use sync sign(), ensure utils.hmacSha256 is sync');
|
|
8196
|
-
return res;
|
|
8197
|
-
}
|
|
8198
|
-
incr() {
|
|
8199
|
-
if (this.counter >= 1000) {
|
|
8200
|
-
throw new Error('Tried 1,000 k values for sign(), all were invalid');
|
|
8201
|
-
}
|
|
8202
|
-
this.counter += 1;
|
|
8203
|
-
}
|
|
8204
|
-
async reseed(seed = new Uint8Array()) {
|
|
8205
|
-
this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed);
|
|
8206
|
-
this.v = await this.hmac(this.v);
|
|
8207
|
-
if (seed.length === 0)
|
|
8208
|
-
return;
|
|
8209
|
-
this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed);
|
|
8210
|
-
this.v = await this.hmac(this.v);
|
|
8211
|
-
}
|
|
8212
|
-
reseedSync(seed = new Uint8Array()) {
|
|
8213
|
-
this.k = this.hmacSync(this.v, Uint8Array.from([0x00]), seed);
|
|
8214
|
-
this.v = this.hmacSync(this.v);
|
|
8215
|
-
if (seed.length === 0)
|
|
8216
|
-
return;
|
|
8217
|
-
this.k = this.hmacSync(this.v, Uint8Array.from([0x01]), seed);
|
|
8218
|
-
this.v = this.hmacSync(this.v);
|
|
8219
|
-
}
|
|
8220
|
-
async generate() {
|
|
8221
|
-
this.incr();
|
|
8222
|
-
this.v = await this.hmac(this.v);
|
|
8223
|
-
return this.v;
|
|
8224
|
-
}
|
|
8225
|
-
generateSync() {
|
|
8226
|
-
this.incr();
|
|
8227
|
-
this.v = this.hmacSync(this.v);
|
|
8228
|
-
return this.v;
|
|
8229
|
-
}
|
|
8230
|
-
}
|
|
8231
|
-
function isWithinCurveOrder(num) {
|
|
8232
|
-
return _0n < num && num < CURVE.n;
|
|
8233
|
-
}
|
|
8234
|
-
function isValidFieldElement(num) {
|
|
8235
|
-
return _0n < num && num < CURVE.P;
|
|
8236
|
-
}
|
|
8237
|
-
function kmdToSig(kBytes, m, d) {
|
|
8238
|
-
const k = bytesToNumber(kBytes);
|
|
8239
|
-
if (!isWithinCurveOrder(k))
|
|
8240
|
-
return;
|
|
8241
|
-
const { n } = CURVE;
|
|
8242
|
-
const q = Point.BASE.multiply(k);
|
|
8243
|
-
const r = mod(q.x, n);
|
|
8244
|
-
if (r === _0n)
|
|
8245
|
-
return;
|
|
8246
|
-
const s = mod(invert(k, n) * mod(m + d * r, n), n);
|
|
8247
|
-
if (s === _0n)
|
|
8248
|
-
return;
|
|
8249
|
-
const sig = new Signature(r, s);
|
|
8250
|
-
const recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);
|
|
8251
|
-
return { sig, recovery };
|
|
8252
|
-
}
|
|
8253
|
-
function normalizePrivateKey(key) {
|
|
8254
|
-
let num;
|
|
8255
|
-
if (typeof key === 'bigint') {
|
|
8256
|
-
num = key;
|
|
8257
|
-
}
|
|
8258
|
-
else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) {
|
|
8259
|
-
num = BigInt(key);
|
|
8260
|
-
}
|
|
8261
|
-
else if (typeof key === 'string') {
|
|
8262
|
-
if (key.length !== 64)
|
|
8263
|
-
throw new Error('Expected 32 bytes of private key');
|
|
8264
|
-
num = hexToNumber(key);
|
|
8265
|
-
}
|
|
8266
|
-
else if (isUint8a(key)) {
|
|
8267
|
-
if (key.length !== 32)
|
|
8268
|
-
throw new Error('Expected 32 bytes of private key');
|
|
8269
|
-
num = bytesToNumber(key);
|
|
8270
|
-
}
|
|
8271
|
-
else {
|
|
8272
|
-
throw new TypeError('Expected valid private key');
|
|
8273
|
-
}
|
|
8274
|
-
if (!isWithinCurveOrder(num))
|
|
8275
|
-
throw new Error('Expected private key: 0 < key < n');
|
|
8276
|
-
return num;
|
|
8277
|
-
}
|
|
8278
|
-
function normalizeSignature(signature) {
|
|
8279
|
-
if (signature instanceof Signature) {
|
|
8280
|
-
signature.assertValidity();
|
|
8281
|
-
return signature;
|
|
8282
|
-
}
|
|
8283
|
-
try {
|
|
8284
|
-
return Signature.fromDER(signature);
|
|
8285
|
-
}
|
|
8286
|
-
catch (error) {
|
|
8287
|
-
return Signature.fromCompact(signature);
|
|
8288
|
-
}
|
|
8289
|
-
}
|
|
8290
|
-
function getPublicKey(privateKey, isCompressed = false) {
|
|
8291
|
-
return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
|
|
8292
|
-
}
|
|
8293
|
-
function bits2int(bytes) {
|
|
8294
|
-
const slice = bytes.length > 32 ? bytes.slice(0, 32) : bytes;
|
|
8295
|
-
return bytesToNumber(slice);
|
|
8296
|
-
}
|
|
8297
|
-
function bits2octets(bytes) {
|
|
8298
|
-
const z1 = bits2int(bytes);
|
|
8299
|
-
const z2 = mod(z1, CURVE.n);
|
|
8300
|
-
return int2octets(z2 < _0n ? z1 : z2);
|
|
8301
|
-
}
|
|
8302
|
-
function int2octets(num) {
|
|
8303
|
-
if (typeof num !== 'bigint')
|
|
8304
|
-
throw new Error('Expected bigint');
|
|
8305
|
-
const hex = numTo32bStr(num);
|
|
8306
|
-
return hexToBytes(hex);
|
|
8307
|
-
}
|
|
8308
|
-
function initSigArgs(msgHash, privateKey, extraEntropy) {
|
|
8309
|
-
if (msgHash == null)
|
|
8310
|
-
throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
|
|
8311
|
-
const h1 = ensureBytes(msgHash);
|
|
8312
|
-
const d = normalizePrivateKey(privateKey);
|
|
8313
|
-
const seedArgs = [int2octets(d), bits2octets(h1)];
|
|
8314
|
-
if (extraEntropy != null) {
|
|
8315
|
-
if (extraEntropy === true)
|
|
8316
|
-
extraEntropy = utils.randomBytes(32);
|
|
8317
|
-
const e = ensureBytes(extraEntropy);
|
|
8318
|
-
if (e.length !== 32)
|
|
8319
|
-
throw new Error('sign: Expected 32 bytes of extra data');
|
|
8320
|
-
seedArgs.push(e);
|
|
8321
|
-
}
|
|
8322
|
-
const seed = concatBytes(...seedArgs);
|
|
8323
|
-
const m = bits2int(h1);
|
|
8324
|
-
return { seed, m, d };
|
|
8325
|
-
}
|
|
8326
|
-
function finalizeSig(recSig, opts) {
|
|
8327
|
-
let { sig, recovery } = recSig;
|
|
8328
|
-
const { canonical, der, recovered } = Object.assign({ canonical: true, der: true }, opts);
|
|
8329
|
-
if (canonical && sig.hasHighS()) {
|
|
8330
|
-
sig = sig.normalizeS();
|
|
8331
|
-
recovery ^= 1;
|
|
8332
|
-
}
|
|
8333
|
-
const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes();
|
|
8334
|
-
return recovered ? [hashed, recovery] : hashed;
|
|
8335
|
-
}
|
|
8336
|
-
function signSync(msgHash, privKey, opts = {}) {
|
|
8337
|
-
const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);
|
|
8338
|
-
let sig;
|
|
8339
|
-
const drbg = new HmacDrbg();
|
|
8340
|
-
drbg.reseedSync(seed);
|
|
8341
|
-
while (!(sig = kmdToSig(drbg.generateSync(), m, d)))
|
|
8342
|
-
drbg.reseedSync();
|
|
8343
|
-
return finalizeSig(sig, opts);
|
|
8344
|
-
}
|
|
8345
|
-
Point.BASE._setWindowSize(8);
|
|
8346
|
-
const crypto = {
|
|
8347
|
-
node: nodeCrypto,
|
|
8348
|
-
web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined,
|
|
8349
|
-
};
|
|
8350
|
-
const TAGGED_HASH_PREFIXES = {};
|
|
8351
|
-
const utils = {
|
|
8352
|
-
isValidPrivateKey(privateKey) {
|
|
8353
|
-
try {
|
|
8354
|
-
normalizePrivateKey(privateKey);
|
|
8355
|
-
return true;
|
|
8356
|
-
}
|
|
8357
|
-
catch (error) {
|
|
8358
|
-
return false;
|
|
8359
|
-
}
|
|
8360
|
-
},
|
|
8361
|
-
privateAdd: (privateKey, tweak) => {
|
|
8362
|
-
const p = normalizePrivateKey(privateKey);
|
|
8363
|
-
const t = normalizePrivateKey(tweak);
|
|
8364
|
-
return numTo32b(mod(p + t, CURVE.n));
|
|
8365
|
-
},
|
|
8366
|
-
privateNegate: (privateKey) => {
|
|
8367
|
-
const p = normalizePrivateKey(privateKey);
|
|
8368
|
-
return numTo32b(CURVE.n - p);
|
|
8369
|
-
},
|
|
8370
|
-
pointAddScalar: (p, tweak, isCompressed) => {
|
|
8371
|
-
const P = Point.fromHex(p);
|
|
8372
|
-
const t = normalizePrivateKey(tweak);
|
|
8373
|
-
const Q = Point.BASE.multiplyAndAddUnsafe(P, t, _1n);
|
|
8374
|
-
if (!Q)
|
|
8375
|
-
throw new Error('Tweaked point at infinity');
|
|
8376
|
-
return Q.toRawBytes(isCompressed);
|
|
8377
|
-
},
|
|
8378
|
-
pointMultiply: (p, tweak, isCompressed) => {
|
|
8379
|
-
const P = Point.fromHex(p);
|
|
8380
|
-
const t = bytesToNumber(ensureBytes(tweak));
|
|
8381
|
-
return P.multiply(t).toRawBytes(isCompressed);
|
|
8382
|
-
},
|
|
8383
|
-
hashToPrivateKey: (hash) => {
|
|
8384
|
-
hash = ensureBytes(hash);
|
|
8385
|
-
if (hash.length < 40 || hash.length > 1024)
|
|
8386
|
-
throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
|
|
8387
|
-
const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n;
|
|
8388
|
-
return numTo32b(num);
|
|
8389
|
-
},
|
|
8390
|
-
randomBytes: (bytesLength = 32) => {
|
|
8391
|
-
if (crypto.web) {
|
|
8392
|
-
return crypto.web.getRandomValues(new Uint8Array(bytesLength));
|
|
8393
|
-
}
|
|
8394
|
-
else if (crypto.node) {
|
|
8395
|
-
const { randomBytes } = crypto.node;
|
|
8396
|
-
return Uint8Array.from(randomBytes(bytesLength));
|
|
8397
|
-
}
|
|
8398
|
-
else {
|
|
8399
|
-
throw new Error("The environment doesn't have randomBytes function");
|
|
8400
|
-
}
|
|
8401
|
-
},
|
|
8402
|
-
randomPrivateKey: () => {
|
|
8403
|
-
return utils.hashToPrivateKey(utils.randomBytes(40));
|
|
8404
|
-
},
|
|
8405
|
-
bytesToHex,
|
|
8406
|
-
hexToBytes,
|
|
8407
|
-
concatBytes,
|
|
8408
|
-
mod,
|
|
8409
|
-
invert,
|
|
8410
|
-
sha256: async (...messages) => {
|
|
8411
|
-
if (crypto.web) {
|
|
8412
|
-
const buffer = await crypto.web.subtle.digest('SHA-256', concatBytes(...messages));
|
|
8413
|
-
return new Uint8Array(buffer);
|
|
8414
|
-
}
|
|
8415
|
-
else if (crypto.node) {
|
|
8416
|
-
const { createHash } = crypto.node;
|
|
8417
|
-
const hash = createHash('sha256');
|
|
8418
|
-
messages.forEach((m) => hash.update(m));
|
|
8419
|
-
return Uint8Array.from(hash.digest());
|
|
8420
|
-
}
|
|
8421
|
-
else {
|
|
8422
|
-
throw new Error("The environment doesn't have sha256 function");
|
|
8423
|
-
}
|
|
8424
|
-
},
|
|
8425
|
-
hmacSha256: async (key, ...messages) => {
|
|
8426
|
-
if (crypto.web) {
|
|
8427
|
-
const ckey = await crypto.web.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
|
|
8428
|
-
const message = concatBytes(...messages);
|
|
8429
|
-
const buffer = await crypto.web.subtle.sign('HMAC', ckey, message);
|
|
8430
|
-
return new Uint8Array(buffer);
|
|
8431
|
-
}
|
|
8432
|
-
else if (crypto.node) {
|
|
8433
|
-
const { createHmac } = crypto.node;
|
|
8434
|
-
const hash = createHmac('sha256', key);
|
|
8435
|
-
messages.forEach((m) => hash.update(m));
|
|
8436
|
-
return Uint8Array.from(hash.digest());
|
|
8437
|
-
}
|
|
8438
|
-
else {
|
|
8439
|
-
throw new Error("The environment doesn't have hmac-sha256 function");
|
|
8440
|
-
}
|
|
8441
|
-
},
|
|
8442
|
-
sha256Sync: undefined,
|
|
8443
|
-
hmacSha256Sync: undefined,
|
|
8444
|
-
taggedHash: async (tag, ...messages) => {
|
|
8445
|
-
let tagP = TAGGED_HASH_PREFIXES[tag];
|
|
8446
|
-
if (tagP === undefined) {
|
|
8447
|
-
const tagH = await utils.sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));
|
|
8448
|
-
tagP = concatBytes(tagH, tagH);
|
|
8449
|
-
TAGGED_HASH_PREFIXES[tag] = tagP;
|
|
8450
|
-
}
|
|
8451
|
-
return utils.sha256(tagP, ...messages);
|
|
8452
|
-
},
|
|
8453
|
-
taggedHashSync: (tag, ...messages) => {
|
|
8454
|
-
if (typeof utils.sha256Sync !== 'function')
|
|
8455
|
-
throw new Error('utils.sha256Sync is undefined, you need to set it');
|
|
8456
|
-
let tagP = TAGGED_HASH_PREFIXES[tag];
|
|
8457
|
-
if (tagP === undefined) {
|
|
8458
|
-
const tagH = utils.sha256Sync(Uint8Array.from(tag, (c) => c.charCodeAt(0)));
|
|
8459
|
-
tagP = concatBytes(tagH, tagH);
|
|
8460
|
-
TAGGED_HASH_PREFIXES[tag] = tagP;
|
|
8461
|
-
}
|
|
8462
|
-
return utils.sha256Sync(tagP, ...messages);
|
|
8463
|
-
},
|
|
8464
|
-
precompute(windowSize = 8, point = Point.BASE) {
|
|
8465
|
-
const cached = point === Point.BASE ? point : new Point(point.x, point.y);
|
|
8466
|
-
cached._setWindowSize(windowSize);
|
|
8467
|
-
cached.multiply(_3n);
|
|
8468
|
-
return cached;
|
|
8469
|
-
},
|
|
8470
|
-
};
|
|
8471
|
-
|
|
8472
8683
|
// library interoperable with the synchronous APIs in web3.js.
|
|
8473
8684
|
|
|
8474
|
-
utils.hmacSha256Sync = (key, ...msgs) => {
|
|
8685
|
+
secp256k1.utils.hmacSha256Sync = (key, ...msgs) => {
|
|
8475
8686
|
const h = hmac.create(sha256, key);
|
|
8476
8687
|
msgs.forEach(msg => h.update(msg));
|
|
8477
8688
|
return h.digest();
|
|
8478
8689
|
};
|
|
8479
8690
|
|
|
8480
|
-
const ecdsaSign = (msgHash, privKey) => signSync(msgHash, privKey, {
|
|
8691
|
+
const ecdsaSign = (msgHash, privKey) => secp256k1.signSync(msgHash, privKey, {
|
|
8481
8692
|
der: false,
|
|
8482
8693
|
recovered: true
|
|
8483
8694
|
});
|
|
8484
|
-
utils.isValidPrivateKey;
|
|
8485
|
-
const publicKeyCreate = getPublicKey;
|
|
8695
|
+
secp256k1.utils.isValidPrivateKey;
|
|
8696
|
+
const publicKeyCreate = secp256k1.getPublicKey;
|
|
8486
8697
|
|
|
8487
8698
|
const PRIVATE_KEY_BYTES = 32;
|
|
8488
8699
|
const ETHEREUM_ADDRESS_BYTES = 20;
|
|
@@ -8511,7 +8722,7 @@ class Secp256k1Program {
|
|
|
8511
8722
|
assert(publicKey.length === PUBLIC_KEY_BYTES, `Public key must be ${PUBLIC_KEY_BYTES} bytes but received ${publicKey.length} bytes`);
|
|
8512
8723
|
|
|
8513
8724
|
try {
|
|
8514
|
-
return Buffer.from(
|
|
8725
|
+
return Buffer.from(keccak_256(toBuffer(publicKey))).slice(-ETHEREUM_ADDRESS_BYTES);
|
|
8515
8726
|
} catch (error) {
|
|
8516
8727
|
throw new Error(`Error constructing Ethereum address: ${error}`);
|
|
8517
8728
|
}
|
|
@@ -8611,7 +8822,7 @@ class Secp256k1Program {
|
|
|
8611
8822
|
/* isCompressed */
|
|
8612
8823
|
).slice(1); // throw away leading byte
|
|
8613
8824
|
|
|
8614
|
-
const messageHash = Buffer.from(
|
|
8825
|
+
const messageHash = Buffer.from(keccak_256(toBuffer(message)));
|
|
8615
8826
|
const [signature, recoveryId] = ecdsaSign(messageHash, privateKey);
|
|
8616
8827
|
return this.createInstructionWithPublicKey({
|
|
8617
8828
|
publicKey,
|
|
@@ -9505,6 +9716,33 @@ class VoteInstruction {
|
|
|
9505
9716
|
}
|
|
9506
9717
|
};
|
|
9507
9718
|
}
|
|
9719
|
+
/**
|
|
9720
|
+
* Decode an authorize instruction and retrieve the instruction params.
|
|
9721
|
+
*/
|
|
9722
|
+
|
|
9723
|
+
|
|
9724
|
+
static decodeAuthorizeWithSeed(instruction) {
|
|
9725
|
+
this.checkProgramId(instruction.programId);
|
|
9726
|
+
this.checkKeyLength(instruction.keys, 3);
|
|
9727
|
+
const {
|
|
9728
|
+
voteAuthorizeWithSeedArgs: {
|
|
9729
|
+
currentAuthorityDerivedKeyOwnerPubkey,
|
|
9730
|
+
currentAuthorityDerivedKeySeed,
|
|
9731
|
+
newAuthorized,
|
|
9732
|
+
voteAuthorizationType
|
|
9733
|
+
}
|
|
9734
|
+
} = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed, instruction.data);
|
|
9735
|
+
return {
|
|
9736
|
+
currentAuthorityDerivedKeyBasePubkey: instruction.keys[2].pubkey,
|
|
9737
|
+
currentAuthorityDerivedKeyOwnerPubkey: new PublicKey(currentAuthorityDerivedKeyOwnerPubkey),
|
|
9738
|
+
currentAuthorityDerivedKeySeed: currentAuthorityDerivedKeySeed,
|
|
9739
|
+
newAuthorizedPubkey: new PublicKey(newAuthorized),
|
|
9740
|
+
voteAuthorizationType: {
|
|
9741
|
+
index: voteAuthorizationType
|
|
9742
|
+
},
|
|
9743
|
+
votePubkey: instruction.keys[0].pubkey
|
|
9744
|
+
};
|
|
9745
|
+
}
|
|
9508
9746
|
/**
|
|
9509
9747
|
* Decode a withdraw instruction and retrieve the instruction params.
|
|
9510
9748
|
*/
|
|
@@ -9561,6 +9799,10 @@ const VOTE_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
9561
9799
|
Withdraw: {
|
|
9562
9800
|
index: 3,
|
|
9563
9801
|
layout: BufferLayout.struct([BufferLayout.u32('instruction'), BufferLayout.ns64('lamports')])
|
|
9802
|
+
},
|
|
9803
|
+
AuthorizeWithSeed: {
|
|
9804
|
+
index: 10,
|
|
9805
|
+
layout: BufferLayout.struct([BufferLayout.u32('instruction'), voteAuthorizeWithSeedArgs()])
|
|
9564
9806
|
}
|
|
9565
9807
|
});
|
|
9566
9808
|
/**
|
|
@@ -9689,6 +9931,49 @@ class VoteProgram {
|
|
|
9689
9931
|
data
|
|
9690
9932
|
});
|
|
9691
9933
|
}
|
|
9934
|
+
/**
|
|
9935
|
+
* Generate a transaction that authorizes a new Voter or Withdrawer on the Vote account
|
|
9936
|
+
* where the current Voter or Withdrawer authority is a derived key.
|
|
9937
|
+
*/
|
|
9938
|
+
|
|
9939
|
+
|
|
9940
|
+
static authorizeWithSeed(params) {
|
|
9941
|
+
const {
|
|
9942
|
+
currentAuthorityDerivedKeyBasePubkey,
|
|
9943
|
+
currentAuthorityDerivedKeyOwnerPubkey,
|
|
9944
|
+
currentAuthorityDerivedKeySeed,
|
|
9945
|
+
newAuthorizedPubkey,
|
|
9946
|
+
voteAuthorizationType,
|
|
9947
|
+
votePubkey
|
|
9948
|
+
} = params;
|
|
9949
|
+
const type = VOTE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed;
|
|
9950
|
+
const data = encodeData(type, {
|
|
9951
|
+
voteAuthorizeWithSeedArgs: {
|
|
9952
|
+
currentAuthorityDerivedKeyOwnerPubkey: toBuffer(currentAuthorityDerivedKeyOwnerPubkey.toBuffer()),
|
|
9953
|
+
currentAuthorityDerivedKeySeed: currentAuthorityDerivedKeySeed,
|
|
9954
|
+
newAuthorized: toBuffer(newAuthorizedPubkey.toBuffer()),
|
|
9955
|
+
voteAuthorizationType: voteAuthorizationType.index
|
|
9956
|
+
}
|
|
9957
|
+
});
|
|
9958
|
+
const keys = [{
|
|
9959
|
+
pubkey: votePubkey,
|
|
9960
|
+
isSigner: false,
|
|
9961
|
+
isWritable: true
|
|
9962
|
+
}, {
|
|
9963
|
+
pubkey: SYSVAR_CLOCK_PUBKEY,
|
|
9964
|
+
isSigner: false,
|
|
9965
|
+
isWritable: false
|
|
9966
|
+
}, {
|
|
9967
|
+
pubkey: currentAuthorityDerivedKeyBasePubkey,
|
|
9968
|
+
isSigner: true,
|
|
9969
|
+
isWritable: false
|
|
9970
|
+
}];
|
|
9971
|
+
return new Transaction().add({
|
|
9972
|
+
keys,
|
|
9973
|
+
programId: this.programId,
|
|
9974
|
+
data
|
|
9975
|
+
});
|
|
9976
|
+
}
|
|
9692
9977
|
/**
|
|
9693
9978
|
* Generate a transaction to withdraw from a Vote account.
|
|
9694
9979
|
*/
|
|
@@ -9812,7 +10097,7 @@ class ValidatorInfo {
|
|
|
9812
10097
|
if (configKeys[1].isSigner) {
|
|
9813
10098
|
const rawInfo = rustString().decode(Buffer.from(byteArray));
|
|
9814
10099
|
const info = JSON.parse(rawInfo);
|
|
9815
|
-
assert$
|
|
10100
|
+
assert$1(info, InfoString);
|
|
9816
10101
|
return new ValidatorInfo(configKeys[1].publicKey, info);
|
|
9817
10102
|
}
|
|
9818
10103
|
}
|
|
@@ -9984,6 +10269,9 @@ async function sendAndConfirmRawTransaction(connection, rawTransaction, confirma
|
|
|
9984
10269
|
if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'lastValidBlockHeight')) {
|
|
9985
10270
|
confirmationStrategy = confirmationStrategyOrConfirmOptions;
|
|
9986
10271
|
options = maybeConfirmOptions;
|
|
10272
|
+
} else if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'nonceValue')) {
|
|
10273
|
+
confirmationStrategy = confirmationStrategyOrConfirmOptions;
|
|
10274
|
+
options = maybeConfirmOptions;
|
|
9987
10275
|
} else {
|
|
9988
10276
|
options = confirmationStrategyOrConfirmOptions;
|
|
9989
10277
|
}
|
|
@@ -10011,5 +10299,5 @@ async function sendAndConfirmRawTransaction(connection, rawTransaction, confirma
|
|
|
10011
10299
|
|
|
10012
10300
|
const LAMPORTS_PER_SOL = 1000000000;
|
|
10013
10301
|
|
|
10014
|
-
export { Account, AddressLookupTableAccount, AddressLookupTableInstruction, AddressLookupTableProgram, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, COMPUTE_BUDGET_INSTRUCTION_LAYOUTS, ComputeBudgetInstruction, ComputeBudgetProgram, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, LOOKUP_TABLE_INSTRUCTION_LAYOUTS, Loader, Lockup, MAX_SEED_LENGTH, Message, NONCE_ACCOUNT_LENGTH, NonceAccount, PACKET_DATA_SIZE, PUBLIC_KEY_LENGTH, PublicKey, SIGNATURE_LENGTH_IN_BYTES, SOLANA_SCHEMA, STAKE_CONFIG_ID, STAKE_INSTRUCTION_LAYOUTS, SYSTEM_INSTRUCTION_LAYOUTS, SYSVAR_CLOCK_PUBKEY, SYSVAR_EPOCH_SCHEDULE_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_REWARDS_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_SLOT_HISTORY_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, Secp256k1Program, SendTransactionError, SolanaJSONRPCError, SolanaJSONRPCErrorCode, StakeAuthorizationLayout, StakeInstruction, StakeProgram, Struct, SystemInstruction, SystemProgram, Transaction, TransactionExpiredBlockheightExceededError, TransactionExpiredTimeoutError, TransactionInstruction, TransactionStatus, VALIDATOR_INFO_KEY, VOTE_PROGRAM_ID, ValidatorInfo, VoteAccount, VoteAuthorizationLayout, VoteInit, VoteInstruction, VoteProgram, clusterApiUrl, sendAndConfirmRawTransaction, sendAndConfirmTransaction };
|
|
10302
|
+
export { Account, AddressLookupTableAccount, AddressLookupTableInstruction, AddressLookupTableProgram, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, COMPUTE_BUDGET_INSTRUCTION_LAYOUTS, ComputeBudgetInstruction, ComputeBudgetProgram, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, LOOKUP_TABLE_INSTRUCTION_LAYOUTS, Loader, Lockup, MAX_SEED_LENGTH, Message, MessageAccountKeys, MessageV0, NONCE_ACCOUNT_LENGTH, NonceAccount, PACKET_DATA_SIZE, PUBLIC_KEY_LENGTH, PublicKey, SIGNATURE_LENGTH_IN_BYTES, SOLANA_SCHEMA, STAKE_CONFIG_ID, STAKE_INSTRUCTION_LAYOUTS, SYSTEM_INSTRUCTION_LAYOUTS, SYSVAR_CLOCK_PUBKEY, SYSVAR_EPOCH_SCHEDULE_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_REWARDS_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_SLOT_HISTORY_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, Secp256k1Program, SendTransactionError, SolanaJSONRPCError, SolanaJSONRPCErrorCode, StakeAuthorizationLayout, StakeInstruction, StakeProgram, Struct, SystemInstruction, SystemProgram, Transaction, TransactionExpiredBlockheightExceededError, TransactionExpiredNonceInvalidError, TransactionExpiredTimeoutError, TransactionInstruction, TransactionMessage, TransactionStatus, VALIDATOR_INFO_KEY, VERSION_PREFIX_MASK, VOTE_PROGRAM_ID, ValidatorInfo, VersionedMessage, VersionedTransaction, VoteAccount, VoteAuthorizationLayout, VoteInit, VoteInstruction, VoteProgram, clusterApiUrl, sendAndConfirmRawTransaction, sendAndConfirmTransaction };
|
|
10015
10303
|
//# sourceMappingURL=index.browser.esm.js.map
|