var solanaWeb3 = (function (exports) { 'use strict'; var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function getAugmentedNamespace(n) { if (n.__esModule) return n; var f = n.default; if (typeof f == "function") { var a = function a () { if (this instanceof a) { return Reflect.construct(f, arguments, this.constructor); } return f.apply(this, arguments); }; a.prototype = f.prototype; } else a = {}; Object.defineProperty(a, '__esModule', {value: true}); Object.keys(n).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(n, k); Object.defineProperty(a, k, d.get ? d : { enumerable: true, get: function () { return n[k]; } }); }); return a; } var buffer = {}; var base64Js = {}; base64Js.byteLength = byteLength; base64Js.toByteArray = toByteArray; base64Js.fromByteArray = fromByteArray; var lookup = []; var revLookup = []; var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; for (var i$1 = 0, len = code.length; i$1 < len; ++i$1) { lookup[i$1] = code[i$1]; revLookup[code.charCodeAt(i$1)] = i$1; } // Support decoding URL-safe base64 strings, as Node.js does. // See: https://en.wikipedia.org/wiki/Base64#URL_applications revLookup['-'.charCodeAt(0)] = 62; revLookup['_'.charCodeAt(0)] = 63; function getLens (b64) { var len = b64.length; if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // Trim off extra bytes after placeholder bytes are found // See: https://github.com/beatgammit/base64-js/issues/42 var validLen = b64.indexOf('='); if (validLen === -1) validLen = len; var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4); return [validLen, placeHoldersLen] } // base64 is 4/3 + up to two characters of the original data function byteLength (b64) { var lens = getLens(b64); var validLen = lens[0]; var placeHoldersLen = lens[1]; return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function _byteLength (b64, validLen, placeHoldersLen) { return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function toByteArray (b64) { var tmp; var lens = getLens(b64); var validLen = lens[0]; var placeHoldersLen = lens[1]; var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)); var curByte = 0; // if there are placeholders, only get up to the last complete 4 chars var len = placeHoldersLen > 0 ? validLen - 4 : validLen; var i; for (i = 0; i < len; i += 4) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]; arr[curByte++] = (tmp >> 16) & 0xFF; arr[curByte++] = (tmp >> 8) & 0xFF; arr[curByte++] = tmp & 0xFF; } if (placeHoldersLen === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4); arr[curByte++] = tmp & 0xFF; } if (placeHoldersLen === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2); arr[curByte++] = (tmp >> 8) & 0xFF; arr[curByte++] = tmp & 0xFF; } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp; var output = []; for (var i = start; i < end; i += 3) { tmp = ((uint8[i] << 16) & 0xFF0000) + ((uint8[i + 1] << 8) & 0xFF00) + (uint8[i + 2] & 0xFF); output.push(tripletToBase64(tmp)); } return output.join('') } function fromByteArray (uint8) { var tmp; var len = uint8.length; var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes var parts = []; var maxChunkLength = 16383; // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))); } // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { tmp = uint8[len - 1]; parts.push( lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3F] + '==' ); } else if (extraBytes === 2) { tmp = (uint8[len - 2] << 8) + uint8[len - 1]; parts.push( lookup[tmp >> 10] + lookup[(tmp >> 4) & 0x3F] + lookup[(tmp << 2) & 0x3F] + '=' ); } return parts.join('') } var ieee754 = {}; /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ ieee754.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m; var eLen = (nBytes * 8) - mLen - 1; var eMax = (1 << eLen) - 1; var eBias = eMax >> 1; var nBits = -7; var i = isLE ? (nBytes - 1) : 0; var d = isLE ? -1 : 1; var s = buffer[offset + i]; i += d; e = s & ((1 << (-nBits)) - 1); s >>= (-nBits); nBits += eLen; for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} m = e & ((1 << (-nBits)) - 1); e >>= (-nBits); nBits += mLen; for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { e = 1 - eBias; } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { m = m + Math.pow(2, mLen); e = e - eBias; } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) }; ieee754.write = function (buffer, value, offset, isLE, mLen, nBytes) { var e, m, c; var eLen = (nBytes * 8) - mLen - 1; var eMax = (1 << eLen) - 1; var eBias = eMax >> 1; var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0); var i = isLE ? 0 : (nBytes - 1); var d = isLE ? 1 : -1; var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; value = Math.abs(value); if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0; e = eMax; } else { e = Math.floor(Math.log(value) / Math.LN2); if (value * (c = Math.pow(2, -e)) < 1) { e--; c *= 2; } if (e + eBias >= 1) { value += rt / c; } else { value += rt * Math.pow(2, 1 - eBias); } if (value * c >= 2) { e++; c /= 2; } if (e + eBias >= eMax) { m = 0; e = eMax; } else if (e + eBias >= 1) { m = ((value * c) - 1) * Math.pow(2, mLen); e = e + eBias; } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); e = 0; } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} e = (e << mLen) | m; eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128; }; /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ (function (exports) { const base64 = base64Js; const ieee754$1 = ieee754; const customInspectSymbol = (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation : null; exports.Buffer = Buffer; exports.SlowBuffer = SlowBuffer; exports.INSPECT_MAX_BYTES = 50; const K_MAX_LENGTH = 0x7fffffff; exports.kMaxLength = K_MAX_LENGTH; /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Print warning and recommend using `buffer` v4.x which has an Object * implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * We report that the browser does not support typed arrays if the are not subclassable * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support * for __proto__ and has a buggy typed array implementation. */ Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport(); if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && typeof console.error === 'function') { console.error( 'This browser lacks typed array (Uint8Array) support which is required by ' + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' ); } function typedArraySupport () { // Can typed array instances can be augmented? try { const arr = new Uint8Array(1); const proto = { foo: function () { return 42 } }; Object.setPrototypeOf(proto, Uint8Array.prototype); Object.setPrototypeOf(arr, proto); return arr.foo() === 42 } catch (e) { return false } } Object.defineProperty(Buffer.prototype, 'parent', { enumerable: true, get: function () { if (!Buffer.isBuffer(this)) return undefined return this.buffer } }); Object.defineProperty(Buffer.prototype, 'offset', { enumerable: true, get: function () { if (!Buffer.isBuffer(this)) return undefined return this.byteOffset } }); function createBuffer (length) { if (length > K_MAX_LENGTH) { throw new RangeError('The value "' + length + '" is invalid for option "size"') } // Return an augmented `Uint8Array` instance const buf = new Uint8Array(length); Object.setPrototypeOf(buf, Buffer.prototype); return buf } /** * The Buffer constructor returns instances of `Uint8Array` that have their * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of * `Uint8Array`, so the returned instances will have all the node `Buffer` methods * and the `Uint8Array` methods. Square bracket notation works as expected -- it * returns a single octet. * * The `Uint8Array` prototype remains unmodified. */ function Buffer (arg, encodingOrOffset, length) { // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { throw new TypeError( 'The "string" argument must be of type string. Received type number' ) } return allocUnsafe(arg) } return from(arg, encodingOrOffset, length) } Buffer.poolSize = 8192; // not used by this implementation function from (value, encodingOrOffset, length) { if (typeof value === 'string') { return fromString(value, encodingOrOffset) } if (ArrayBuffer.isView(value)) { return fromArrayView(value) } if (value == null) { throw new TypeError( 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + (typeof value) ) } if (isInstance(value, ArrayBuffer) || (value && isInstance(value.buffer, ArrayBuffer))) { return fromArrayBuffer(value, encodingOrOffset, length) } if (typeof SharedArrayBuffer !== 'undefined' && (isInstance(value, SharedArrayBuffer) || (value && isInstance(value.buffer, SharedArrayBuffer)))) { return fromArrayBuffer(value, encodingOrOffset, length) } if (typeof value === 'number') { throw new TypeError( 'The "value" argument must not be of type number. Received type number' ) } const valueOf = value.valueOf && value.valueOf(); if (valueOf != null && valueOf !== value) { return Buffer.from(valueOf, encodingOrOffset, length) } const b = fromObject(value); if (b) return b if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && typeof value[Symbol.toPrimitive] === 'function') { return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length) } throw new TypeError( 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + (typeof value) ) } /** * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError * if value is a number. * Buffer.from(str[, encoding]) * Buffer.from(array) * Buffer.from(buffer) * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { return from(value, encodingOrOffset, length) }; // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: // https://github.com/feross/buffer/pull/148 Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); Object.setPrototypeOf(Buffer, Uint8Array); function assertSize (size) { if (typeof size !== 'number') { throw new TypeError('"size" argument must be of type number') } else if (size < 0) { throw new RangeError('The value "' + size + '" is invalid for option "size"') } } function alloc (size, fill, encoding) { assertSize(size); if (size <= 0) { return createBuffer(size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpreted as a start offset. return typeof encoding === 'string' ? createBuffer(size).fill(fill, encoding) : createBuffer(size).fill(fill) } return createBuffer(size) } /** * Creates a new filled Buffer instance. * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { return alloc(size, fill, encoding) }; function allocUnsafe (size) { assertSize(size); return createBuffer(size < 0 ? 0 : checked(size) | 0) } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(size) }; /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(size) }; function fromString (string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8'; } if (!Buffer.isEncoding(encoding)) { throw new TypeError('Unknown encoding: ' + encoding) } const length = byteLength(string, encoding) | 0; let buf = createBuffer(length); const actual = buf.write(string, encoding); if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will // cause everything after the first invalid character to be ignored. (e.g. // 'abxxcd' will be treated as 'ab') buf = buf.slice(0, actual); } return buf } function fromArrayLike (array) { const length = array.length < 0 ? 0 : checked(array.length) | 0; const buf = createBuffer(length); for (let i = 0; i < length; i += 1) { buf[i] = array[i] & 255; } return buf } function fromArrayView (arrayView) { if (isInstance(arrayView, Uint8Array)) { const copy = new Uint8Array(arrayView); return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength) } return fromArrayLike(arrayView) } function fromArrayBuffer (array, byteOffset, length) { if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('"offset" is outside of buffer bounds') } if (array.byteLength < byteOffset + (length || 0)) { throw new RangeError('"length" is outside of buffer bounds') } let buf; if (byteOffset === undefined && length === undefined) { buf = new Uint8Array(array); } else if (length === undefined) { buf = new Uint8Array(array, byteOffset); } else { buf = new Uint8Array(array, byteOffset, length); } // Return an augmented `Uint8Array` instance Object.setPrototypeOf(buf, Buffer.prototype); return buf } function fromObject (obj) { if (Buffer.isBuffer(obj)) { const len = checked(obj.length) | 0; const buf = createBuffer(len); if (buf.length === 0) { return buf } obj.copy(buf, 0, 0, len); return buf } if (obj.length !== undefined) { if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { return createBuffer(0) } return fromArrayLike(obj) } if (obj.type === 'Buffer' && Array.isArray(obj.data)) { return fromArrayLike(obj.data) } } function checked (length) { // Note: cannot use `length < K_MAX_LENGTH` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= K_MAX_LENGTH) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') } return length | 0 } function SlowBuffer (length) { if (+length != length) { // eslint-disable-line eqeqeq length = 0; } return Buffer.alloc(+length) } Buffer.isBuffer = function isBuffer (b) { return b != null && b._isBuffer === true && b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false }; Buffer.compare = function compare (a, b) { if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength); if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength); if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError( 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' ) } if (a === b) return 0 let x = a.length; let y = b.length; for (let i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i]; y = b[i]; break } } if (x < y) return -1 if (y < x) return 1 return 0 }; Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'latin1': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } }; Buffer.concat = function concat (list, length) { if (!Array.isArray(list)) { throw new TypeError('"list" argument must be an Array of Buffers') } if (list.length === 0) { return Buffer.alloc(0) } let i; if (length === undefined) { length = 0; for (i = 0; i < list.length; ++i) { length += list[i].length; } } const buffer = Buffer.allocUnsafe(length); let pos = 0; for (i = 0; i < list.length; ++i) { let buf = list[i]; if (isInstance(buf, Uint8Array)) { if (pos + buf.length > buffer.length) { if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf); buf.copy(buffer, pos); } else { Uint8Array.prototype.set.call( buffer, buf, pos ); } } else if (!Buffer.isBuffer(buf)) { throw new TypeError('"list" argument must be an Array of Buffers') } else { buf.copy(buffer, pos); } pos += buf.length; } return buffer }; function byteLength (string, encoding) { if (Buffer.isBuffer(string)) { return string.length } if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { return string.byteLength } if (typeof string !== 'string') { throw new TypeError( 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 'Received type ' + typeof string ) } const len = string.length; const mustMatch = (arguments.length > 2 && arguments[2] === true); if (!mustMatch && len === 0) return 0 // Use a for loop to avoid recursion let loweredCase = false; for (;;) { switch (encoding) { case 'ascii': case 'latin1': case 'binary': return len case 'utf8': case 'utf-8': return utf8ToBytes(string).length case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return len * 2 case 'hex': return len >>> 1 case 'base64': return base64ToBytes(string).length default: if (loweredCase) { return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 } encoding = ('' + encoding).toLowerCase(); loweredCase = true; } } } Buffer.byteLength = byteLength; function slowToString (encoding, start, end) { let loweredCase = false; // No need to verify that "this.length <= MAX_UINT32" since it's a read-only // property of a typed array. // This behaves neither like String nor Uint8Array in that we set start/end // to their upper/lower bounds if the value passed is out of range. // undefined is handled specially as per ECMA-262 6th Edition, // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. if (start === undefined || start < 0) { start = 0; } // Return early if start > this.length. Done here to prevent potential uint32 // coercion fail below. if (start > this.length) { return '' } if (end === undefined || end > this.length) { end = this.length; } if (end <= 0) { return '' } // Force coercion to uint32. This will also coerce falsey/NaN values to 0. end >>>= 0; start >>>= 0; if (end <= start) { return '' } if (!encoding) encoding = 'utf8'; while (true) { switch (encoding) { case 'hex': return hexSlice(this, start, end) case 'utf8': case 'utf-8': return utf8Slice(this, start, end) case 'ascii': return asciiSlice(this, start, end) case 'latin1': case 'binary': return latin1Slice(this, start, end) case 'base64': return base64Slice(this, start, end) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return utf16leSlice(this, start, end) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase(); loweredCase = true; } } } // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) // to detect a Buffer instance. It's not possible to use `instanceof Buffer` // reliably in a browserify context because there could be multiple different // copies of the 'buffer' package in use. This method works even for Buffer // instances that were created from another copy of the `buffer` package. // See: https://github.com/feross/buffer/issues/154 Buffer.prototype._isBuffer = true; function swap (b, n, m) { const i = b[n]; b[n] = b[m]; b[m] = i; } Buffer.prototype.swap16 = function swap16 () { const len = this.length; if (len % 2 !== 0) { throw new RangeError('Buffer size must be a multiple of 16-bits') } for (let i = 0; i < len; i += 2) { swap(this, i, i + 1); } return this }; Buffer.prototype.swap32 = function swap32 () { const len = this.length; if (len % 4 !== 0) { throw new RangeError('Buffer size must be a multiple of 32-bits') } for (let i = 0; i < len; i += 4) { swap(this, i, i + 3); swap(this, i + 1, i + 2); } return this }; Buffer.prototype.swap64 = function swap64 () { const len = this.length; if (len % 8 !== 0) { throw new RangeError('Buffer size must be a multiple of 64-bits') } for (let i = 0; i < len; i += 8) { swap(this, i, i + 7); swap(this, i + 1, i + 6); swap(this, i + 2, i + 5); swap(this, i + 3, i + 4); } return this }; Buffer.prototype.toString = function toString () { const length = this.length; if (length === 0) return '' if (arguments.length === 0) return utf8Slice(this, 0, length) return slowToString.apply(this, arguments) }; Buffer.prototype.toLocaleString = Buffer.prototype.toString; Buffer.prototype.equals = function equals (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return true return Buffer.compare(this, b) === 0 }; Buffer.prototype.inspect = function inspect () { let str = ''; const max = exports.INSPECT_MAX_BYTES; str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim(); if (this.length > max) str += ' ... '; return '' }; if (customInspectSymbol) { Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect; } Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { if (isInstance(target, Uint8Array)) { target = Buffer.from(target, target.offset, target.byteLength); } if (!Buffer.isBuffer(target)) { throw new TypeError( 'The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + (typeof target) ) } if (start === undefined) { start = 0; } if (end === undefined) { end = target ? target.length : 0; } if (thisStart === undefined) { thisStart = 0; } if (thisEnd === undefined) { thisEnd = this.length; } if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { throw new RangeError('out of range index') } if (thisStart >= thisEnd && start >= end) { return 0 } if (thisStart >= thisEnd) { return -1 } if (start >= end) { return 1 } start >>>= 0; end >>>= 0; thisStart >>>= 0; thisEnd >>>= 0; if (this === target) return 0 let x = thisEnd - thisStart; let y = end - start; const len = Math.min(x, y); const thisCopy = this.slice(thisStart, thisEnd); const targetCopy = target.slice(start, end); for (let i = 0; i < len; ++i) { if (thisCopy[i] !== targetCopy[i]) { x = thisCopy[i]; y = targetCopy[i]; break } } if (x < y) return -1 if (y < x) return 1 return 0 }; // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, // OR the last index of `val` in `buffer` at offset <= `byteOffset`. // // Arguments: // - buffer - a Buffer to search // - val - a string, Buffer, or number // - byteOffset - an index into `buffer`; will be clamped to an int32 // - encoding - an optional encoding, relevant is val is a string // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { // Empty buffer means no match if (buffer.length === 0) return -1 // Normalize byteOffset if (typeof byteOffset === 'string') { encoding = byteOffset; byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; } else if (byteOffset < -0x80000000) { byteOffset = -0x80000000; } byteOffset = +byteOffset; // Coerce to Number. if (numberIsNaN(byteOffset)) { // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer byteOffset = dir ? 0 : (buffer.length - 1); } // Normalize byteOffset: negative offsets start from the end of the buffer if (byteOffset < 0) byteOffset = buffer.length + byteOffset; if (byteOffset >= buffer.length) { if (dir) return -1 else byteOffset = buffer.length - 1; } else if (byteOffset < 0) { if (dir) byteOffset = 0; else return -1 } // Normalize val if (typeof val === 'string') { val = Buffer.from(val, encoding); } // Finally, search either indexOf (if dir is true) or lastIndexOf if (Buffer.isBuffer(val)) { // Special case: looking for empty string/buffer always fails if (val.length === 0) { return -1 } return arrayIndexOf(buffer, val, byteOffset, encoding, dir) } else if (typeof val === 'number') { val = val & 0xFF; // Search for a byte value [0-255] if (typeof Uint8Array.prototype.indexOf === 'function') { if (dir) { return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) } else { return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) } } return arrayIndexOf(buffer, [val], byteOffset, encoding, dir) } throw new TypeError('val must be string, number or Buffer') } function arrayIndexOf (arr, val, byteOffset, encoding, dir) { let indexSize = 1; let arrLength = arr.length; let valLength = val.length; if (encoding !== undefined) { encoding = String(encoding).toLowerCase(); if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { if (arr.length < 2 || val.length < 2) { return -1 } indexSize = 2; arrLength /= 2; valLength /= 2; byteOffset /= 2; } } function read (buf, i) { if (indexSize === 1) { return buf[i] } else { return buf.readUInt16BE(i * indexSize) } } let i; if (dir) { let foundIndex = -1; for (i = byteOffset; i < arrLength; i++) { if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { if (foundIndex === -1) foundIndex = i; if (i - foundIndex + 1 === valLength) return foundIndex * indexSize } else { if (foundIndex !== -1) i -= i - foundIndex; foundIndex = -1; } } } else { if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; for (i = byteOffset; i >= 0; i--) { let found = true; for (let j = 0; j < valLength; j++) { if (read(arr, i + j) !== read(val, j)) { found = false; break } } if (found) return i } } return -1 } Buffer.prototype.includes = function includes (val, byteOffset, encoding) { return this.indexOf(val, byteOffset, encoding) !== -1 }; Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, true) }; Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, false) }; function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0; const remaining = buf.length - offset; if (!length) { length = remaining; } else { length = Number(length); if (length > remaining) { length = remaining; } } const strLen = string.length; if (length > strLen / 2) { length = strLen / 2; } let i; for (i = 0; i < length; ++i) { const parsed = parseInt(string.substr(i * 2, 2), 16); if (numberIsNaN(parsed)) return i buf[offset + i] = parsed; } return i } function utf8Write (buf, string, offset, length) { return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) } function asciiWrite (buf, string, offset, length) { return blitBuffer(asciiToBytes(string), buf, offset, length) } function base64Write (buf, string, offset, length) { return blitBuffer(base64ToBytes(string), buf, offset, length) } function ucs2Write (buf, string, offset, length) { return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { encoding = 'utf8'; length = this.length; offset = 0; // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { encoding = offset; length = this.length; offset = 0; // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { offset = offset >>> 0; if (isFinite(length)) { length = length >>> 0; if (encoding === undefined) encoding = 'utf8'; } else { encoding = length; length = undefined; } } else { throw new Error( 'Buffer.write(string, encoding, offset[, length]) is no longer supported' ) } const remaining = this.length - offset; if (length === undefined || length > remaining) length = remaining; if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('Attempt to write outside buffer bounds') } if (!encoding) encoding = 'utf8'; let loweredCase = false; for (;;) { switch (encoding) { case 'hex': return hexWrite(this, string, offset, length) case 'utf8': case 'utf-8': return utf8Write(this, string, offset, length) case 'ascii': case 'latin1': case 'binary': return asciiWrite(this, string, offset, length) case 'base64': // Warning: maxLength not taken into account in base64Write return base64Write(this, string, offset, length) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return ucs2Write(this, string, offset, length) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = ('' + encoding).toLowerCase(); loweredCase = true; } } }; Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } }; function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) } else { return base64.fromByteArray(buf.slice(start, end)) } } function utf8Slice (buf, start, end) { end = Math.min(buf.length, end); const res = []; let i = start; while (i < end) { const firstByte = buf[i]; let codePoint = null; let bytesPerSequence = (firstByte > 0xEF) ? 4 : (firstByte > 0xDF) ? 3 : (firstByte > 0xBF) ? 2 : 1; if (i + bytesPerSequence <= end) { let secondByte, thirdByte, fourthByte, tempCodePoint; switch (bytesPerSequence) { case 1: if (firstByte < 0x80) { codePoint = firstByte; } break case 2: secondByte = buf[i + 1]; if ((secondByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F); if (tempCodePoint > 0x7F) { codePoint = tempCodePoint; } } break case 3: secondByte = buf[i + 1]; thirdByte = buf[i + 2]; if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F); if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { codePoint = tempCodePoint; } } break case 4: secondByte = buf[i + 1]; thirdByte = buf[i + 2]; fourthByte = buf[i + 3]; if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F); if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { codePoint = tempCodePoint; } } } } if (codePoint === null) { // we did not generate a valid codePoint so insert a // replacement char (U+FFFD) and advance only 1 byte codePoint = 0xFFFD; bytesPerSequence = 1; } else if (codePoint > 0xFFFF) { // encode to utf16 (surrogate pair dance) codePoint -= 0x10000; res.push(codePoint >>> 10 & 0x3FF | 0xD800); codePoint = 0xDC00 | codePoint & 0x3FF; } res.push(codePoint); i += bytesPerSequence; } return decodeCodePointsArray(res) } // Based on http://stackoverflow.com/a/22747272/680742, the browser with // the lowest limit is Chrome, with 0x10000 args. // We go 1 magnitude less, for safety const MAX_ARGUMENTS_LENGTH = 0x1000; function decodeCodePointsArray (codePoints) { const len = codePoints.length; if (len <= MAX_ARGUMENTS_LENGTH) { return String.fromCharCode.apply(String, codePoints) // avoid extra slice() } // Decode in chunks to avoid "call stack size exceeded". let res = ''; let i = 0; while (i < len) { res += String.fromCharCode.apply( String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) ); } return res } function asciiSlice (buf, start, end) { let ret = ''; end = Math.min(buf.length, end); for (let i = start; i < end; ++i) { ret += String.fromCharCode(buf[i] & 0x7F); } return ret } function latin1Slice (buf, start, end) { let ret = ''; end = Math.min(buf.length, end); for (let i = start; i < end; ++i) { ret += String.fromCharCode(buf[i]); } return ret } function hexSlice (buf, start, end) { const len = buf.length; if (!start || start < 0) start = 0; if (!end || end < 0 || end > len) end = len; let out = ''; for (let i = start; i < end; ++i) { out += hexSliceLookupTable[buf[i]]; } return out } function utf16leSlice (buf, start, end) { const bytes = buf.slice(start, end); let res = ''; // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) for (let i = 0; i < bytes.length - 1; i += 2) { res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)); } return res } Buffer.prototype.slice = function slice (start, end) { const len = this.length; start = ~~start; end = end === undefined ? len : ~~end; if (start < 0) { start += len; if (start < 0) start = 0; } else if (start > len) { start = len; } if (end < 0) { end += len; if (end < 0) end = 0; } else if (end > len) { end = len; } if (end < start) end = start; const newBuf = this.subarray(start, end); // Return an augmented `Uint8Array` instance Object.setPrototypeOf(newBuf, Buffer.prototype); return newBuf }; /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUintLE = Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) checkOffset(offset, byteLength, this.length); let val = this[offset]; let mul = 1; let i = 0; while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul; } return val }; Buffer.prototype.readUintBE = Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) { checkOffset(offset, byteLength, this.length); } let val = this[offset + --byteLength]; let mul = 1; while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul; } return val }; Buffer.prototype.readUint8 = Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 1, this.length); return this[offset] }; Buffer.prototype.readUint16LE = Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 2, this.length); return this[offset] | (this[offset + 1] << 8) }; Buffer.prototype.readUint16BE = Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 2, this.length); return (this[offset] << 8) | this[offset + 1] }; Buffer.prototype.readUint32LE = Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) }; Buffer.prototype.readUint32BE = Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) }; Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) { offset = offset >>> 0; validateNumber(offset, 'offset'); const first = this[offset]; const last = this[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } const lo = first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 24; const hi = this[++offset] + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + last * 2 ** 24; return BigInt(lo) + (BigInt(hi) << BigInt(32)) }); Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) { offset = offset >>> 0; validateNumber(offset, 'offset'); const first = this[offset]; const last = this[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } const hi = first * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + this[++offset]; const lo = this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + last; return (BigInt(hi) << BigInt(32)) + BigInt(lo) }); Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) checkOffset(offset, byteLength, this.length); let val = this[offset]; let mul = 1; let i = 0; while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul; } mul *= 0x80; if (val >= mul) val -= Math.pow(2, 8 * byteLength); return val }; Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) checkOffset(offset, byteLength, this.length); let i = byteLength; let mul = 1; let val = this[offset + --i]; while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul; } mul *= 0x80; if (val >= mul) val -= Math.pow(2, 8 * byteLength); return val }; Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 1, this.length); if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) }; Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 2, this.length); const val = this[offset] | (this[offset + 1] << 8); return (val & 0x8000) ? val | 0xFFFF0000 : val }; Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 2, this.length); const val = this[offset + 1] | (this[offset] << 8); return (val & 0x8000) ? val | 0xFFFF0000 : val }; Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) }; Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) }; Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) { offset = offset >>> 0; validateNumber(offset, 'offset'); const first = this[offset]; const last = this[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } const val = this[offset + 4] + this[offset + 5] * 2 ** 8 + this[offset + 6] * 2 ** 16 + (last << 24); // Overflow return (BigInt(val) << BigInt(32)) + BigInt(first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 24) }); Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) { offset = offset >>> 0; validateNumber(offset, 'offset'); const first = this[offset]; const last = this[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 8); } const val = (first << 24) + // Overflow this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + this[++offset]; return (BigInt(val) << BigInt(32)) + BigInt(this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + last) }); Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return ieee754$1.read(this, offset, true, 23, 4) }; Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 4, this.length); return ieee754$1.read(this, offset, false, 23, 4) }; Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 8, this.length); return ieee754$1.read(this, offset, true, 52, 8) }; Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { offset = offset >>> 0; if (!noAssert) checkOffset(offset, 8, this.length); return ieee754$1.read(this, offset, false, 52, 8) }; function checkInt (buf, value, offset, ext, max, min) { if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') if (offset + ext > buf.length) throw new RangeError('Index out of range') } Buffer.prototype.writeUintLE = Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value; offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) { const maxBytes = Math.pow(2, 8 * byteLength) - 1; checkInt(this, value, offset, byteLength, maxBytes, 0); } let mul = 1; let i = 0; this[offset] = value & 0xFF; while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF; } return offset + byteLength }; Buffer.prototype.writeUintBE = Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value; offset = offset >>> 0; byteLength = byteLength >>> 0; if (!noAssert) { const maxBytes = Math.pow(2, 8 * byteLength) - 1; checkInt(this, value, offset, byteLength, maxBytes, 0); } let i = byteLength - 1; let mul = 1; this[offset + i] = value & 0xFF; while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF; } return offset + byteLength }; Buffer.prototype.writeUint8 = Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); this[offset] = (value & 0xff); return offset + 1 }; Buffer.prototype.writeUint16LE = Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); return offset + 2 }; Buffer.prototype.writeUint16BE = Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); return offset + 2 }; Buffer.prototype.writeUint32LE = Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); this[offset + 3] = (value >>> 24); this[offset + 2] = (value >>> 16); this[offset + 1] = (value >>> 8); this[offset] = (value & 0xff); return offset + 4 }; Buffer.prototype.writeUint32BE = Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); this[offset] = (value >>> 24); this[offset + 1] = (value >>> 16); this[offset + 2] = (value >>> 8); this[offset + 3] = (value & 0xff); return offset + 4 }; function wrtBigUInt64LE (buf, value, offset, min, max) { checkIntBI(value, min, max, buf, offset, 7); let lo = Number(value & BigInt(0xffffffff)); buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; lo = lo >> 8; buf[offset++] = lo; let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)); buf[offset++] = hi; hi = hi >> 8; buf[offset++] = hi; hi = hi >> 8; buf[offset++] = hi; hi = hi >> 8; buf[offset++] = hi; return offset } function wrtBigUInt64BE (buf, value, offset, min, max) { checkIntBI(value, min, max, buf, offset, 7); let lo = Number(value & BigInt(0xffffffff)); buf[offset + 7] = lo; lo = lo >> 8; buf[offset + 6] = lo; lo = lo >> 8; buf[offset + 5] = lo; lo = lo >> 8; buf[offset + 4] = lo; let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)); buf[offset + 3] = hi; hi = hi >> 8; buf[offset + 2] = hi; hi = hi >> 8; buf[offset + 1] = hi; hi = hi >> 8; buf[offset] = hi; return offset + 8 } Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) { return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) }); Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) { return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) }); Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) { const limit = Math.pow(2, (8 * byteLength) - 1); checkInt(this, value, offset, byteLength, limit - 1, -limit); } let i = 0; let mul = 1; let sub = 0; this[offset] = value & 0xFF; while (++i < byteLength && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { sub = 1; } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF; } return offset + byteLength }; Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) { const limit = Math.pow(2, (8 * byteLength) - 1); checkInt(this, value, offset, byteLength, limit - 1, -limit); } let i = byteLength - 1; let mul = 1; let sub = 0; this[offset + i] = value & 0xFF; while (--i >= 0 && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { sub = 1; } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF; } return offset + byteLength }; Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); return offset + 1 }; Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); return offset + 2 }; Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); return offset + 2 }; Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); this[offset + 2] = (value >>> 16); this[offset + 3] = (value >>> 24); return offset + 4 }; Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; this[offset] = (value >>> 24); this[offset + 1] = (value >>> 16); this[offset + 2] = (value >>> 8); this[offset + 3] = (value & 0xff); return offset + 4 }; Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) { return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) }); Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) { return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) }); function checkIEEE754 (buf, value, offset, ext, max, min) { if (offset + ext > buf.length) throw new RangeError('Index out of range') if (offset < 0) throw new RangeError('Index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) { checkIEEE754(buf, value, offset, 4); } ieee754$1.write(buf, value, offset, littleEndian, 23, 4); return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) }; Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) }; function writeDouble (buf, value, offset, littleEndian, noAssert) { value = +value; offset = offset >>> 0; if (!noAssert) { checkIEEE754(buf, value, offset, 8); } ieee754$1.write(buf, value, offset, littleEndian, 52, 8); return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) }; Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') if (!start) start = 0; if (!end && end !== 0) end = this.length; if (targetStart >= target.length) targetStart = target.length; if (!targetStart) targetStart = 0; if (end > 0 && end < start) end = start; // Copy 0 bytes; we're done if (end === start) return 0 if (target.length === 0 || this.length === 0) return 0 // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } if (start < 0 || start >= this.length) throw new RangeError('Index out of range') if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length; if (target.length - targetStart < end - start) { end = target.length - targetStart + start; } const len = end - start; if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { // Use built-in when available, missing from IE11 this.copyWithin(targetStart, start, end); } else { Uint8Array.prototype.set.call( target, this.subarray(start, end), targetStart ); } return len }; // Usage: // buffer.fill(number[, offset[, end]]) // buffer.fill(buffer[, offset[, end]]) // buffer.fill(string[, offset[, end]][, encoding]) Buffer.prototype.fill = function fill (val, start, end, encoding) { // Handle string cases: if (typeof val === 'string') { if (typeof start === 'string') { encoding = start; start = 0; end = this.length; } else if (typeof end === 'string') { encoding = end; end = this.length; } if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string') } if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { throw new TypeError('Unknown encoding: ' + encoding) } if (val.length === 1) { const code = val.charCodeAt(0); if ((encoding === 'utf8' && code < 128) || encoding === 'latin1') { // Fast path: If `val` fits into a single byte, use that numeric value. val = code; } } } else if (typeof val === 'number') { val = val & 255; } else if (typeof val === 'boolean') { val = Number(val); } // Invalid ranges are not set to a default, so can range check early. if (start < 0 || this.length < start || this.length < end) { throw new RangeError('Out of range index') } if (end <= start) { return this } start = start >>> 0; end = end === undefined ? this.length : end >>> 0; if (!val) val = 0; let i; if (typeof val === 'number') { for (i = start; i < end; ++i) { this[i] = val; } } else { const bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding); const len = bytes.length; if (len === 0) { throw new TypeError('The value "' + val + '" is invalid for argument "value"') } for (i = 0; i < end - start; ++i) { this[i + start] = bytes[i % len]; } } return this }; // CUSTOM ERRORS // ============= // Simplified versions from Node, changed for Buffer-only usage const errors = {}; function E (sym, getMessage, Base) { errors[sym] = class NodeError extends Base { constructor () { super(); Object.defineProperty(this, 'message', { value: getMessage.apply(this, arguments), writable: true, configurable: true }); // Add the error code to the name to include it in the stack trace. this.name = `${this.name} [${sym}]`; // Access the stack to generate the error message including the error code // from the name. this.stack; // eslint-disable-line no-unused-expressions // Reset the name to the actual name. delete this.name; } get code () { return sym } set code (value) { Object.defineProperty(this, 'code', { configurable: true, enumerable: true, value, writable: true }); } toString () { return `${this.name} [${sym}]: ${this.message}` } }; } E('ERR_BUFFER_OUT_OF_BOUNDS', function (name) { if (name) { return `${name} is outside of buffer bounds` } return 'Attempt to access memory outside buffer bounds' }, RangeError); E('ERR_INVALID_ARG_TYPE', function (name, actual) { return `The "${name}" argument must be of type number. Received type ${typeof actual}` }, TypeError); E('ERR_OUT_OF_RANGE', function (str, range, input) { let msg = `The value of "${str}" is out of range.`; let received = input; if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { received = addNumericalSeparator(String(input)); } else if (typeof input === 'bigint') { received = String(input); if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) { received = addNumericalSeparator(received); } received += 'n'; } msg += ` It must be ${range}. Received ${received}`; return msg }, RangeError); function addNumericalSeparator (val) { let res = ''; let i = val.length; const start = val[0] === '-' ? 1 : 0; for (; i >= start + 4; i -= 3) { res = `_${val.slice(i - 3, i)}${res}`; } return `${val.slice(0, i)}${res}` } // CHECK FUNCTIONS // =============== function checkBounds (buf, offset, byteLength) { validateNumber(offset, 'offset'); if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { boundsError(offset, buf.length - (byteLength + 1)); } } function checkIntBI (value, min, max, buf, offset, byteLength) { if (value > max || value < min) { const n = typeof min === 'bigint' ? 'n' : ''; let range; if (byteLength > 3) { if (min === 0 || min === BigInt(0)) { range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`; } else { range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + `${(byteLength + 1) * 8 - 1}${n}`; } } else { range = `>= ${min}${n} and <= ${max}${n}`; } throw new errors.ERR_OUT_OF_RANGE('value', range, value) } checkBounds(buf, offset, byteLength); } function validateNumber (value, name) { if (typeof value !== 'number') { throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value) } } function boundsError (value, length, type) { if (Math.floor(value) !== value) { validateNumber(value, type); throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value) } if (length < 0) { throw new errors.ERR_BUFFER_OUT_OF_BOUNDS() } throw new errors.ERR_OUT_OF_RANGE(type || 'offset', `>= ${type ? 1 : 0} and <= ${length}`, value) } // HELPER FUNCTIONS // ================ const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g; function base64clean (str) { // Node takes equal signs as end of the Base64 encoding str = str.split('=')[0]; // Node strips out invalid characters like \n and \t from the string, base64-js does not str = str.trim().replace(INVALID_BASE64_RE, ''); // Node converts strings with length < 2 to '' if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '='; } return str } function utf8ToBytes (string, units) { units = units || Infinity; let codePoint; const length = string.length; let leadSurrogate = null; const bytes = []; for (let i = 0; i < length; ++i) { codePoint = string.charCodeAt(i); // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (!leadSurrogate) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue } // valid lead leadSurrogate = codePoint; continue } // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); leadSurrogate = codePoint; continue } // valid surrogate pair codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); } leadSurrogate = null; // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break bytes.push(codePoint); } else if (codePoint < 0x800) { if ((units -= 2) < 0) break bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ); } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ); } else if (codePoint < 0x110000) { if ((units -= 4) < 0) break bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ); } else { throw new Error('Invalid code point') } } return bytes } function asciiToBytes (str) { const byteArray = []; for (let i = 0; i < str.length; ++i) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF); } return byteArray } function utf16leToBytes (str, units) { let c, hi, lo; const byteArray = []; for (let i = 0; i < str.length; ++i) { if ((units -= 2) < 0) break c = str.charCodeAt(i); hi = c >> 8; lo = c % 256; byteArray.push(lo); byteArray.push(hi); } return byteArray } function base64ToBytes (str) { return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { let i; for (i = 0; i < length; ++i) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i]; } return i } // ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass // the `instanceof` check but they should be treated as of that type. // See: https://github.com/feross/buffer/issues/166 function isInstance (obj, type) { return obj instanceof type || (obj != null && obj.constructor != null && obj.constructor.name != null && obj.constructor.name === type.name) } function numberIsNaN (obj) { // For IE11 support return obj !== obj // eslint-disable-line no-self-compare } // Create lookup table for `toString('hex')` // See: https://github.com/feross/buffer/issues/219 const hexSliceLookupTable = (function () { const alphabet = '0123456789abcdef'; const table = new Array(256); for (let i = 0; i < 16; ++i) { const i16 = i * 16; for (let j = 0; j < 16; ++j) { table[i16 + j] = alphabet[i] + alphabet[j]; } } return table })(); // Return not function with Error if BigInt not supported function defineBigIntMethod (fn) { return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn } function BufferBigIntNotDefined () { throw new Error('BigInt not supported') } } (buffer)); function number$2(n) { if (!Number.isSafeInteger(n) || n < 0) throw new Error(`positive integer expected, not ${n}`); } // copied from utils function isBytes$3(a) { return (a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); } function bytes$1(b, ...lengths) { if (!isBytes$3(b)) throw new Error('Uint8Array expected'); if (lengths.length > 0 && !lengths.includes(b.length)) throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`); } function hash(h) { if (typeof h !== 'function' || typeof h.create !== 'function') throw new Error('Hash should be wrapped by utils.wrapConstructor'); number$2(h.outputLen); number$2(h.blockLen); } function exists$1(instance, checkFinished = true) { if (instance.destroyed) throw new Error('Hash instance has been destroyed'); if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called'); } function output$1(out, instance) { bytes$1(out); const min = instance.outputLen; if (out.length < min) { throw new Error(`digestInto() expects output buffer of length at least ${min}`); } } const crypto$1 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+. // node.js versions earlier than v19 don't declare it in global scope. // For node.js, package.json#exports field mapping rewrites import // from `crypto` to `cryptoNode`, which imports native module. // Makes the utils un-importable in browsers without a bundler. // Once node.js 18 is deprecated (2025-04-30), we can just drop the import. // Cast array to view const createView$1 = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength); // The rotate right (circular right shift) operation for uint32 const rotr$1 = (word, shift) => (word << (32 - shift)) | (word >>> shift); new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44; /** * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) */ function utf8ToBytes$2(str) { if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`); return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 } /** * Normalizes (non-hex) string or Uint8Array to Uint8Array. * Warning: when Uint8Array is passed, it would NOT get copied. * Keep in mind for future mutable operations. */ function toBytes$1(data) { if (typeof data === 'string') data = utf8ToBytes$2(data); bytes$1(data); return data; } /** * Copies several Uint8Arrays into one. */ function concatBytes$1(...arrays) { let sum = 0; for (let i = 0; i < arrays.length; i++) { const a = arrays[i]; bytes$1(a); sum += a.length; } const res = new Uint8Array(sum); for (let i = 0, pad = 0; i < arrays.length; i++) { const a = arrays[i]; res.set(a, pad); pad += a.length; } return res; } // For runtime check if class implements interface let Hash$1 = class Hash { // Safe version that clones internal state clone() { return this._cloneInto(); } }; function wrapConstructor$1(hashCons) { const hashC = (msg) => hashCons().update(toBytes$1(msg)).digest(); const tmp = hashCons(); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = () => hashCons(); return hashC; } /** * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS. */ function randomBytes(bytesLength = 32) { if (crypto$1 && typeof crypto$1.getRandomValues === 'function') { return crypto$1.getRandomValues(new Uint8Array(bytesLength)); } throw new Error('crypto.getRandomValues must be defined'); } // Polyfill for Safari 14 function setBigUint64$1(view, byteOffset, value, isLE) { if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE); const _32n = BigInt(32); const _u32_max = BigInt(0xffffffff); const wh = Number((value >> _32n) & _u32_max); const wl = Number(value & _u32_max); const h = isLE ? 4 : 0; const l = isLE ? 0 : 4; view.setUint32(byteOffset + h, wh, isLE); view.setUint32(byteOffset + l, wl, isLE); } // Choice: a ? b : c const Chi$1 = (a, b, c) => (a & b) ^ (~a & c); // Majority function, true if any two inpust is true const Maj$1 = (a, b, c) => (a & b) ^ (a & c) ^ (b & c); /** * Merkle-Damgard hash construction base class. * Could be used to create MD5, RIPEMD, SHA1, SHA2. */ class HashMD extends Hash$1 { constructor(blockLen, outputLen, padOffset, isLE) { super(); this.blockLen = blockLen; this.outputLen = outputLen; this.padOffset = padOffset; this.isLE = isLE; this.finished = false; this.length = 0; this.pos = 0; this.destroyed = false; this.buffer = new Uint8Array(blockLen); this.view = createView$1(this.buffer); } update(data) { exists$1(this); const { view, buffer, blockLen } = this; data = toBytes$1(data); const len = data.length; for (let pos = 0; pos < len;) { const take = Math.min(blockLen - this.pos, len - pos); // Fast path: we have at least one block in input, cast it to view and process if (take === blockLen) { const dataView = createView$1(data); for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos); continue; } buffer.set(data.subarray(pos, pos + take), this.pos); this.pos += take; pos += take; if (this.pos === blockLen) { this.process(view, 0); this.pos = 0; } } this.length += data.length; this.roundClean(); return this; } digestInto(out) { exists$1(this); output$1(out, this); this.finished = true; // Padding // We can avoid allocation of buffer for padding completely if it // was previously not allocated here. But it won't change performance. const { buffer, view, blockLen, isLE } = this; let { pos } = this; // append the bit '1' to the message buffer[pos++] = 0b10000000; this.buffer.subarray(pos).fill(0); // we have less than padOffset left in buffer, so we cannot put length in // current block, need process it and pad again if (this.padOffset > blockLen - pos) { this.process(view, 0); pos = 0; } // Pad until full block byte with zeros for (let i = pos; i < blockLen; i++) buffer[i] = 0; // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen. // So we just write lowest 64 bits of that value. setBigUint64$1(view, blockLen - 8, BigInt(this.length * 8), isLE); this.process(view, 0); const oview = createView$1(out); const len = this.outputLen; // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit'); const outLen = len / 4; const state = this.get(); if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state'); for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE); } digest() { const { buffer, outputLen } = this; this.digestInto(buffer); const res = buffer.slice(0, outputLen); this.destroy(); return res; } _cloneInto(to) { to || (to = new this.constructor()); to.set(...this.get()); const { blockLen, buffer, length, finished, destroyed, pos } = this; to.length = length; to.pos = pos; to.finished = finished; to.destroyed = destroyed; if (length % blockLen) to.buffer.set(buffer); return to; } } const U32_MASK64$1 = /* @__PURE__ */ BigInt(2 ** 32 - 1); const _32n$1 = /* @__PURE__ */ BigInt(32); // We are not using BigUint64Array, because they are extremely slow as per 2022 function fromBig$1(n, le = false) { if (le) return { h: Number(n & U32_MASK64$1), l: Number((n >> _32n$1) & U32_MASK64$1) }; return { h: Number((n >> _32n$1) & U32_MASK64$1) | 0, l: Number(n & U32_MASK64$1) | 0 }; } function split$1(lst, le = false) { let Ah = new Uint32Array(lst.length); let Al = new Uint32Array(lst.length); for (let i = 0; i < lst.length; i++) { const { h, l } = fromBig$1(lst[i], le); [Ah[i], Al[i]] = [h, l]; } return [Ah, Al]; } const toBig = (h, l) => (BigInt(h >>> 0) << _32n$1) | BigInt(l >>> 0); // for Shift in [0, 32) const shrSH = (h, _l, s) => h >>> s; const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); // Right rotate for Shift in [1, 32) const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); // Right rotate for Shift in (32, 64), NOTE: 32 is special case. const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); // Right rotate for shift===32 (just swaps l&h) const rotr32H = (_h, l) => l; const rotr32L = (h, _l) => h; // Left rotate for Shift in [1, 32) const rotlSH$1 = (h, l, s) => (h << s) | (l >>> (32 - s)); const rotlSL$1 = (h, l, s) => (l << s) | (h >>> (32 - s)); // Left rotate for Shift in (32, 64), NOTE: 32 is special case. const rotlBH$1 = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); const rotlBL$1 = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); // JS uses 32-bit signed integers for bitwise operations which means we cannot // simple take carry out of low bit sum by shift, we need to use division. function add(Ah, Al, Bh, Bl) { const l = (Al >>> 0) + (Bl >>> 0); return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 }; } // Addition with more than 2 elements const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; // prettier-ignore const u64$1 = { fromBig: fromBig$1, split: split$1, toBig, shrSH, shrSL, rotrSH, rotrSL, rotrBH, rotrBL, rotr32H, rotr32L, rotlSH: rotlSH$1, rotlSL: rotlSL$1, rotlBH: rotlBH$1, rotlBL: rotlBL$1, add, add3L, add3H, add4L, add4H, add5H, add5L, }; // Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409): // prettier-ignore const [SHA512_Kh, SHA512_Kl] = /* @__PURE__ */ (() => u64$1.split([ '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc', '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118', '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2', '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694', '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65', '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5', '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4', '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70', '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df', '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b', '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30', '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8', '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8', '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3', '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec', '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b', '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178', '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b', '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c', '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817' ].map(n => BigInt(n))))(); // Temporary buffer, not used to store anything between runs const SHA512_W_H = /* @__PURE__ */ new Uint32Array(80); const SHA512_W_L = /* @__PURE__ */ new Uint32Array(80); class SHA512 extends HashMD { constructor() { super(128, 64, 16, false); // We cannot use array here since array allows indexing by variable which means optimizer/compiler cannot use registers. // Also looks cleaner and easier to verify with spec. // Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): // h -- high 32 bits, l -- low 32 bits this.Ah = 0x6a09e667 | 0; this.Al = 0xf3bcc908 | 0; this.Bh = 0xbb67ae85 | 0; this.Bl = 0x84caa73b | 0; this.Ch = 0x3c6ef372 | 0; this.Cl = 0xfe94f82b | 0; this.Dh = 0xa54ff53a | 0; this.Dl = 0x5f1d36f1 | 0; this.Eh = 0x510e527f | 0; this.El = 0xade682d1 | 0; this.Fh = 0x9b05688c | 0; this.Fl = 0x2b3e6c1f | 0; this.Gh = 0x1f83d9ab | 0; this.Gl = 0xfb41bd6b | 0; this.Hh = 0x5be0cd19 | 0; this.Hl = 0x137e2179 | 0; } // prettier-ignore get() { const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this; return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl]; } // prettier-ignore set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) { this.Ah = Ah | 0; this.Al = Al | 0; this.Bh = Bh | 0; this.Bl = Bl | 0; this.Ch = Ch | 0; this.Cl = Cl | 0; this.Dh = Dh | 0; this.Dl = Dl | 0; this.Eh = Eh | 0; this.El = El | 0; this.Fh = Fh | 0; this.Fl = Fl | 0; this.Gh = Gh | 0; this.Gl = Gl | 0; this.Hh = Hh | 0; this.Hl = Hl | 0; } process(view, offset) { // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array for (let i = 0; i < 16; i++, offset += 4) { SHA512_W_H[i] = view.getUint32(offset); SHA512_W_L[i] = view.getUint32((offset += 4)); } for (let i = 16; i < 80; i++) { // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7) const W15h = SHA512_W_H[i - 15] | 0; const W15l = SHA512_W_L[i - 15] | 0; const s0h = u64$1.rotrSH(W15h, W15l, 1) ^ u64$1.rotrSH(W15h, W15l, 8) ^ u64$1.shrSH(W15h, W15l, 7); const s0l = u64$1.rotrSL(W15h, W15l, 1) ^ u64$1.rotrSL(W15h, W15l, 8) ^ u64$1.shrSL(W15h, W15l, 7); // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6) const W2h = SHA512_W_H[i - 2] | 0; const W2l = SHA512_W_L[i - 2] | 0; const s1h = u64$1.rotrSH(W2h, W2l, 19) ^ u64$1.rotrBH(W2h, W2l, 61) ^ u64$1.shrSH(W2h, W2l, 6); const s1l = u64$1.rotrSL(W2h, W2l, 19) ^ u64$1.rotrBL(W2h, W2l, 61) ^ u64$1.shrSL(W2h, W2l, 6); // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16]; const SUMl = u64$1.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]); const SUMh = u64$1.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]); SHA512_W_H[i] = SUMh | 0; SHA512_W_L[i] = SUMl | 0; } let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this; // Compression function main loop, 80 rounds for (let i = 0; i < 80; i++) { // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41) const sigma1h = u64$1.rotrSH(Eh, El, 14) ^ u64$1.rotrSH(Eh, El, 18) ^ u64$1.rotrBH(Eh, El, 41); const sigma1l = u64$1.rotrSL(Eh, El, 14) ^ u64$1.rotrSL(Eh, El, 18) ^ u64$1.rotrBL(Eh, El, 41); //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0; const CHIh = (Eh & Fh) ^ (~Eh & Gh); const CHIl = (El & Fl) ^ (~El & Gl); // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i] // prettier-ignore const T1ll = u64$1.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]); const T1h = u64$1.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]); const T1l = T1ll | 0; // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39) const sigma0h = u64$1.rotrSH(Ah, Al, 28) ^ u64$1.rotrBH(Ah, Al, 34) ^ u64$1.rotrBH(Ah, Al, 39); const sigma0l = u64$1.rotrSL(Ah, Al, 28) ^ u64$1.rotrBL(Ah, Al, 34) ^ u64$1.rotrBL(Ah, Al, 39); const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch); const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl); Hh = Gh | 0; Hl = Gl | 0; Gh = Fh | 0; Gl = Fl | 0; Fh = Eh | 0; Fl = El | 0; ({ h: Eh, l: El } = u64$1.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0)); Dh = Ch | 0; Dl = Cl | 0; Ch = Bh | 0; Cl = Bl | 0; Bh = Ah | 0; Bl = Al | 0; const All = u64$1.add3L(T1l, sigma0l, MAJl); Ah = u64$1.add3H(All, T1h, sigma0h, MAJh); Al = All | 0; } // Add the compressed chunk to the current hash value ({ h: Ah, l: Al } = u64$1.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0)); ({ h: Bh, l: Bl } = u64$1.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0)); ({ h: Ch, l: Cl } = u64$1.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0)); ({ h: Dh, l: Dl } = u64$1.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0)); ({ h: Eh, l: El } = u64$1.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0)); ({ h: Fh, l: Fl } = u64$1.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0)); ({ h: Gh, l: Gl } = u64$1.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0)); ({ h: Hh, l: Hl } = u64$1.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0)); this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl); } roundClean() { SHA512_W_H.fill(0); SHA512_W_L.fill(0); } destroy() { this.buffer.fill(0); this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } } const sha512 = /* @__PURE__ */ wrapConstructor$1(() => new SHA512()); /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // 100 lines of code in the file are duplicated from noble-hashes (utils). // This is OK: `abstract` directory does not use noble-hashes. // User may opt-in into using different hashing library. This way, noble-hashes // won't be included into their bundle. const _0n$5 = BigInt(0); const _1n$7 = BigInt(1); const _2n$5 = BigInt(2); function isBytes$2(a) { return (a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); } function abytes(item) { if (!isBytes$2(item)) throw new Error('Uint8Array expected'); } // Array where index 0xf0 (240) is mapped to string 'f0' const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')); /** * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' */ function bytesToHex(bytes) { abytes(bytes); // pre-caching improves the speed 6x let hex = ''; for (let i = 0; i < bytes.length; i++) { hex += hexes[bytes[i]]; } return hex; } function numberToHexUnpadded(num) { const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; } function hexToNumber(hex) { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); // Big Endian return BigInt(hex === '' ? '0' : `0x${hex}`); } // We use optimized technique to convert hex string to byte array const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 }; function asciiToBase16(char) { if (char >= asciis._0 && char <= asciis._9) return char - asciis._0; if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10); if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10); return; } /** * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) */ function hexToBytes(hex) { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); const hl = hex.length; const al = hl / 2; if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl); const array = new Uint8Array(al); for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { const n1 = asciiToBase16(hex.charCodeAt(hi)); const n2 = asciiToBase16(hex.charCodeAt(hi + 1)); if (n1 === undefined || n2 === undefined) { const char = hex[hi] + hex[hi + 1]; throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi); } array[ai] = n1 * 16 + n2; } return array; } // BE: Big Endian, LE: Little Endian function bytesToNumberBE(bytes) { return hexToNumber(bytesToHex(bytes)); } function bytesToNumberLE(bytes) { abytes(bytes); return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())); } function numberToBytesBE(n, len) { return hexToBytes(n.toString(16).padStart(len * 2, '0')); } function numberToBytesLE(n, len) { return numberToBytesBE(n, len).reverse(); } // Unpadded, rarely used function numberToVarBytesBE(n) { return hexToBytes(numberToHexUnpadded(n)); } /** * Takes hex string or Uint8Array, converts to Uint8Array. * Validates output length. * Will throw error for other types. * @param title descriptive title for an error e.g. 'private key' * @param hex hex string or Uint8Array * @param expectedLength optional, will compare to result array's length * @returns */ function ensureBytes(title, hex, expectedLength) { let res; if (typeof hex === 'string') { try { res = hexToBytes(hex); } catch (e) { throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`); } } else if (isBytes$2(hex)) { // Uint8Array.from() instead of hash.slice() because node.js Buffer // is instance of Uint8Array, and its slice() creates **mutable** copy res = Uint8Array.from(hex); } else { throw new Error(`${title} must be hex string or Uint8Array`); } const len = res.length; if (typeof expectedLength === 'number' && len !== expectedLength) throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`); return res; } /** * Copies several Uint8Arrays into one. */ function concatBytes(...arrays) { let sum = 0; for (let i = 0; i < arrays.length; i++) { const a = arrays[i]; abytes(a); sum += a.length; } const res = new Uint8Array(sum); for (let i = 0, pad = 0; i < arrays.length; i++) { const a = arrays[i]; res.set(a, pad); pad += a.length; } return res; } // Compares 2 u8a-s in kinda constant time function equalBytes(a, b) { if (a.length !== b.length) return false; let diff = 0; for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i]; return diff === 0; } /** * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) */ function utf8ToBytes$1(str) { if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`); return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 } // Bit operations /** * Calculates amount of bits in a bigint. * Same as `n.toString(2).length` */ function bitLen(n) { let len; for (len = 0; n > _0n$5; n >>= _1n$7, len += 1) ; return len; } /** * Gets single bit at position. * NOTE: first bit position is 0 (same as arrays) * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` */ function bitGet(n, pos) { return (n >> BigInt(pos)) & _1n$7; } /** * Sets single bit at position. */ function bitSet(n, pos, value) { return n | ((value ? _1n$7 : _0n$5) << BigInt(pos)); } /** * Calculate mask for N bits. Not using ** operator with bigints because of old engines. * Same as BigInt(`0b${Array(i).fill('1').join('')}`) */ const bitMask = (n) => (_2n$5 << BigInt(n - 1)) - _1n$7; // DRBG const u8n = (data) => new Uint8Array(data); // creates Uint8Array const u8fr = (arr) => Uint8Array.from(arr); // another shortcut /** * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. * @returns function that will call DRBG until 2nd arg returns something meaningful * @example * const drbg = createHmacDRBG(32, 32, hmac); * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined */ function createHmacDrbg(hashLen, qByteLen, hmacFn) { if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number'); if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number'); if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function'); // Step B, Step C: set hashLen to 8*ceil(hlen/8) let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same let i = 0; // Iterations counter, will throw when over 1000 const reset = () => { v.fill(1); k.fill(0); i = 0; }; const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values) const reseed = (seed = u8n()) => { // HMAC-DRBG reseed() function. Steps D-G k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed) v = h(); // v = hmac(k || v) if (seed.length === 0) return; k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed) v = h(); // v = hmac(k || v) }; const gen = () => { // HMAC-DRBG generate() function if (i++ >= 1000) throw new Error('drbg: tried 1000 values'); let len = 0; const out = []; while (len < qByteLen) { v = h(); const sl = v.slice(); out.push(sl); len += v.length; } return concatBytes(...out); }; const genUntil = (seed, pred) => { reset(); reseed(seed); // Steps D-G let res = undefined; // Step H: grind until k is in [1..n-1] while (!(res = pred(gen()))) reseed(); reset(); return res; }; return genUntil; } // Validating curves and fields const validatorFns = { bigint: (val) => typeof val === 'bigint', function: (val) => typeof val === 'function', boolean: (val) => typeof val === 'boolean', string: (val) => typeof val === 'string', stringOrUint8Array: (val) => typeof val === 'string' || isBytes$2(val), isSafeInteger: (val) => Number.isSafeInteger(val), array: (val) => Array.isArray(val), field: (val, object) => object.Fp.isValid(val), hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen), }; // type Record = { [P in K]: T; } function validateObject(object, validators, optValidators = {}) { const checkField = (fieldName, type, isOptional) => { const checkVal = validatorFns[type]; if (typeof checkVal !== 'function') throw new Error(`Invalid validator "${type}", expected function`); const val = object[fieldName]; if (isOptional && val === undefined) return; if (!checkVal(val, object)) { throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`); } }; for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false); for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true); return object; } // validate type tests // const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; // const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! // // Should fail type-check // const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); // const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); // const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); // const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); var ut = /*#__PURE__*/Object.freeze({ __proto__: null, abytes: abytes, bitGet: bitGet, bitLen: bitLen, bitMask: bitMask, bitSet: bitSet, bytesToHex: bytesToHex, bytesToNumberBE: bytesToNumberBE, bytesToNumberLE: bytesToNumberLE, concatBytes: concatBytes, createHmacDrbg: createHmacDrbg, ensureBytes: ensureBytes, equalBytes: equalBytes, hexToBytes: hexToBytes, hexToNumber: hexToNumber, isBytes: isBytes$2, numberToBytesBE: numberToBytesBE, numberToBytesLE: numberToBytesLE, numberToHexUnpadded: numberToHexUnpadded, numberToVarBytesBE: numberToVarBytesBE, utf8ToBytes: utf8ToBytes$1, validateObject: validateObject }); /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // Utilities for modular arithmetics and finite fields // prettier-ignore const _0n$4 = BigInt(0), _1n$6 = BigInt(1), _2n$4 = BigInt(2), _3n$1 = BigInt(3); // prettier-ignore const _4n = BigInt(4), _5n$1 = BigInt(5), _8n$1 = BigInt(8); // prettier-ignore BigInt(9); BigInt(16); // Calculates a modulo b function mod(a, b) { const result = a % b; return result >= _0n$4 ? result : b + result; } /** * Efficiently raise num to power and do modular division. * Unsafe in some contexts: uses ladder, so can expose bigint bits. * @example * pow(2n, 6n, 11n) // 64n % 11n == 9n */ // TODO: use field version && remove function pow(num, power, modulo) { if (modulo <= _0n$4 || power < _0n$4) throw new Error('Expected power/modulo > 0'); if (modulo === _1n$6) return _0n$4; let res = _1n$6; while (power > _0n$4) { if (power & _1n$6) res = (res * num) % modulo; num = (num * num) % modulo; power >>= _1n$6; } return res; } // Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4) function pow2(x, power, modulo) { let res = x; while (power-- > _0n$4) { res *= res; res %= modulo; } return res; } // Inverses number over modulo function invert(number, modulo) { if (number === _0n$4 || modulo <= _0n$4) { throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); } // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/ // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. let a = mod(number, modulo); let b = modulo; // prettier-ignore let x = _0n$4, u = _1n$6; while (a !== _0n$4) { // JIT applies optimization if those two lines follow each other const q = b / a; const r = b % a; const m = x - u * q; // prettier-ignore b = a, a = r, x = u, u = m; } const gcd = b; if (gcd !== _1n$6) throw new Error('invert: does not exist'); return mod(x, modulo); } /** * Tonelli-Shanks square root search algorithm. * 1. https://eprint.iacr.org/2012/685.pdf (page 12) * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks * Will start an infinite loop if field order P is not prime. * @param P field order * @returns function that takes field Fp (created from P) and number n */ function tonelliShanks(P) { // Legendre constant: used to calculate Legendre symbol (a | p), // which denotes the value of a^((p-1)/2) (mod p). // (a | p) ≡ 1 if a is a square (mod p) // (a | p) ≡ -1 if a is not a square (mod p) // (a | p) ≡ 0 if a ≡ 0 (mod p) const legendreC = (P - _1n$6) / _2n$4; let Q, S, Z; // Step 1: By factoring out powers of 2 from p - 1, // find q and s such that p - 1 = q*(2^s) with q odd for (Q = P - _1n$6, S = 0; Q % _2n$4 === _0n$4; Q /= _2n$4, S++) ; // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq for (Z = _2n$4; Z < P && pow(Z, legendreC, P) !== P - _1n$6; Z++) ; // Fast-path if (S === 1) { const p1div4 = (P + _1n$6) / _4n; return function tonelliFast(Fp, n) { const root = Fp.pow(n, p1div4); if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root'); return root; }; } // Slow-path const Q1div2 = (Q + _1n$6) / _2n$4; return function tonelliSlow(Fp, n) { // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root'); let r = S; // TODO: will fail at Fp2/etc let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b let x = Fp.pow(n, Q1div2); // first guess at the square root let b = Fp.pow(n, Q); // first guess at the fudge factor while (!Fp.eql(b, Fp.ONE)) { if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) // Find m such b^(2^m)==1 let m = 1; for (let t2 = Fp.sqr(b); m < r; m++) { if (Fp.eql(t2, Fp.ONE)) break; t2 = Fp.sqr(t2); // t2 *= t2 } // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow const ge = Fp.pow(g, _1n$6 << BigInt(r - m - 1)); // ge = 2^(r-m-1) g = Fp.sqr(ge); // g = ge * ge x = Fp.mul(x, ge); // x *= ge b = Fp.mul(b, g); // b *= g r = m; } return x; }; } function FpSqrt(P) { // NOTE: different algorithms can give different roots, it is up to user to decide which one they want. // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). // P ≡ 3 (mod 4) // √n = n^((P+1)/4) if (P % _4n === _3n$1) { // Not all roots possible! // const ORDER = // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; // const NUM = 72057594037927816n; const p1div4 = (P + _1n$6) / _4n; return function sqrt3mod4(Fp, n) { const root = Fp.pow(n, p1div4); // Throw if root**2 != n if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root'); return root; }; } // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) if (P % _8n$1 === _5n$1) { const c1 = (P - _5n$1) / _8n$1; return function sqrt5mod8(Fp, n) { const n2 = Fp.mul(n, _2n$4); const v = Fp.pow(n2, c1); const nv = Fp.mul(n, v); const i = Fp.mul(Fp.mul(nv, _2n$4), v); const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)); if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root'); return root; }; } // Other cases: Tonelli-Shanks algorithm return tonelliShanks(P); } // Little-endian check for first LE bit (last BE bit); const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n$6) === _1n$6; // prettier-ignore const FIELD_FIELDS = [ 'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr', 'eql', 'add', 'sub', 'mul', 'pow', 'div', 'addN', 'subN', 'mulN', 'sqrN' ]; function validateField(field) { const initial = { ORDER: 'bigint', MASK: 'bigint', BYTES: 'isSafeInteger', BITS: 'isSafeInteger', }; const opts = FIELD_FIELDS.reduce((map, val) => { map[val] = 'function'; return map; }, initial); return validateObject(field, opts); } // Generic field functions /** * Same as `pow` but for Fp: non-constant-time. * Unsafe in some contexts: uses ladder, so can expose bigint bits. */ function FpPow(f, num, power) { // Should have same speed as pow for bigints // TODO: benchmark! if (power < _0n$4) throw new Error('Expected power > 0'); if (power === _0n$4) return f.ONE; if (power === _1n$6) return num; let p = f.ONE; let d = num; while (power > _0n$4) { if (power & _1n$6) p = f.mul(p, d); d = f.sqr(d); power >>= _1n$6; } return p; } /** * Efficiently invert an array of Field elements. * `inv(0)` will return `undefined` here: make sure to throw an error. */ function FpInvertBatch(f, nums) { const tmp = new Array(nums.length); // Walk from first to last, multiply them by each other MOD p const lastMultiplied = nums.reduce((acc, num, i) => { if (f.is0(num)) return acc; tmp[i] = acc; return f.mul(acc, num); }, f.ONE); // Invert last element const inverted = f.inv(lastMultiplied); // Walk from last to first, multiply them by inverted each other MOD p nums.reduceRight((acc, num, i) => { if (f.is0(num)) return acc; tmp[i] = f.mul(acc, tmp[i]); return f.mul(acc, num); }, inverted); return tmp; } // CURVE.n lengths function nLength(n, nBitLength) { // Bit size, byte size of CURVE.n const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length; const nByteLength = Math.ceil(_nBitLength / 8); return { nBitLength: _nBitLength, nByteLength }; } /** * Initializes a finite field over prime. **Non-primes are not supported.** * Do not init in loop: slow. Very fragile: always run a benchmark on a change. * Major performance optimizations: * * a) denormalized operations like mulN instead of mul * * b) same object shape: never add or remove keys * * c) Object.freeze * @param ORDER prime positive bigint * @param bitLen how many bits the field consumes * @param isLE (def: false) if encoding / decoding should be in little-endian * @param redef optional faster redefinitions of sqrt and other methods */ function Field(ORDER, bitLen, isLE = false, redef = {}) { if (ORDER <= _0n$4) throw new Error(`Expected Field ORDER > 0, got ${ORDER}`); const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen); if (BYTES > 2048) throw new Error('Field lengths over 2048 bytes are not supported'); const sqrtP = FpSqrt(ORDER); const f = Object.freeze({ ORDER, BITS, BYTES, MASK: bitMask(BITS), ZERO: _0n$4, ONE: _1n$6, create: (num) => mod(num, ORDER), isValid: (num) => { if (typeof num !== 'bigint') throw new Error(`Invalid field element: expected bigint, got ${typeof num}`); return _0n$4 <= num && num < ORDER; // 0 is valid element, but it's not invertible }, is0: (num) => num === _0n$4, isOdd: (num) => (num & _1n$6) === _1n$6, neg: (num) => mod(-num, ORDER), eql: (lhs, rhs) => lhs === rhs, sqr: (num) => mod(num * num, ORDER), add: (lhs, rhs) => mod(lhs + rhs, ORDER), sub: (lhs, rhs) => mod(lhs - rhs, ORDER), mul: (lhs, rhs) => mod(lhs * rhs, ORDER), pow: (num, power) => FpPow(f, num, power), div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), // Same as above, but doesn't normalize sqrN: (num) => num * num, addN: (lhs, rhs) => lhs + rhs, subN: (lhs, rhs) => lhs - rhs, mulN: (lhs, rhs) => lhs * rhs, inv: (num) => invert(num, ORDER), sqrt: redef.sqrt || ((n) => sqrtP(f, n)), invertBatch: (lst) => FpInvertBatch(f, lst), // TODO: do we really need constant cmov? // We don't have const-time bigints anyway, so probably will be not very useful cmov: (a, b, c) => (c ? b : a), toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), fromBytes: (bytes) => { if (bytes.length !== BYTES) throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`); return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes); }, }); return Object.freeze(f); } function FpSqrtEven(Fp, elm) { if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`); const root = Fp.sqrt(elm); return Fp.isOdd(root) ? Fp.neg(root) : root; } /** * Returns total number of bytes consumed by the field element. * For example, 32 bytes for usual 256-bit weierstrass curve. * @param fieldOrder number of field elements, usually CURVE.n * @returns byte length of field */ function getFieldBytesLength(fieldOrder) { if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint'); const bitLength = fieldOrder.toString(2).length; return Math.ceil(bitLength / 8); } /** * Returns minimal amount of bytes that can be safely reduced * by field order. * Should be 2^-128 for 128-bit curve such as P256. * @param fieldOrder number of field elements, usually CURVE.n * @returns byte length of target hash */ function getMinHashLength(fieldOrder) { const length = getFieldBytesLength(fieldOrder); return length + Math.ceil(length / 2); } /** * "Constant-time" private key generation utility. * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF * and convert them into private scalar, with the modulo bias being negligible. * Needs at least 48 bytes of input for 32-byte private key. * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 * @param hash hash output from SHA3 or a similar function * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) * @param isLE interpret hash bytes as LE num * @returns valid private scalar */ function mapHashToField(key, fieldOrder, isLE = false) { const len = key.length; const fieldLen = getFieldBytesLength(fieldOrder); const minLen = getMinHashLength(fieldOrder); // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. if (len < 16 || len < minLen || len > 1024) throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`); const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key); // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 const reduced = mod(num, fieldOrder - _1n$6) + _1n$6; return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen); } /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // Abelian group utilities const _0n$3 = BigInt(0); const _1n$5 = BigInt(1); // Elliptic curve multiplication of Point by scalar. Fragile. // Scalars should always be less than curve order: this should be checked inside of a curve itself. // Creates precomputation tables for fast multiplication: // - private scalar is split by fixed size windows of W bits // - every window point is collected from window's table & added to accumulator // - since windows are different, same point inside tables won't be accessed more than once per calc // - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) // - +1 window is neccessary for wNAF // - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication // TODO: Research returning 2d JS array of windows, instead of a single window. This would allow // windows to be in different memory locations function wNAF(c, bits) { const constTimeNegate = (condition, item) => { const neg = item.negate(); return condition ? neg : item; }; const opts = (W) => { const windows = Math.ceil(bits / W) + 1; // +1, because const windowSize = 2 ** (W - 1); // -1 because we skip zero return { windows, windowSize }; }; return { constTimeNegate, // non-const time multiplication ladder unsafeLadder(elm, n) { let p = c.ZERO; let d = elm; while (n > _0n$3) { if (n & _1n$5) p = p.add(d); d = d.double(); n >>= _1n$5; } return p; }, /** * Creates a wNAF precomputation window. Used for caching. * Default window size is set by `utils.precompute()` and is equal to 8. * Number of precomputed points depends on the curve size: * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: * - 𝑊 is the window size * - 𝑛 is the bitlength of the curve order. * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. * @returns precomputed point tables flattened to a single array */ precomputeWindow(elm, W) { const { windows, windowSize } = opts(W); const points = []; let p = elm; let base = p; for (let window = 0; window < windows; window++) { base = p; points.push(base); // =1, because we skip zero for (let i = 1; i < windowSize; i++) { base = base.add(p); points.push(base); } p = base.double(); } return points; }, /** * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. * @param W window size * @param precomputes precomputed tables * @param n scalar (we don't check here, but should be less than curve order) * @returns real and fake (for const-time) points */ wNAF(W, precomputes, n) { // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise // But need to carefully remove other checks before wNAF. ORDER == bits here const { windows, windowSize } = opts(W); let p = c.ZERO; let f = c.BASE; const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc. const maxNumber = 2 ** W; const shiftBy = BigInt(W); for (let window = 0; window < windows; window++) { const offset = window * windowSize; // Extract W bits. let wbits = Number(n & mask); // Shift number by W bits. n >>= shiftBy; // If the bits are bigger than max size, we'll split those. // +224 => 256 - 32 if (wbits > windowSize) { wbits -= maxNumber; n += _1n$5; } // This code was first written with assumption that 'f' and 'p' will never be infinity point: // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, // there is negate now: it is possible that negated element from low value // would be the same as high element, which will create carry into next window. // It's not obvious how this can fail, but still worth investigating later. // Check if we're onto Zero point. // Add random point inside current window to f. const offset1 = offset; const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero const cond1 = window % 2 !== 0; const cond2 = wbits < 0; if (wbits === 0) { // The most important part for const-time getPublicKey f = f.add(constTimeNegate(cond1, precomputes[offset1])); } else { p = p.add(constTimeNegate(cond2, precomputes[offset2])); } } // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() // Even if the variable is still unused, there are some checks which will // throw an exception, so compiler needs to prove they won't happen, which is hard. // At this point there is a way to F be infinity-point even if p is not, // which makes it less const-time: around 1 bigint multiply. return { p, f }; }, wNAFCached(P, precomputesMap, n, transform) { // @ts-ignore const W = P._WINDOW_SIZE || 1; // Calculate precomputes on a first run, reuse them after let comp = precomputesMap.get(P); if (!comp) { comp = this.precomputeWindow(P, W); if (W !== 1) { precomputesMap.set(P, transform(comp)); } } return this.wNAF(W, comp, n); }, }; } function validateBasic(curve) { validateField(curve.Fp); validateObject(curve, { n: 'bigint', h: 'bigint', Gx: 'field', Gy: 'field', }, { nBitLength: 'isSafeInteger', nByteLength: 'isSafeInteger', }); // Set defaults return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve, ...{ p: curve.Fp.ORDER }, }); } /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y² // Be friendly to bad ECMAScript parsers by not using bigint literals // prettier-ignore const _0n$2 = BigInt(0), _1n$4 = BigInt(1), _2n$3 = BigInt(2), _8n = BigInt(8); // verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: const VERIFY_DEFAULT = { zip215: true }; function validateOpts$1(curve) { const opts = validateBasic(curve); validateObject(curve, { hash: 'function', a: 'bigint', d: 'bigint', randomBytes: 'function', }, { adjustScalarBytes: 'function', domain: 'function', uvRatio: 'function', mapToCurve: 'function', }); // Set defaults return Object.freeze({ ...opts }); } // It is not generic twisted curve for now, but ed25519/ed448 generic implementation function twistedEdwards(curveDef) { const CURVE = validateOpts$1(curveDef); const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE; const MASK = _2n$3 << (BigInt(nByteLength * 8) - _1n$4); const modP = Fp.create; // Function overrides // sqrt(u/v) const uvRatio = CURVE.uvRatio || ((u, v) => { try { return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) }; } catch (e) { return { isValid: false, value: _0n$2 }; } }); const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes); // NOOP const domain = CURVE.domain || ((data, ctx, phflag) => { if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported'); return data; }); // NOOP const inBig = (n) => typeof n === 'bigint' && _0n$2 < n; // n in [1..] const inRange = (n, max) => inBig(n) && inBig(max) && n < max; // n in [1..max-1] const in0MaskRange = (n) => n === _0n$2 || inRange(n, MASK); // n in [0..MASK-1] function assertInRange(n, max) { // n in [1..max-1] if (inRange(n, max)) return n; throw new Error(`Expected valid scalar < ${max}, got ${typeof n} ${n}`); } function assertGE0(n) { // n in [0..CURVE_ORDER-1] return n === _0n$2 ? n : assertInRange(n, CURVE_ORDER); // GE = prime subgroup, not full group } const pointPrecomputes = new Map(); function isPoint(other) { if (!(other instanceof Point)) throw new Error('ExtendedPoint expected'); } // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates class Point { constructor(ex, ey, ez, et) { this.ex = ex; this.ey = ey; this.ez = ez; this.et = et; if (!in0MaskRange(ex)) throw new Error('x required'); if (!in0MaskRange(ey)) throw new Error('y required'); if (!in0MaskRange(ez)) throw new Error('z required'); if (!in0MaskRange(et)) throw new Error('t required'); } get x() { return this.toAffine().x; } get y() { return this.toAffine().y; } static fromAffine(p) { if (p instanceof Point) throw new Error('extended point not allowed'); const { x, y } = p || {}; if (!in0MaskRange(x) || !in0MaskRange(y)) throw new Error('invalid affine point'); return new Point(x, y, _1n$4, modP(x * y)); } static normalizeZ(points) { const toInv = Fp.invertBatch(points.map((p) => p.ez)); return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine); } // "Private method", don't use it directly _setWindowSize(windowSize) { this._WINDOW_SIZE = windowSize; pointPrecomputes.delete(this); } // Not required for fromHex(), which always creates valid points. // Could be useful for fromAffine(). assertValidity() { const { a, d } = CURVE; if (this.is0()) throw new Error('bad point: ZERO'); // TODO: optimize, with vars below? // Equation in affine coordinates: ax² + y² = 1 + dx²y² // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² const { ex: X, ey: Y, ez: Z, et: T } = this; const X2 = modP(X * X); // X² const Y2 = modP(Y * Y); // Y² const Z2 = modP(Z * Z); // Z² const Z4 = modP(Z2 * Z2); // Z⁴ const aX2 = modP(X2 * a); // aX² const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z² const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y² if (left !== right) throw new Error('bad point: equation left != right (1)'); // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T const XY = modP(X * Y); const ZT = modP(Z * T); if (XY !== ZT) throw new Error('bad point: equation left != right (2)'); } // Compare one point to another. equals(other) { isPoint(other); const { ex: X1, ey: Y1, ez: Z1 } = this; const { ex: X2, ey: Y2, ez: Z2 } = other; const X1Z2 = modP(X1 * Z2); const X2Z1 = modP(X2 * Z1); const Y1Z2 = modP(Y1 * Z2); const Y2Z1 = modP(Y2 * Z1); return X1Z2 === X2Z1 && Y1Z2 === Y2Z1; } is0() { return this.equals(Point.ZERO); } negate() { // Flips point sign to a negative one (-x, y in affine coords) return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)); } // Fast algo for doubling Extended Point. // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd // Cost: 4M + 4S + 1*a + 6add + 1*2. double() { const { a } = CURVE; const { ex: X1, ey: Y1, ez: Z1 } = this; const A = modP(X1 * X1); // A = X12 const B = modP(Y1 * Y1); // B = Y12 const C = modP(_2n$3 * modP(Z1 * Z1)); // C = 2*Z12 const D = modP(a * A); // D = a*A const x1y1 = X1 + Y1; const E = modP(modP(x1y1 * x1y1) - A - B); // E = (X1+Y1)2-A-B const G = D + B; // G = D+B const F = G - C; // F = G-C const H = D - B; // H = D-B const X3 = modP(E * F); // X3 = E*F const Y3 = modP(G * H); // Y3 = G*H const T3 = modP(E * H); // T3 = E*H const Z3 = modP(F * G); // Z3 = F*G return new Point(X3, Y3, Z3, T3); } // Fast algo for adding 2 Extended Points. // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd // Cost: 9M + 1*a + 1*d + 7add. add(other) { isPoint(other); const { a, d } = CURVE; const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this; const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other; // Faster algo for adding 2 Extended Points when curve's a=-1. // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 // Cost: 8M + 8add + 2*2. // Note: It does not check whether the `other` point is valid. if (a === BigInt(-1)) { const A = modP((Y1 - X1) * (Y2 + X2)); const B = modP((Y1 + X1) * (Y2 - X2)); const F = modP(B - A); if (F === _0n$2) return this.double(); // Same point. Tests say it doesn't affect timing const C = modP(Z1 * _2n$3 * T2); const D = modP(T1 * _2n$3 * Z2); const E = D + C; const G = B + A; const H = D - C; const X3 = modP(E * F); const Y3 = modP(G * H); const T3 = modP(E * H); const Z3 = modP(F * G); return new Point(X3, Y3, Z3, T3); } const A = modP(X1 * X2); // A = X1*X2 const B = modP(Y1 * Y2); // B = Y1*Y2 const C = modP(T1 * d * T2); // C = T1*d*T2 const D = modP(Z1 * Z2); // D = Z1*Z2 const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B const F = D - C; // F = D-C const G = D + C; // G = D+C const H = modP(B - a * A); // H = B-a*A const X3 = modP(E * F); // X3 = E*F const Y3 = modP(G * H); // Y3 = G*H const T3 = modP(E * H); // T3 = E*H const Z3 = modP(F * G); // Z3 = F*G return new Point(X3, Y3, Z3, T3); } subtract(other) { return this.add(other.negate()); } wNAF(n) { return wnaf.wNAFCached(this, pointPrecomputes, n, Point.normalizeZ); } // Constant-time multiplication. multiply(scalar) { const { p, f } = this.wNAF(assertInRange(scalar, CURVE_ORDER)); return Point.normalizeZ([p, f])[0]; } // Non-constant-time multiplication. Uses double-and-add algorithm. // It's faster, but should only be used when you don't care about // an exposed private key e.g. sig verification. // Does NOT allow scalars higher than CURVE.n. multiplyUnsafe(scalar) { let n = assertGE0(scalar); // 0 <= scalar < CURVE.n if (n === _0n$2) return I; if (this.equals(I) || n === _1n$4) return this; if (this.equals(G)) return this.wNAF(n).p; return wnaf.unsafeLadder(this, n); } // Checks if point is of small order. // If you add something to small order point, you will have "dirty" // point with torsion component. // Multiplies point by cofactor and checks if the result is 0. isSmallOrder() { return this.multiplyUnsafe(cofactor).is0(); } // Multiplies point by curve order and checks if the result is 0. // Returns `false` is the point is dirty. isTorsionFree() { return wnaf.unsafeLadder(this, CURVE_ORDER).is0(); } // Converts Extended point to default (x, y) coordinates. // Can accept precomputed Z^-1 - for example, from invertBatch. toAffine(iz) { const { ex: x, ey: y, ez: z } = this; const is0 = this.is0(); if (iz == null) iz = is0 ? _8n : Fp.inv(z); // 8 was chosen arbitrarily const ax = modP(x * iz); const ay = modP(y * iz); const zz = modP(z * iz); if (is0) return { x: _0n$2, y: _1n$4 }; if (zz !== _1n$4) throw new Error('invZ was invalid'); return { x: ax, y: ay }; } clearCofactor() { const { h: cofactor } = CURVE; if (cofactor === _1n$4) return this; return this.multiplyUnsafe(cofactor); } // Converts hash string or Uint8Array to Point. // Uses algo from RFC8032 5.1.3. static fromHex(hex, zip215 = false) { const { d, a } = CURVE; const len = Fp.BYTES; hex = ensureBytes('pointHex', hex, len); // copy hex to a new array const normed = hex.slice(); // copy again, we'll manipulate it const lastByte = hex[len - 1]; // select last byte normed[len - 1] = lastByte & ~0x80; // clear last bit const y = bytesToNumberLE(normed); if (y === _0n$2) ; else { // RFC8032 prohibits >= p, but ZIP215 doesn't if (zip215) assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519) else assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519) } // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) const y2 = modP(y * y); // denominator is always non-0 mod p. const u = modP(y2 - _1n$4); // u = y² - 1 const v = modP(d * y2 - a); // v = d y² + 1. let { isValid, value: x } = uvRatio(u, v); // √(u/v) if (!isValid) throw new Error('Point.fromHex: invalid y coordinate'); const isXOdd = (x & _1n$4) === _1n$4; // There are 2 square roots. Use x_0 bit to select proper const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit if (!zip215 && x === _0n$2 && isLastByteOdd) // if x=0 and x_0 = 1, fail throw new Error('Point.fromHex: x=0 and x_0=1'); if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x return Point.fromAffine({ x, y }); } static fromPrivateKey(privKey) { return getExtendedPublicKey(privKey).point; } toRawBytes() { const { x, y } = this.toAffine(); const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y) bytes[bytes.length - 1] |= x & _1n$4 ? 0x80 : 0; // when compressing, it's enough to store y return bytes; // and use the last byte to encode sign of x } toHex() { return bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string. } } Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n$4, modP(CURVE.Gx * CURVE.Gy)); Point.ZERO = new Point(_0n$2, _1n$4, _1n$4, _0n$2); // 0, 1, 1, 0 const { BASE: G, ZERO: I } = Point; const wnaf = wNAF(Point, nByteLength * 8); function modN(a) { return mod(a, CURVE_ORDER); } // Little-endian SHA512 with modulo n function modN_LE(hash) { return modN(bytesToNumberLE(hash)); } /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ function getExtendedPublicKey(key) { const len = nByteLength; key = ensureBytes('private key', key, len); // Hash private key with curve's hash function to produce uniformingly random input // Check byte lengths: ensure(64, h(ensure(32, key))) const hashed = ensureBytes('hashed private key', cHash(key), 2 * len); const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6) const scalar = modN_LE(head); // The actual private scalar const point = G.multiply(scalar); // Point on Edwards curve aka public key const pointBytes = point.toRawBytes(); // Uint8Array representation return { head, prefix, scalar, point, pointBytes }; } // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared function getPublicKey(privKey) { return getExtendedPublicKey(privKey).pointBytes; } // int('LE', SHA512(dom2(F, C) || msgs)) mod N function hashDomainToScalar(context = new Uint8Array(), ...msgs) { const msg = concatBytes(...msgs); return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))); } /** Signs message with privateKey. RFC8032 5.1.6 */ function sign(msg, privKey, options = {}) { msg = ensureBytes('message', msg); if (prehash) msg = prehash(msg); // for ed25519ph etc. const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey); const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M) const R = G.multiply(r).toRawBytes(); // R = rG const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M) const s = modN(r + k * scalar); // S = (r + k * s) mod L assertGE0(s); // 0 <= s < l const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES)); return ensureBytes('result', res, nByteLength * 2); // 64-byte signature } const verifyOpts = VERIFY_DEFAULT; function verify(sig, msg, publicKey, options = verifyOpts) { const { context, zip215 } = options; const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked. msg = ensureBytes('message', msg); if (prehash) msg = prehash(msg); // for ed25519ph, etc const s = bytesToNumberLE(sig.slice(len, 2 * len)); // zip215: true is good for consensus-critical apps and allows points < 2^256 // zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p let A, R, SB; try { A = Point.fromHex(publicKey, zip215); R = Point.fromHex(sig.slice(0, len), zip215); SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside } catch (error) { return false; } if (!zip215 && A.isSmallOrder()) return false; const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg); const RkA = R.add(A.multiplyUnsafe(k)); // [8][S]B = [8]R + [8][k]A' return RkA.subtract(SB).clearCofactor().equals(Point.ZERO); } G._setWindowSize(8); // Enable precomputes. Slows down first publicKey computation by 20ms. const utils = { getExtendedPublicKey, // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. randomPrivateKey: () => randomBytes(Fp.BYTES), /** * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT * values. This slows down first getPublicKey() by milliseconds (see Speed section), * but allows to speed-up subsequent getPublicKey() calls up to 20x. * @param windowSize 2, 4, 8, 16 */ precompute(windowSize = 8, point = Point.BASE) { point._setWindowSize(windowSize); point.multiply(BigInt(3)); return point; }, }; return { CURVE, getPublicKey, sign, verify, ExtendedPoint: Point, utils, }; } /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ /** * ed25519 Twisted Edwards curve with following addons: * - X25519 ECDH * - Ristretto cofactor elimination * - Elligator hash-to-group / point indistinguishability */ const ED25519_P = BigInt('57896044618658097711785492504343953926634992332820282019728792003956564819949'); // √(-1) aka √(a) aka 2^((p-1)/4) const ED25519_SQRT_M1 = BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752'); // prettier-ignore BigInt(0); const _1n$3 = BigInt(1), _2n$2 = BigInt(2), _5n = BigInt(5); // prettier-ignore const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80); function ed25519_pow_2_252_3(x) { const P = ED25519_P; const x2 = (x * x) % P; const b2 = (x2 * x) % P; // x^3, 11 const b4 = (pow2(b2, _2n$2, P) * b2) % P; // x^15, 1111 const b5 = (pow2(b4, _1n$3, P) * x) % P; // x^31 const b10 = (pow2(b5, _5n, P) * b5) % P; const b20 = (pow2(b10, _10n, P) * b10) % P; const b40 = (pow2(b20, _20n, P) * b20) % P; const b80 = (pow2(b40, _40n, P) * b40) % P; const b160 = (pow2(b80, _80n, P) * b80) % P; const b240 = (pow2(b160, _80n, P) * b80) % P; const b250 = (pow2(b240, _10n, P) * b10) % P; const pow_p_5_8 = (pow2(b250, _2n$2, P) * x) % P; // ^ To pow to (p+3)/8, multiply it by x. return { pow_p_5_8, b2 }; } function adjustScalarBytes(bytes) { // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, // set the three least significant bits of the first byte bytes[0] &= 248; // 0b1111_1000 // and the most significant bit of the last to zero, bytes[31] &= 127; // 0b0111_1111 // set the second most significant bit of the last byte to 1 bytes[31] |= 64; // 0b0100_0000 return bytes; } // sqrt(u/v) function uvRatio(u, v) { const P = ED25519_P; const v3 = mod(v * v * v, P); // v³ const v7 = mod(v3 * v3 * v, P); // v⁷ // (p+3)/8 and (p-5)/8 const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8; let x = mod(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8 const vx2 = mod(v * x * x, P); // vx² const root1 = x; // First root candidate const root2 = mod(x * ED25519_SQRT_M1, P); // Second root candidate const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root const useRoot2 = vx2 === mod(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4) const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1) if (useRoot1) x = root1; if (useRoot2 || noRoot) x = root2; // We return root2 anyway, for const-time if (isNegativeLE(x, P)) x = mod(-x, P); return { isValid: useRoot1 || useRoot2, value: x }; } const Fp$1 = Field(ED25519_P, undefined, true); const ed25519Defaults = { // Param: a a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster // d is equal to -121665/121666 over finite field. // Negative number is P - number, and division is invert(number, P) d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n Fp: Fp$1, // Subgroup order: how many points curve has // 2n**252n + 27742317777372353535851937790883648493n; n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), // Cofactor h: BigInt(8), // Base point (x, y) aka generator point Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), hash: sha512, randomBytes, adjustScalarBytes, // dom2 // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. // Constant-time, u/√v uvRatio, }; const ed25519 = /* @__PURE__ */ twistedEdwards(ed25519Defaults); function ed25519_domain(data, ctx, phflag) { if (ctx.length > 255) throw new Error('Context is too big'); return concatBytes$1(utf8ToBytes$2('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data); } /* @__PURE__ */ twistedEdwards({ ...ed25519Defaults, domain: ed25519_domain, }); /* @__PURE__ */ twistedEdwards({ ...ed25519Defaults, domain: ed25519_domain, prehash: sha512, }); // Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) // NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since // SageMath returns different root first and everything falls apart const ELL2_C1 = (Fp$1.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic Fp$1.pow(_2n$2, ELL2_C1); // 2. c2 = 2^c1 Fp$1.sqrt(Fp$1.neg(Fp$1.ONE)); // 3. c3 = sqrt(-1) (Fp$1.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic BigInt(486662); FpSqrtEven(Fp$1, Fp$1.neg(BigInt(486664))); // sgn0(c1) MUST equal 0 // √(ad - 1) BigInt('25063068953384623474111414158702152701244531502492656460079210482610430750235'); // 1 / √(a-d) BigInt('54469307008909316920995813868745141605393597292927456921205312896311721017578'); // 1-d² BigInt('1159843021668779879193775521855586647937357759715417654439879720876111806838'); // (d-1)² BigInt('40440834346308536858101042469323190826248399146238708352240133220865137265952'); BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); /** * A 64 byte secret key, the first 32 bytes of which is the * private scalar and the last 32 bytes is the public key. * Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ */ /** * Ed25519 Keypair */ const generatePrivateKey = ed25519.utils.randomPrivateKey; const generateKeypair = () => { const privateScalar = ed25519.utils.randomPrivateKey(); const publicKey = getPublicKey(privateScalar); const secretKey = new Uint8Array(64); secretKey.set(privateScalar); secretKey.set(publicKey, 32); return { publicKey, secretKey }; }; const getPublicKey = ed25519.getPublicKey; function isOnCurve(publicKey) { try { ed25519.ExtendedPoint.fromHex(publicKey); return true; } catch { return false; } } const sign = (message, secretKey) => ed25519.sign(message, secretKey.slice(0, 32)); const verify = ed25519.verify; const toBuffer = arr => { if (buffer.Buffer.isBuffer(arr)) { return arr; } else if (arr instanceof Uint8Array) { return buffer.Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength); } else { return buffer.Buffer.from(arr); } }; var bn = {exports: {}}; var _nodeResolve_empty = {}; var _nodeResolve_empty$1 = /*#__PURE__*/Object.freeze({ __proto__: null, default: _nodeResolve_empty }); var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(_nodeResolve_empty$1); bn.exports; (function (module) { (function (module, exports) { // Utils function assert (val, msg) { if (!val) throw new Error(msg || 'Assertion failed'); } // Could use `inherits` module, but don't want to move from single file // architecture yet. function inherits (ctor, superCtor) { ctor.super_ = superCtor; var TempCtor = function () {}; TempCtor.prototype = superCtor.prototype; ctor.prototype = new TempCtor(); ctor.prototype.constructor = ctor; } // BN function BN (number, base, endian) { if (BN.isBN(number)) { return number; } this.negative = 0; this.words = null; this.length = 0; // Reduction context this.red = null; if (number !== null) { if (base === 'le' || base === 'be') { endian = base; base = 10; } this._init(number || 0, base || 10, endian || 'be'); } } if (typeof module === 'object') { module.exports = BN; } else { exports.BN = BN; } BN.BN = BN; BN.wordSize = 26; var Buffer; try { if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') { Buffer = window.Buffer; } else { Buffer = require$$0$1.Buffer; } } catch (e) { } BN.isBN = function isBN (num) { if (num instanceof BN) { return true; } return num !== null && typeof num === 'object' && num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); }; BN.max = function max (left, right) { if (left.cmp(right) > 0) return left; return right; }; BN.min = function min (left, right) { if (left.cmp(right) < 0) return left; return right; }; BN.prototype._init = function init (number, base, endian) { if (typeof number === 'number') { return this._initNumber(number, base, endian); } if (typeof number === 'object') { return this._initArray(number, base, endian); } if (base === 'hex') { base = 16; } assert(base === (base | 0) && base >= 2 && base <= 36); number = number.toString().replace(/\s+/g, ''); var start = 0; if (number[0] === '-') { start++; this.negative = 1; } if (start < number.length) { if (base === 16) { this._parseHex(number, start, endian); } else { this._parseBase(number, base, start); if (endian === 'le') { this._initArray(this.toArray(), base, endian); } } } }; BN.prototype._initNumber = function _initNumber (number, base, endian) { if (number < 0) { this.negative = 1; number = -number; } if (number < 0x4000000) { this.words = [number & 0x3ffffff]; this.length = 1; } else if (number < 0x10000000000000) { this.words = [ number & 0x3ffffff, (number / 0x4000000) & 0x3ffffff ]; this.length = 2; } else { assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) this.words = [ number & 0x3ffffff, (number / 0x4000000) & 0x3ffffff, 1 ]; this.length = 3; } if (endian !== 'le') return; // Reverse the bytes this._initArray(this.toArray(), base, endian); }; BN.prototype._initArray = function _initArray (number, base, endian) { // Perhaps a Uint8Array assert(typeof number.length === 'number'); if (number.length <= 0) { this.words = [0]; this.length = 1; return this; } this.length = Math.ceil(number.length / 3); this.words = new Array(this.length); for (var i = 0; i < this.length; i++) { this.words[i] = 0; } var j, w; var off = 0; if (endian === 'be') { for (i = number.length - 1, j = 0; i >= 0; i -= 3) { w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; off += 24; if (off >= 26) { off -= 26; j++; } } } else if (endian === 'le') { for (i = 0, j = 0; i < number.length; i += 3) { w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; off += 24; if (off >= 26) { off -= 26; j++; } } } return this._strip(); }; function parseHex4Bits (string, index) { var c = string.charCodeAt(index); // '0' - '9' if (c >= 48 && c <= 57) { return c - 48; // 'A' - 'F' } else if (c >= 65 && c <= 70) { return c - 55; // 'a' - 'f' } else if (c >= 97 && c <= 102) { return c - 87; } else { assert(false, 'Invalid character in ' + string); } } function parseHexByte (string, lowerBound, index) { var r = parseHex4Bits(string, index); if (index - 1 >= lowerBound) { r |= parseHex4Bits(string, index - 1) << 4; } return r; } BN.prototype._parseHex = function _parseHex (number, start, endian) { // Create possibly bigger array to ensure that it fits the number this.length = Math.ceil((number.length - start) / 6); this.words = new Array(this.length); for (var i = 0; i < this.length; i++) { this.words[i] = 0; } // 24-bits chunks var off = 0; var j = 0; var w; if (endian === 'be') { for (i = number.length - 1; i >= start; i -= 2) { w = parseHexByte(number, start, i) << off; this.words[j] |= w & 0x3ffffff; if (off >= 18) { off -= 18; j += 1; this.words[j] |= w >>> 26; } else { off += 8; } } } else { var parseLength = number.length - start; for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) { w = parseHexByte(number, start, i) << off; this.words[j] |= w & 0x3ffffff; if (off >= 18) { off -= 18; j += 1; this.words[j] |= w >>> 26; } else { off += 8; } } } this._strip(); }; function parseBase (str, start, end, mul) { var r = 0; var b = 0; var len = Math.min(str.length, end); for (var i = start; i < len; i++) { var c = str.charCodeAt(i) - 48; r *= mul; // 'a' if (c >= 49) { b = c - 49 + 0xa; // 'A' } else if (c >= 17) { b = c - 17 + 0xa; // '0' - '9' } else { b = c; } assert(c >= 0 && b < mul, 'Invalid character'); r += b; } return r; } BN.prototype._parseBase = function _parseBase (number, base, start) { // Initialize as zero this.words = [0]; this.length = 1; // Find length of limb in base for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { limbLen++; } limbLen--; limbPow = (limbPow / base) | 0; var total = number.length - start; var mod = total % limbLen; var end = Math.min(total, total - mod) + start; var word = 0; for (var i = start; i < end; i += limbLen) { word = parseBase(number, i, i + limbLen, base); this.imuln(limbPow); if (this.words[0] + word < 0x4000000) { this.words[0] += word; } else { this._iaddn(word); } } if (mod !== 0) { var pow = 1; word = parseBase(number, i, number.length, base); for (i = 0; i < mod; i++) { pow *= base; } this.imuln(pow); if (this.words[0] + word < 0x4000000) { this.words[0] += word; } else { this._iaddn(word); } } this._strip(); }; BN.prototype.copy = function copy (dest) { dest.words = new Array(this.length); for (var i = 0; i < this.length; i++) { dest.words[i] = this.words[i]; } dest.length = this.length; dest.negative = this.negative; dest.red = this.red; }; function move (dest, src) { dest.words = src.words; dest.length = src.length; dest.negative = src.negative; dest.red = src.red; } BN.prototype._move = function _move (dest) { move(dest, this); }; BN.prototype.clone = function clone () { var r = new BN(null); this.copy(r); return r; }; BN.prototype._expand = function _expand (size) { while (this.length < size) { this.words[this.length++] = 0; } return this; }; // Remove leading `0` from `this` BN.prototype._strip = function strip () { while (this.length > 1 && this.words[this.length - 1] === 0) { this.length--; } return this._normSign(); }; BN.prototype._normSign = function _normSign () { // -0 = 0 if (this.length === 1 && this.words[0] === 0) { this.negative = 0; } return this; }; // Check Symbol.for because not everywhere where Symbol defined // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') { try { BN.prototype[Symbol.for('nodejs.util.inspect.custom')] = inspect; } catch (e) { BN.prototype.inspect = inspect; } } else { BN.prototype.inspect = inspect; } function inspect () { return (this.red ? ''; } /* var zeros = []; var groupSizes = []; var groupBases = []; var s = ''; var i = -1; while (++i < BN.wordSize) { zeros[i] = s; s += '0'; } groupSizes[0] = 0; groupSizes[1] = 0; groupBases[0] = 0; groupBases[1] = 0; var base = 2 - 1; while (++base < 36 + 1) { var groupSize = 0; var groupBase = 1; while (groupBase < (1 << BN.wordSize) / base) { groupBase *= base; groupSize += 1; } groupSizes[base] = groupSize; groupBases[base] = groupBase; } */ var zeros = [ '', '0', '00', '000', '0000', '00000', '000000', '0000000', '00000000', '000000000', '0000000000', '00000000000', '000000000000', '0000000000000', '00000000000000', '000000000000000', '0000000000000000', '00000000000000000', '000000000000000000', '0000000000000000000', '00000000000000000000', '000000000000000000000', '0000000000000000000000', '00000000000000000000000', '000000000000000000000000', '0000000000000000000000000' ]; var groupSizes = [ 0, 0, 25, 16, 12, 11, 10, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ]; var groupBases = [ 0, 0, 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 ]; BN.prototype.toString = function toString (base, padding) { base = base || 10; padding = padding | 0 || 1; var out; if (base === 16 || base === 'hex') { out = ''; var off = 0; var carry = 0; for (var i = 0; i < this.length; i++) { var w = this.words[i]; var word = (((w << off) | carry) & 0xffffff).toString(16); carry = (w >>> (24 - off)) & 0xffffff; off += 2; if (off >= 26) { off -= 26; i--; } if (carry !== 0 || i !== this.length - 1) { out = zeros[6 - word.length] + word + out; } else { out = word + out; } } if (carry !== 0) { out = carry.toString(16) + out; } while (out.length % padding !== 0) { out = '0' + out; } if (this.negative !== 0) { out = '-' + out; } return out; } if (base === (base | 0) && base >= 2 && base <= 36) { // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); var groupSize = groupSizes[base]; // var groupBase = Math.pow(base, groupSize); var groupBase = groupBases[base]; out = ''; var c = this.clone(); c.negative = 0; while (!c.isZero()) { var r = c.modrn(groupBase).toString(base); c = c.idivn(groupBase); if (!c.isZero()) { out = zeros[groupSize - r.length] + r + out; } else { out = r + out; } } if (this.isZero()) { out = '0' + out; } while (out.length % padding !== 0) { out = '0' + out; } if (this.negative !== 0) { out = '-' + out; } return out; } assert(false, 'Base should be between 2 and 36'); }; BN.prototype.toNumber = function toNumber () { var ret = this.words[0]; if (this.length === 2) { ret += this.words[1] * 0x4000000; } else if (this.length === 3 && this.words[2] === 0x01) { // NOTE: at this stage it is known that the top bit is set ret += 0x10000000000000 + (this.words[1] * 0x4000000); } else if (this.length > 2) { assert(false, 'Number can only safely store up to 53 bits'); } return (this.negative !== 0) ? -ret : ret; }; BN.prototype.toJSON = function toJSON () { return this.toString(16, 2); }; if (Buffer) { BN.prototype.toBuffer = function toBuffer (endian, length) { return this.toArrayLike(Buffer, endian, length); }; } BN.prototype.toArray = function toArray (endian, length) { return this.toArrayLike(Array, endian, length); }; var allocate = function allocate (ArrayType, size) { if (ArrayType.allocUnsafe) { return ArrayType.allocUnsafe(size); } return new ArrayType(size); }; BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { this._strip(); var byteLength = this.byteLength(); var reqLength = length || Math.max(1, byteLength); assert(byteLength <= reqLength, 'byte array longer than desired length'); assert(reqLength > 0, 'Requested array length <= 0'); var res = allocate(ArrayType, reqLength); var postfix = endian === 'le' ? 'LE' : 'BE'; this['_toArrayLike' + postfix](res, byteLength); return res; }; BN.prototype._toArrayLikeLE = function _toArrayLikeLE (res, byteLength) { var position = 0; var carry = 0; for (var i = 0, shift = 0; i < this.length; i++) { var word = (this.words[i] << shift) | carry; res[position++] = word & 0xff; if (position < res.length) { res[position++] = (word >> 8) & 0xff; } if (position < res.length) { res[position++] = (word >> 16) & 0xff; } if (shift === 6) { if (position < res.length) { res[position++] = (word >> 24) & 0xff; } carry = 0; shift = 0; } else { carry = word >>> 24; shift += 2; } } if (position < res.length) { res[position++] = carry; while (position < res.length) { res[position++] = 0; } } }; BN.prototype._toArrayLikeBE = function _toArrayLikeBE (res, byteLength) { var position = res.length - 1; var carry = 0; for (var i = 0, shift = 0; i < this.length; i++) { var word = (this.words[i] << shift) | carry; res[position--] = word & 0xff; if (position >= 0) { res[position--] = (word >> 8) & 0xff; } if (position >= 0) { res[position--] = (word >> 16) & 0xff; } if (shift === 6) { if (position >= 0) { res[position--] = (word >> 24) & 0xff; } carry = 0; shift = 0; } else { carry = word >>> 24; shift += 2; } } if (position >= 0) { res[position--] = carry; while (position >= 0) { res[position--] = 0; } } }; if (Math.clz32) { BN.prototype._countBits = function _countBits (w) { return 32 - Math.clz32(w); }; } else { BN.prototype._countBits = function _countBits (w) { var t = w; var r = 0; if (t >= 0x1000) { r += 13; t >>>= 13; } if (t >= 0x40) { r += 7; t >>>= 7; } if (t >= 0x8) { r += 4; t >>>= 4; } if (t >= 0x02) { r += 2; t >>>= 2; } return r + t; }; } BN.prototype._zeroBits = function _zeroBits (w) { // Short-cut if (w === 0) return 26; var t = w; var r = 0; if ((t & 0x1fff) === 0) { r += 13; t >>>= 13; } if ((t & 0x7f) === 0) { r += 7; t >>>= 7; } if ((t & 0xf) === 0) { r += 4; t >>>= 4; } if ((t & 0x3) === 0) { r += 2; t >>>= 2; } if ((t & 0x1) === 0) { r++; } return r; }; // Return number of used bits in a BN BN.prototype.bitLength = function bitLength () { var w = this.words[this.length - 1]; var hi = this._countBits(w); return (this.length - 1) * 26 + hi; }; function toBitArray (num) { var w = new Array(num.bitLength()); for (var bit = 0; bit < w.length; bit++) { var off = (bit / 26) | 0; var wbit = bit % 26; w[bit] = (num.words[off] >>> wbit) & 0x01; } return w; } // Number of trailing zero bits BN.prototype.zeroBits = function zeroBits () { if (this.isZero()) return 0; var r = 0; for (var i = 0; i < this.length; i++) { var b = this._zeroBits(this.words[i]); r += b; if (b !== 26) break; } return r; }; BN.prototype.byteLength = function byteLength () { return Math.ceil(this.bitLength() / 8); }; BN.prototype.toTwos = function toTwos (width) { if (this.negative !== 0) { return this.abs().inotn(width).iaddn(1); } return this.clone(); }; BN.prototype.fromTwos = function fromTwos (width) { if (this.testn(width - 1)) { return this.notn(width).iaddn(1).ineg(); } return this.clone(); }; BN.prototype.isNeg = function isNeg () { return this.negative !== 0; }; // Return negative clone of `this` BN.prototype.neg = function neg () { return this.clone().ineg(); }; BN.prototype.ineg = function ineg () { if (!this.isZero()) { this.negative ^= 1; } return this; }; // Or `num` with `this` in-place BN.prototype.iuor = function iuor (num) { while (this.length < num.length) { this.words[this.length++] = 0; } for (var i = 0; i < num.length; i++) { this.words[i] = this.words[i] | num.words[i]; } return this._strip(); }; BN.prototype.ior = function ior (num) { assert((this.negative | num.negative) === 0); return this.iuor(num); }; // Or `num` with `this` BN.prototype.or = function or (num) { if (this.length > num.length) return this.clone().ior(num); return num.clone().ior(this); }; BN.prototype.uor = function uor (num) { if (this.length > num.length) return this.clone().iuor(num); return num.clone().iuor(this); }; // And `num` with `this` in-place BN.prototype.iuand = function iuand (num) { // b = min-length(num, this) var b; if (this.length > num.length) { b = num; } else { b = this; } for (var i = 0; i < b.length; i++) { this.words[i] = this.words[i] & num.words[i]; } this.length = b.length; return this._strip(); }; BN.prototype.iand = function iand (num) { assert((this.negative | num.negative) === 0); return this.iuand(num); }; // And `num` with `this` BN.prototype.and = function and (num) { if (this.length > num.length) return this.clone().iand(num); return num.clone().iand(this); }; BN.prototype.uand = function uand (num) { if (this.length > num.length) return this.clone().iuand(num); return num.clone().iuand(this); }; // Xor `num` with `this` in-place BN.prototype.iuxor = function iuxor (num) { // a.length > b.length var a; var b; if (this.length > num.length) { a = this; b = num; } else { a = num; b = this; } for (var i = 0; i < b.length; i++) { this.words[i] = a.words[i] ^ b.words[i]; } if (this !== a) { for (; i < a.length; i++) { this.words[i] = a.words[i]; } } this.length = a.length; return this._strip(); }; BN.prototype.ixor = function ixor (num) { assert((this.negative | num.negative) === 0); return this.iuxor(num); }; // Xor `num` with `this` BN.prototype.xor = function xor (num) { if (this.length > num.length) return this.clone().ixor(num); return num.clone().ixor(this); }; BN.prototype.uxor = function uxor (num) { if (this.length > num.length) return this.clone().iuxor(num); return num.clone().iuxor(this); }; // Not ``this`` with ``width`` bitwidth BN.prototype.inotn = function inotn (width) { assert(typeof width === 'number' && width >= 0); var bytesNeeded = Math.ceil(width / 26) | 0; var bitsLeft = width % 26; // Extend the buffer with leading zeroes this._expand(bytesNeeded); if (bitsLeft > 0) { bytesNeeded--; } // Handle complete words for (var i = 0; i < bytesNeeded; i++) { this.words[i] = ~this.words[i] & 0x3ffffff; } // Handle the residue if (bitsLeft > 0) { this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); } // And remove leading zeroes return this._strip(); }; BN.prototype.notn = function notn (width) { return this.clone().inotn(width); }; // Set `bit` of `this` BN.prototype.setn = function setn (bit, val) { assert(typeof bit === 'number' && bit >= 0); var off = (bit / 26) | 0; var wbit = bit % 26; this._expand(off + 1); if (val) { this.words[off] = this.words[off] | (1 << wbit); } else { this.words[off] = this.words[off] & ~(1 << wbit); } return this._strip(); }; // Add `num` to `this` in-place BN.prototype.iadd = function iadd (num) { var r; // negative + positive if (this.negative !== 0 && num.negative === 0) { this.negative = 0; r = this.isub(num); this.negative ^= 1; return this._normSign(); // positive + negative } else if (this.negative === 0 && num.negative !== 0) { num.negative = 0; r = this.isub(num); num.negative = 1; return r._normSign(); } // a.length > b.length var a, b; if (this.length > num.length) { a = this; b = num; } else { a = num; b = this; } var carry = 0; for (var i = 0; i < b.length; i++) { r = (a.words[i] | 0) + (b.words[i] | 0) + carry; this.words[i] = r & 0x3ffffff; carry = r >>> 26; } for (; carry !== 0 && i < a.length; i++) { r = (a.words[i] | 0) + carry; this.words[i] = r & 0x3ffffff; carry = r >>> 26; } this.length = a.length; if (carry !== 0) { this.words[this.length] = carry; this.length++; // Copy the rest of the words } else if (a !== this) { for (; i < a.length; i++) { this.words[i] = a.words[i]; } } return this; }; // Add `num` to `this` BN.prototype.add = function add (num) { var res; if (num.negative !== 0 && this.negative === 0) { num.negative = 0; res = this.sub(num); num.negative ^= 1; return res; } else if (num.negative === 0 && this.negative !== 0) { this.negative = 0; res = num.sub(this); this.negative = 1; return res; } if (this.length > num.length) return this.clone().iadd(num); return num.clone().iadd(this); }; // Subtract `num` from `this` in-place BN.prototype.isub = function isub (num) { // this - (-num) = this + num if (num.negative !== 0) { num.negative = 0; var r = this.iadd(num); num.negative = 1; return r._normSign(); // -this - num = -(this + num) } else if (this.negative !== 0) { this.negative = 0; this.iadd(num); this.negative = 1; return this._normSign(); } // At this point both numbers are positive var cmp = this.cmp(num); // Optimization - zeroify if (cmp === 0) { this.negative = 0; this.length = 1; this.words[0] = 0; return this; } // a > b var a, b; if (cmp > 0) { a = this; b = num; } else { a = num; b = this; } var carry = 0; for (var i = 0; i < b.length; i++) { r = (a.words[i] | 0) - (b.words[i] | 0) + carry; carry = r >> 26; this.words[i] = r & 0x3ffffff; } for (; carry !== 0 && i < a.length; i++) { r = (a.words[i] | 0) + carry; carry = r >> 26; this.words[i] = r & 0x3ffffff; } // Copy rest of the words if (carry === 0 && i < a.length && a !== this) { for (; i < a.length; i++) { this.words[i] = a.words[i]; } } this.length = Math.max(this.length, i); if (a !== this) { this.negative = 1; } return this._strip(); }; // Subtract `num` from `this` BN.prototype.sub = function sub (num) { return this.clone().isub(num); }; function smallMulTo (self, num, out) { out.negative = num.negative ^ self.negative; var len = (self.length + num.length) | 0; out.length = len; len = (len - 1) | 0; // Peel one iteration (compiler can't do it, because of code complexity) var a = self.words[0] | 0; var b = num.words[0] | 0; var r = a * b; var lo = r & 0x3ffffff; var carry = (r / 0x4000000) | 0; out.words[0] = lo; for (var k = 1; k < len; k++) { // Sum all words with the same `i + j = k` and accumulate `ncarry`, // note that ncarry could be >= 0x3ffffff var ncarry = carry >>> 26; var rword = carry & 0x3ffffff; var maxJ = Math.min(k, num.length - 1); for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { var i = (k - j) | 0; a = self.words[i] | 0; b = num.words[j] | 0; r = a * b + rword; ncarry += (r / 0x4000000) | 0; rword = r & 0x3ffffff; } out.words[k] = rword | 0; carry = ncarry | 0; } if (carry !== 0) { out.words[k] = carry | 0; } else { out.length--; } return out._strip(); } // TODO(indutny): it may be reasonable to omit it for users who don't need // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit // multiplication (like elliptic secp256k1). var comb10MulTo = function comb10MulTo (self, num, out) { var a = self.words; var b = num.words; var o = out.words; var c = 0; var lo; var mid; var hi; var a0 = a[0] | 0; var al0 = a0 & 0x1fff; var ah0 = a0 >>> 13; var a1 = a[1] | 0; var al1 = a1 & 0x1fff; var ah1 = a1 >>> 13; var a2 = a[2] | 0; var al2 = a2 & 0x1fff; var ah2 = a2 >>> 13; var a3 = a[3] | 0; var al3 = a3 & 0x1fff; var ah3 = a3 >>> 13; var a4 = a[4] | 0; var al4 = a4 & 0x1fff; var ah4 = a4 >>> 13; var a5 = a[5] | 0; var al5 = a5 & 0x1fff; var ah5 = a5 >>> 13; var a6 = a[6] | 0; var al6 = a6 & 0x1fff; var ah6 = a6 >>> 13; var a7 = a[7] | 0; var al7 = a7 & 0x1fff; var ah7 = a7 >>> 13; var a8 = a[8] | 0; var al8 = a8 & 0x1fff; var ah8 = a8 >>> 13; var a9 = a[9] | 0; var al9 = a9 & 0x1fff; var ah9 = a9 >>> 13; var b0 = b[0] | 0; var bl0 = b0 & 0x1fff; var bh0 = b0 >>> 13; var b1 = b[1] | 0; var bl1 = b1 & 0x1fff; var bh1 = b1 >>> 13; var b2 = b[2] | 0; var bl2 = b2 & 0x1fff; var bh2 = b2 >>> 13; var b3 = b[3] | 0; var bl3 = b3 & 0x1fff; var bh3 = b3 >>> 13; var b4 = b[4] | 0; var bl4 = b4 & 0x1fff; var bh4 = b4 >>> 13; var b5 = b[5] | 0; var bl5 = b5 & 0x1fff; var bh5 = b5 >>> 13; var b6 = b[6] | 0; var bl6 = b6 & 0x1fff; var bh6 = b6 >>> 13; var b7 = b[7] | 0; var bl7 = b7 & 0x1fff; var bh7 = b7 >>> 13; var b8 = b[8] | 0; var bl8 = b8 & 0x1fff; var bh8 = b8 >>> 13; var b9 = b[9] | 0; var bl9 = b9 & 0x1fff; var bh9 = b9 >>> 13; out.negative = self.negative ^ num.negative; out.length = 19; /* k = 0 */ lo = Math.imul(al0, bl0); mid = Math.imul(al0, bh0); mid = (mid + Math.imul(ah0, bl0)) | 0; hi = Math.imul(ah0, bh0); var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; w0 &= 0x3ffffff; /* k = 1 */ lo = Math.imul(al1, bl0); mid = Math.imul(al1, bh0); mid = (mid + Math.imul(ah1, bl0)) | 0; hi = Math.imul(ah1, bh0); lo = (lo + Math.imul(al0, bl1)) | 0; mid = (mid + Math.imul(al0, bh1)) | 0; mid = (mid + Math.imul(ah0, bl1)) | 0; hi = (hi + Math.imul(ah0, bh1)) | 0; var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; w1 &= 0x3ffffff; /* k = 2 */ lo = Math.imul(al2, bl0); mid = Math.imul(al2, bh0); mid = (mid + Math.imul(ah2, bl0)) | 0; hi = Math.imul(ah2, bh0); lo = (lo + Math.imul(al1, bl1)) | 0; mid = (mid + Math.imul(al1, bh1)) | 0; mid = (mid + Math.imul(ah1, bl1)) | 0; hi = (hi + Math.imul(ah1, bh1)) | 0; lo = (lo + Math.imul(al0, bl2)) | 0; mid = (mid + Math.imul(al0, bh2)) | 0; mid = (mid + Math.imul(ah0, bl2)) | 0; hi = (hi + Math.imul(ah0, bh2)) | 0; var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; w2 &= 0x3ffffff; /* k = 3 */ lo = Math.imul(al3, bl0); mid = Math.imul(al3, bh0); mid = (mid + Math.imul(ah3, bl0)) | 0; hi = Math.imul(ah3, bh0); lo = (lo + Math.imul(al2, bl1)) | 0; mid = (mid + Math.imul(al2, bh1)) | 0; mid = (mid + Math.imul(ah2, bl1)) | 0; hi = (hi + Math.imul(ah2, bh1)) | 0; lo = (lo + Math.imul(al1, bl2)) | 0; mid = (mid + Math.imul(al1, bh2)) | 0; mid = (mid + Math.imul(ah1, bl2)) | 0; hi = (hi + Math.imul(ah1, bh2)) | 0; lo = (lo + Math.imul(al0, bl3)) | 0; mid = (mid + Math.imul(al0, bh3)) | 0; mid = (mid + Math.imul(ah0, bl3)) | 0; hi = (hi + Math.imul(ah0, bh3)) | 0; var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; w3 &= 0x3ffffff; /* k = 4 */ lo = Math.imul(al4, bl0); mid = Math.imul(al4, bh0); mid = (mid + Math.imul(ah4, bl0)) | 0; hi = Math.imul(ah4, bh0); lo = (lo + Math.imul(al3, bl1)) | 0; mid = (mid + Math.imul(al3, bh1)) | 0; mid = (mid + Math.imul(ah3, bl1)) | 0; hi = (hi + Math.imul(ah3, bh1)) | 0; lo = (lo + Math.imul(al2, bl2)) | 0; mid = (mid + Math.imul(al2, bh2)) | 0; mid = (mid + Math.imul(ah2, bl2)) | 0; hi = (hi + Math.imul(ah2, bh2)) | 0; lo = (lo + Math.imul(al1, bl3)) | 0; mid = (mid + Math.imul(al1, bh3)) | 0; mid = (mid + Math.imul(ah1, bl3)) | 0; hi = (hi + Math.imul(ah1, bh3)) | 0; lo = (lo + Math.imul(al0, bl4)) | 0; mid = (mid + Math.imul(al0, bh4)) | 0; mid = (mid + Math.imul(ah0, bl4)) | 0; hi = (hi + Math.imul(ah0, bh4)) | 0; var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; w4 &= 0x3ffffff; /* k = 5 */ lo = Math.imul(al5, bl0); mid = Math.imul(al5, bh0); mid = (mid + Math.imul(ah5, bl0)) | 0; hi = Math.imul(ah5, bh0); lo = (lo + Math.imul(al4, bl1)) | 0; mid = (mid + Math.imul(al4, bh1)) | 0; mid = (mid + Math.imul(ah4, bl1)) | 0; hi = (hi + Math.imul(ah4, bh1)) | 0; lo = (lo + Math.imul(al3, bl2)) | 0; mid = (mid + Math.imul(al3, bh2)) | 0; mid = (mid + Math.imul(ah3, bl2)) | 0; hi = (hi + Math.imul(ah3, bh2)) | 0; lo = (lo + Math.imul(al2, bl3)) | 0; mid = (mid + Math.imul(al2, bh3)) | 0; mid = (mid + Math.imul(ah2, bl3)) | 0; hi = (hi + Math.imul(ah2, bh3)) | 0; lo = (lo + Math.imul(al1, bl4)) | 0; mid = (mid + Math.imul(al1, bh4)) | 0; mid = (mid + Math.imul(ah1, bl4)) | 0; hi = (hi + Math.imul(ah1, bh4)) | 0; lo = (lo + Math.imul(al0, bl5)) | 0; mid = (mid + Math.imul(al0, bh5)) | 0; mid = (mid + Math.imul(ah0, bl5)) | 0; hi = (hi + Math.imul(ah0, bh5)) | 0; var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; w5 &= 0x3ffffff; /* k = 6 */ lo = Math.imul(al6, bl0); mid = Math.imul(al6, bh0); mid = (mid + Math.imul(ah6, bl0)) | 0; hi = Math.imul(ah6, bh0); lo = (lo + Math.imul(al5, bl1)) | 0; mid = (mid + Math.imul(al5, bh1)) | 0; mid = (mid + Math.imul(ah5, bl1)) | 0; hi = (hi + Math.imul(ah5, bh1)) | 0; lo = (lo + Math.imul(al4, bl2)) | 0; mid = (mid + Math.imul(al4, bh2)) | 0; mid = (mid + Math.imul(ah4, bl2)) | 0; hi = (hi + Math.imul(ah4, bh2)) | 0; lo = (lo + Math.imul(al3, bl3)) | 0; mid = (mid + Math.imul(al3, bh3)) | 0; mid = (mid + Math.imul(ah3, bl3)) | 0; hi = (hi + Math.imul(ah3, bh3)) | 0; lo = (lo + Math.imul(al2, bl4)) | 0; mid = (mid + Math.imul(al2, bh4)) | 0; mid = (mid + Math.imul(ah2, bl4)) | 0; hi = (hi + Math.imul(ah2, bh4)) | 0; lo = (lo + Math.imul(al1, bl5)) | 0; mid = (mid + Math.imul(al1, bh5)) | 0; mid = (mid + Math.imul(ah1, bl5)) | 0; hi = (hi + Math.imul(ah1, bh5)) | 0; lo = (lo + Math.imul(al0, bl6)) | 0; mid = (mid + Math.imul(al0, bh6)) | 0; mid = (mid + Math.imul(ah0, bl6)) | 0; hi = (hi + Math.imul(ah0, bh6)) | 0; var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; w6 &= 0x3ffffff; /* k = 7 */ lo = Math.imul(al7, bl0); mid = Math.imul(al7, bh0); mid = (mid + Math.imul(ah7, bl0)) | 0; hi = Math.imul(ah7, bh0); lo = (lo + Math.imul(al6, bl1)) | 0; mid = (mid + Math.imul(al6, bh1)) | 0; mid = (mid + Math.imul(ah6, bl1)) | 0; hi = (hi + Math.imul(ah6, bh1)) | 0; lo = (lo + Math.imul(al5, bl2)) | 0; mid = (mid + Math.imul(al5, bh2)) | 0; mid = (mid + Math.imul(ah5, bl2)) | 0; hi = (hi + Math.imul(ah5, bh2)) | 0; lo = (lo + Math.imul(al4, bl3)) | 0; mid = (mid + Math.imul(al4, bh3)) | 0; mid = (mid + Math.imul(ah4, bl3)) | 0; hi = (hi + Math.imul(ah4, bh3)) | 0; lo = (lo + Math.imul(al3, bl4)) | 0; mid = (mid + Math.imul(al3, bh4)) | 0; mid = (mid + Math.imul(ah3, bl4)) | 0; hi = (hi + Math.imul(ah3, bh4)) | 0; lo = (lo + Math.imul(al2, bl5)) | 0; mid = (mid + Math.imul(al2, bh5)) | 0; mid = (mid + Math.imul(ah2, bl5)) | 0; hi = (hi + Math.imul(ah2, bh5)) | 0; lo = (lo + Math.imul(al1, bl6)) | 0; mid = (mid + Math.imul(al1, bh6)) | 0; mid = (mid + Math.imul(ah1, bl6)) | 0; hi = (hi + Math.imul(ah1, bh6)) | 0; lo = (lo + Math.imul(al0, bl7)) | 0; mid = (mid + Math.imul(al0, bh7)) | 0; mid = (mid + Math.imul(ah0, bl7)) | 0; hi = (hi + Math.imul(ah0, bh7)) | 0; var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; w7 &= 0x3ffffff; /* k = 8 */ lo = Math.imul(al8, bl0); mid = Math.imul(al8, bh0); mid = (mid + Math.imul(ah8, bl0)) | 0; hi = Math.imul(ah8, bh0); lo = (lo + Math.imul(al7, bl1)) | 0; mid = (mid + Math.imul(al7, bh1)) | 0; mid = (mid + Math.imul(ah7, bl1)) | 0; hi = (hi + Math.imul(ah7, bh1)) | 0; lo = (lo + Math.imul(al6, bl2)) | 0; mid = (mid + Math.imul(al6, bh2)) | 0; mid = (mid + Math.imul(ah6, bl2)) | 0; hi = (hi + Math.imul(ah6, bh2)) | 0; lo = (lo + Math.imul(al5, bl3)) | 0; mid = (mid + Math.imul(al5, bh3)) | 0; mid = (mid + Math.imul(ah5, bl3)) | 0; hi = (hi + Math.imul(ah5, bh3)) | 0; lo = (lo + Math.imul(al4, bl4)) | 0; mid = (mid + Math.imul(al4, bh4)) | 0; mid = (mid + Math.imul(ah4, bl4)) | 0; hi = (hi + Math.imul(ah4, bh4)) | 0; lo = (lo + Math.imul(al3, bl5)) | 0; mid = (mid + Math.imul(al3, bh5)) | 0; mid = (mid + Math.imul(ah3, bl5)) | 0; hi = (hi + Math.imul(ah3, bh5)) | 0; lo = (lo + Math.imul(al2, bl6)) | 0; mid = (mid + Math.imul(al2, bh6)) | 0; mid = (mid + Math.imul(ah2, bl6)) | 0; hi = (hi + Math.imul(ah2, bh6)) | 0; lo = (lo + Math.imul(al1, bl7)) | 0; mid = (mid + Math.imul(al1, bh7)) | 0; mid = (mid + Math.imul(ah1, bl7)) | 0; hi = (hi + Math.imul(ah1, bh7)) | 0; lo = (lo + Math.imul(al0, bl8)) | 0; mid = (mid + Math.imul(al0, bh8)) | 0; mid = (mid + Math.imul(ah0, bl8)) | 0; hi = (hi + Math.imul(ah0, bh8)) | 0; var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; w8 &= 0x3ffffff; /* k = 9 */ lo = Math.imul(al9, bl0); mid = Math.imul(al9, bh0); mid = (mid + Math.imul(ah9, bl0)) | 0; hi = Math.imul(ah9, bh0); lo = (lo + Math.imul(al8, bl1)) | 0; mid = (mid + Math.imul(al8, bh1)) | 0; mid = (mid + Math.imul(ah8, bl1)) | 0; hi = (hi + Math.imul(ah8, bh1)) | 0; lo = (lo + Math.imul(al7, bl2)) | 0; mid = (mid + Math.imul(al7, bh2)) | 0; mid = (mid + Math.imul(ah7, bl2)) | 0; hi = (hi + Math.imul(ah7, bh2)) | 0; lo = (lo + Math.imul(al6, bl3)) | 0; mid = (mid + Math.imul(al6, bh3)) | 0; mid = (mid + Math.imul(ah6, bl3)) | 0; hi = (hi + Math.imul(ah6, bh3)) | 0; lo = (lo + Math.imul(al5, bl4)) | 0; mid = (mid + Math.imul(al5, bh4)) | 0; mid = (mid + Math.imul(ah5, bl4)) | 0; hi = (hi + Math.imul(ah5, bh4)) | 0; lo = (lo + Math.imul(al4, bl5)) | 0; mid = (mid + Math.imul(al4, bh5)) | 0; mid = (mid + Math.imul(ah4, bl5)) | 0; hi = (hi + Math.imul(ah4, bh5)) | 0; lo = (lo + Math.imul(al3, bl6)) | 0; mid = (mid + Math.imul(al3, bh6)) | 0; mid = (mid + Math.imul(ah3, bl6)) | 0; hi = (hi + Math.imul(ah3, bh6)) | 0; lo = (lo + Math.imul(al2, bl7)) | 0; mid = (mid + Math.imul(al2, bh7)) | 0; mid = (mid + Math.imul(ah2, bl7)) | 0; hi = (hi + Math.imul(ah2, bh7)) | 0; lo = (lo + Math.imul(al1, bl8)) | 0; mid = (mid + Math.imul(al1, bh8)) | 0; mid = (mid + Math.imul(ah1, bl8)) | 0; hi = (hi + Math.imul(ah1, bh8)) | 0; lo = (lo + Math.imul(al0, bl9)) | 0; mid = (mid + Math.imul(al0, bh9)) | 0; mid = (mid + Math.imul(ah0, bl9)) | 0; hi = (hi + Math.imul(ah0, bh9)) | 0; var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; w9 &= 0x3ffffff; /* k = 10 */ lo = Math.imul(al9, bl1); mid = Math.imul(al9, bh1); mid = (mid + Math.imul(ah9, bl1)) | 0; hi = Math.imul(ah9, bh1); lo = (lo + Math.imul(al8, bl2)) | 0; mid = (mid + Math.imul(al8, bh2)) | 0; mid = (mid + Math.imul(ah8, bl2)) | 0; hi = (hi + Math.imul(ah8, bh2)) | 0; lo = (lo + Math.imul(al7, bl3)) | 0; mid = (mid + Math.imul(al7, bh3)) | 0; mid = (mid + Math.imul(ah7, bl3)) | 0; hi = (hi + Math.imul(ah7, bh3)) | 0; lo = (lo + Math.imul(al6, bl4)) | 0; mid = (mid + Math.imul(al6, bh4)) | 0; mid = (mid + Math.imul(ah6, bl4)) | 0; hi = (hi + Math.imul(ah6, bh4)) | 0; lo = (lo + Math.imul(al5, bl5)) | 0; mid = (mid + Math.imul(al5, bh5)) | 0; mid = (mid + Math.imul(ah5, bl5)) | 0; hi = (hi + Math.imul(ah5, bh5)) | 0; lo = (lo + Math.imul(al4, bl6)) | 0; mid = (mid + Math.imul(al4, bh6)) | 0; mid = (mid + Math.imul(ah4, bl6)) | 0; hi = (hi + Math.imul(ah4, bh6)) | 0; lo = (lo + Math.imul(al3, bl7)) | 0; mid = (mid + Math.imul(al3, bh7)) | 0; mid = (mid + Math.imul(ah3, bl7)) | 0; hi = (hi + Math.imul(ah3, bh7)) | 0; lo = (lo + Math.imul(al2, bl8)) | 0; mid = (mid + Math.imul(al2, bh8)) | 0; mid = (mid + Math.imul(ah2, bl8)) | 0; hi = (hi + Math.imul(ah2, bh8)) | 0; lo = (lo + Math.imul(al1, bl9)) | 0; mid = (mid + Math.imul(al1, bh9)) | 0; mid = (mid + Math.imul(ah1, bl9)) | 0; hi = (hi + Math.imul(ah1, bh9)) | 0; var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; w10 &= 0x3ffffff; /* k = 11 */ lo = Math.imul(al9, bl2); mid = Math.imul(al9, bh2); mid = (mid + Math.imul(ah9, bl2)) | 0; hi = Math.imul(ah9, bh2); lo = (lo + Math.imul(al8, bl3)) | 0; mid = (mid + Math.imul(al8, bh3)) | 0; mid = (mid + Math.imul(ah8, bl3)) | 0; hi = (hi + Math.imul(ah8, bh3)) | 0; lo = (lo + Math.imul(al7, bl4)) | 0; mid = (mid + Math.imul(al7, bh4)) | 0; mid = (mid + Math.imul(ah7, bl4)) | 0; hi = (hi + Math.imul(ah7, bh4)) | 0; lo = (lo + Math.imul(al6, bl5)) | 0; mid = (mid + Math.imul(al6, bh5)) | 0; mid = (mid + Math.imul(ah6, bl5)) | 0; hi = (hi + Math.imul(ah6, bh5)) | 0; lo = (lo + Math.imul(al5, bl6)) | 0; mid = (mid + Math.imul(al5, bh6)) | 0; mid = (mid + Math.imul(ah5, bl6)) | 0; hi = (hi + Math.imul(ah5, bh6)) | 0; lo = (lo + Math.imul(al4, bl7)) | 0; mid = (mid + Math.imul(al4, bh7)) | 0; mid = (mid + Math.imul(ah4, bl7)) | 0; hi = (hi + Math.imul(ah4, bh7)) | 0; lo = (lo + Math.imul(al3, bl8)) | 0; mid = (mid + Math.imul(al3, bh8)) | 0; mid = (mid + Math.imul(ah3, bl8)) | 0; hi = (hi + Math.imul(ah3, bh8)) | 0; lo = (lo + Math.imul(al2, bl9)) | 0; mid = (mid + Math.imul(al2, bh9)) | 0; mid = (mid + Math.imul(ah2, bl9)) | 0; hi = (hi + Math.imul(ah2, bh9)) | 0; var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; w11 &= 0x3ffffff; /* k = 12 */ lo = Math.imul(al9, bl3); mid = Math.imul(al9, bh3); mid = (mid + Math.imul(ah9, bl3)) | 0; hi = Math.imul(ah9, bh3); lo = (lo + Math.imul(al8, bl4)) | 0; mid = (mid + Math.imul(al8, bh4)) | 0; mid = (mid + Math.imul(ah8, bl4)) | 0; hi = (hi + Math.imul(ah8, bh4)) | 0; lo = (lo + Math.imul(al7, bl5)) | 0; mid = (mid + Math.imul(al7, bh5)) | 0; mid = (mid + Math.imul(ah7, bl5)) | 0; hi = (hi + Math.imul(ah7, bh5)) | 0; lo = (lo + Math.imul(al6, bl6)) | 0; mid = (mid + Math.imul(al6, bh6)) | 0; mid = (mid + Math.imul(ah6, bl6)) | 0; hi = (hi + Math.imul(ah6, bh6)) | 0; lo = (lo + Math.imul(al5, bl7)) | 0; mid = (mid + Math.imul(al5, bh7)) | 0; mid = (mid + Math.imul(ah5, bl7)) | 0; hi = (hi + Math.imul(ah5, bh7)) | 0; lo = (lo + Math.imul(al4, bl8)) | 0; mid = (mid + Math.imul(al4, bh8)) | 0; mid = (mid + Math.imul(ah4, bl8)) | 0; hi = (hi + Math.imul(ah4, bh8)) | 0; lo = (lo + Math.imul(al3, bl9)) | 0; mid = (mid + Math.imul(al3, bh9)) | 0; mid = (mid + Math.imul(ah3, bl9)) | 0; hi = (hi + Math.imul(ah3, bh9)) | 0; var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; w12 &= 0x3ffffff; /* k = 13 */ lo = Math.imul(al9, bl4); mid = Math.imul(al9, bh4); mid = (mid + Math.imul(ah9, bl4)) | 0; hi = Math.imul(ah9, bh4); lo = (lo + Math.imul(al8, bl5)) | 0; mid = (mid + Math.imul(al8, bh5)) | 0; mid = (mid + Math.imul(ah8, bl5)) | 0; hi = (hi + Math.imul(ah8, bh5)) | 0; lo = (lo + Math.imul(al7, bl6)) | 0; mid = (mid + Math.imul(al7, bh6)) | 0; mid = (mid + Math.imul(ah7, bl6)) | 0; hi = (hi + Math.imul(ah7, bh6)) | 0; lo = (lo + Math.imul(al6, bl7)) | 0; mid = (mid + Math.imul(al6, bh7)) | 0; mid = (mid + Math.imul(ah6, bl7)) | 0; hi = (hi + Math.imul(ah6, bh7)) | 0; lo = (lo + Math.imul(al5, bl8)) | 0; mid = (mid + Math.imul(al5, bh8)) | 0; mid = (mid + Math.imul(ah5, bl8)) | 0; hi = (hi + Math.imul(ah5, bh8)) | 0; lo = (lo + Math.imul(al4, bl9)) | 0; mid = (mid + Math.imul(al4, bh9)) | 0; mid = (mid + Math.imul(ah4, bl9)) | 0; hi = (hi + Math.imul(ah4, bh9)) | 0; var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; w13 &= 0x3ffffff; /* k = 14 */ lo = Math.imul(al9, bl5); mid = Math.imul(al9, bh5); mid = (mid + Math.imul(ah9, bl5)) | 0; hi = Math.imul(ah9, bh5); lo = (lo + Math.imul(al8, bl6)) | 0; mid = (mid + Math.imul(al8, bh6)) | 0; mid = (mid + Math.imul(ah8, bl6)) | 0; hi = (hi + Math.imul(ah8, bh6)) | 0; lo = (lo + Math.imul(al7, bl7)) | 0; mid = (mid + Math.imul(al7, bh7)) | 0; mid = (mid + Math.imul(ah7, bl7)) | 0; hi = (hi + Math.imul(ah7, bh7)) | 0; lo = (lo + Math.imul(al6, bl8)) | 0; mid = (mid + Math.imul(al6, bh8)) | 0; mid = (mid + Math.imul(ah6, bl8)) | 0; hi = (hi + Math.imul(ah6, bh8)) | 0; lo = (lo + Math.imul(al5, bl9)) | 0; mid = (mid + Math.imul(al5, bh9)) | 0; mid = (mid + Math.imul(ah5, bl9)) | 0; hi = (hi + Math.imul(ah5, bh9)) | 0; var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; w14 &= 0x3ffffff; /* k = 15 */ lo = Math.imul(al9, bl6); mid = Math.imul(al9, bh6); mid = (mid + Math.imul(ah9, bl6)) | 0; hi = Math.imul(ah9, bh6); lo = (lo + Math.imul(al8, bl7)) | 0; mid = (mid + Math.imul(al8, bh7)) | 0; mid = (mid + Math.imul(ah8, bl7)) | 0; hi = (hi + Math.imul(ah8, bh7)) | 0; lo = (lo + Math.imul(al7, bl8)) | 0; mid = (mid + Math.imul(al7, bh8)) | 0; mid = (mid + Math.imul(ah7, bl8)) | 0; hi = (hi + Math.imul(ah7, bh8)) | 0; lo = (lo + Math.imul(al6, bl9)) | 0; mid = (mid + Math.imul(al6, bh9)) | 0; mid = (mid + Math.imul(ah6, bl9)) | 0; hi = (hi + Math.imul(ah6, bh9)) | 0; var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; w15 &= 0x3ffffff; /* k = 16 */ lo = Math.imul(al9, bl7); mid = Math.imul(al9, bh7); mid = (mid + Math.imul(ah9, bl7)) | 0; hi = Math.imul(ah9, bh7); lo = (lo + Math.imul(al8, bl8)) | 0; mid = (mid + Math.imul(al8, bh8)) | 0; mid = (mid + Math.imul(ah8, bl8)) | 0; hi = (hi + Math.imul(ah8, bh8)) | 0; lo = (lo + Math.imul(al7, bl9)) | 0; mid = (mid + Math.imul(al7, bh9)) | 0; mid = (mid + Math.imul(ah7, bl9)) | 0; hi = (hi + Math.imul(ah7, bh9)) | 0; var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; w16 &= 0x3ffffff; /* k = 17 */ lo = Math.imul(al9, bl8); mid = Math.imul(al9, bh8); mid = (mid + Math.imul(ah9, bl8)) | 0; hi = Math.imul(ah9, bh8); lo = (lo + Math.imul(al8, bl9)) | 0; mid = (mid + Math.imul(al8, bh9)) | 0; mid = (mid + Math.imul(ah8, bl9)) | 0; hi = (hi + Math.imul(ah8, bh9)) | 0; var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; w17 &= 0x3ffffff; /* k = 18 */ lo = Math.imul(al9, bl9); mid = Math.imul(al9, bh9); mid = (mid + Math.imul(ah9, bl9)) | 0; hi = Math.imul(ah9, bh9); var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; w18 &= 0x3ffffff; o[0] = w0; o[1] = w1; o[2] = w2; o[3] = w3; o[4] = w4; o[5] = w5; o[6] = w6; o[7] = w7; o[8] = w8; o[9] = w9; o[10] = w10; o[11] = w11; o[12] = w12; o[13] = w13; o[14] = w14; o[15] = w15; o[16] = w16; o[17] = w17; o[18] = w18; if (c !== 0) { o[19] = c; out.length++; } return out; }; // Polyfill comb if (!Math.imul) { comb10MulTo = smallMulTo; } function bigMulTo (self, num, out) { out.negative = num.negative ^ self.negative; out.length = self.length + num.length; var carry = 0; var hncarry = 0; for (var k = 0; k < out.length - 1; k++) { // Sum all words with the same `i + j = k` and accumulate `ncarry`, // note that ncarry could be >= 0x3ffffff var ncarry = hncarry; hncarry = 0; var rword = carry & 0x3ffffff; var maxJ = Math.min(k, num.length - 1); for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { var i = k - j; var a = self.words[i] | 0; var b = num.words[j] | 0; var r = a * b; var lo = r & 0x3ffffff; ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; lo = (lo + rword) | 0; rword = lo & 0x3ffffff; ncarry = (ncarry + (lo >>> 26)) | 0; hncarry += ncarry >>> 26; ncarry &= 0x3ffffff; } out.words[k] = rword; carry = ncarry; ncarry = hncarry; } if (carry !== 0) { out.words[k] = carry; } else { out.length--; } return out._strip(); } function jumboMulTo (self, num, out) { // Temporary disable, see https://github.com/indutny/bn.js/issues/211 // var fftm = new FFTM(); // return fftm.mulp(self, num, out); return bigMulTo(self, num, out); } BN.prototype.mulTo = function mulTo (num, out) { var res; var len = this.length + num.length; if (this.length === 10 && num.length === 10) { res = comb10MulTo(this, num, out); } else if (len < 63) { res = smallMulTo(this, num, out); } else if (len < 1024) { res = bigMulTo(this, num, out); } else { res = jumboMulTo(this, num, out); } return res; }; // Multiply `this` by `num` BN.prototype.mul = function mul (num) { var out = new BN(null); out.words = new Array(this.length + num.length); return this.mulTo(num, out); }; // Multiply employing FFT BN.prototype.mulf = function mulf (num) { var out = new BN(null); out.words = new Array(this.length + num.length); return jumboMulTo(this, num, out); }; // In-place Multiplication BN.prototype.imul = function imul (num) { return this.clone().mulTo(num, this); }; BN.prototype.imuln = function imuln (num) { var isNegNum = num < 0; if (isNegNum) num = -num; assert(typeof num === 'number'); assert(num < 0x4000000); // Carry var carry = 0; for (var i = 0; i < this.length; i++) { var w = (this.words[i] | 0) * num; var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); carry >>= 26; carry += (w / 0x4000000) | 0; // NOTE: lo is 27bit maximum carry += lo >>> 26; this.words[i] = lo & 0x3ffffff; } if (carry !== 0) { this.words[i] = carry; this.length++; } return isNegNum ? this.ineg() : this; }; BN.prototype.muln = function muln (num) { return this.clone().imuln(num); }; // `this` * `this` BN.prototype.sqr = function sqr () { return this.mul(this); }; // `this` * `this` in-place BN.prototype.isqr = function isqr () { return this.imul(this.clone()); }; // Math.pow(`this`, `num`) BN.prototype.pow = function pow (num) { var w = toBitArray(num); if (w.length === 0) return new BN(1); // Skip leading zeroes var res = this; for (var i = 0; i < w.length; i++, res = res.sqr()) { if (w[i] !== 0) break; } if (++i < w.length) { for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { if (w[i] === 0) continue; res = res.mul(q); } } return res; }; // Shift-left in-place BN.prototype.iushln = function iushln (bits) { assert(typeof bits === 'number' && bits >= 0); var r = bits % 26; var s = (bits - r) / 26; var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); var i; if (r !== 0) { var carry = 0; for (i = 0; i < this.length; i++) { var newCarry = this.words[i] & carryMask; var c = ((this.words[i] | 0) - newCarry) << r; this.words[i] = c | carry; carry = newCarry >>> (26 - r); } if (carry) { this.words[i] = carry; this.length++; } } if (s !== 0) { for (i = this.length - 1; i >= 0; i--) { this.words[i + s] = this.words[i]; } for (i = 0; i < s; i++) { this.words[i] = 0; } this.length += s; } return this._strip(); }; BN.prototype.ishln = function ishln (bits) { // TODO(indutny): implement me assert(this.negative === 0); return this.iushln(bits); }; // Shift-right in-place // NOTE: `hint` is a lowest bit before trailing zeroes // NOTE: if `extended` is present - it will be filled with destroyed bits BN.prototype.iushrn = function iushrn (bits, hint, extended) { assert(typeof bits === 'number' && bits >= 0); var h; if (hint) { h = (hint - (hint % 26)) / 26; } else { h = 0; } var r = bits % 26; var s = Math.min((bits - r) / 26, this.length); var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); var maskedWords = extended; h -= s; h = Math.max(0, h); // Extended mode, copy masked part if (maskedWords) { for (var i = 0; i < s; i++) { maskedWords.words[i] = this.words[i]; } maskedWords.length = s; } if (s === 0) ; else if (this.length > s) { this.length -= s; for (i = 0; i < this.length; i++) { this.words[i] = this.words[i + s]; } } else { this.words[0] = 0; this.length = 1; } var carry = 0; for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { var word = this.words[i] | 0; this.words[i] = (carry << (26 - r)) | (word >>> r); carry = word & mask; } // Push carried bits as a mask if (maskedWords && carry !== 0) { maskedWords.words[maskedWords.length++] = carry; } if (this.length === 0) { this.words[0] = 0; this.length = 1; } return this._strip(); }; BN.prototype.ishrn = function ishrn (bits, hint, extended) { // TODO(indutny): implement me assert(this.negative === 0); return this.iushrn(bits, hint, extended); }; // Shift-left BN.prototype.shln = function shln (bits) { return this.clone().ishln(bits); }; BN.prototype.ushln = function ushln (bits) { return this.clone().iushln(bits); }; // Shift-right BN.prototype.shrn = function shrn (bits) { return this.clone().ishrn(bits); }; BN.prototype.ushrn = function ushrn (bits) { return this.clone().iushrn(bits); }; // Test if n bit is set BN.prototype.testn = function testn (bit) { assert(typeof bit === 'number' && bit >= 0); var r = bit % 26; var s = (bit - r) / 26; var q = 1 << r; // Fast case: bit is much higher than all existing words if (this.length <= s) return false; // Check bit and return var w = this.words[s]; return !!(w & q); }; // Return only lowers bits of number (in-place) BN.prototype.imaskn = function imaskn (bits) { assert(typeof bits === 'number' && bits >= 0); var r = bits % 26; var s = (bits - r) / 26; assert(this.negative === 0, 'imaskn works only with positive numbers'); if (this.length <= s) { return this; } if (r !== 0) { s++; } this.length = Math.min(s, this.length); if (r !== 0) { var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); this.words[this.length - 1] &= mask; } return this._strip(); }; // Return only lowers bits of number BN.prototype.maskn = function maskn (bits) { return this.clone().imaskn(bits); }; // Add plain number `num` to `this` BN.prototype.iaddn = function iaddn (num) { assert(typeof num === 'number'); assert(num < 0x4000000); if (num < 0) return this.isubn(-num); // Possible sign change if (this.negative !== 0) { if (this.length === 1 && (this.words[0] | 0) <= num) { this.words[0] = num - (this.words[0] | 0); this.negative = 0; return this; } this.negative = 0; this.isubn(num); this.negative = 1; return this; } // Add without checks return this._iaddn(num); }; BN.prototype._iaddn = function _iaddn (num) { this.words[0] += num; // Carry for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { this.words[i] -= 0x4000000; if (i === this.length - 1) { this.words[i + 1] = 1; } else { this.words[i + 1]++; } } this.length = Math.max(this.length, i + 1); return this; }; // Subtract plain number `num` from `this` BN.prototype.isubn = function isubn (num) { assert(typeof num === 'number'); assert(num < 0x4000000); if (num < 0) return this.iaddn(-num); if (this.negative !== 0) { this.negative = 0; this.iaddn(num); this.negative = 1; return this; } this.words[0] -= num; if (this.length === 1 && this.words[0] < 0) { this.words[0] = -this.words[0]; this.negative = 1; } else { // Carry for (var i = 0; i < this.length && this.words[i] < 0; i++) { this.words[i] += 0x4000000; this.words[i + 1] -= 1; } } return this._strip(); }; BN.prototype.addn = function addn (num) { return this.clone().iaddn(num); }; BN.prototype.subn = function subn (num) { return this.clone().isubn(num); }; BN.prototype.iabs = function iabs () { this.negative = 0; return this; }; BN.prototype.abs = function abs () { return this.clone().iabs(); }; BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { var len = num.length + shift; var i; this._expand(len); var w; var carry = 0; for (i = 0; i < num.length; i++) { w = (this.words[i + shift] | 0) + carry; var right = (num.words[i] | 0) * mul; w -= right & 0x3ffffff; carry = (w >> 26) - ((right / 0x4000000) | 0); this.words[i + shift] = w & 0x3ffffff; } for (; i < this.length - shift; i++) { w = (this.words[i + shift] | 0) + carry; carry = w >> 26; this.words[i + shift] = w & 0x3ffffff; } if (carry === 0) return this._strip(); // Subtraction overflow assert(carry === -1); carry = 0; for (i = 0; i < this.length; i++) { w = -(this.words[i] | 0) + carry; carry = w >> 26; this.words[i] = w & 0x3ffffff; } this.negative = 1; return this._strip(); }; BN.prototype._wordDiv = function _wordDiv (num, mode) { var shift = this.length - num.length; var a = this.clone(); var b = num; // Normalize var bhi = b.words[b.length - 1] | 0; var bhiBits = this._countBits(bhi); shift = 26 - bhiBits; if (shift !== 0) { b = b.ushln(shift); a.iushln(shift); bhi = b.words[b.length - 1] | 0; } // Initialize quotient var m = a.length - b.length; var q; if (mode !== 'mod') { q = new BN(null); q.length = m + 1; q.words = new Array(q.length); for (var i = 0; i < q.length; i++) { q.words[i] = 0; } } var diff = a.clone()._ishlnsubmul(b, 1, m); if (diff.negative === 0) { a = diff; if (q) { q.words[m] = 1; } } for (var j = m - 1; j >= 0; j--) { var qj = (a.words[b.length + j] | 0) * 0x4000000 + (a.words[b.length + j - 1] | 0); // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max // (0x7ffffff) qj = Math.min((qj / bhi) | 0, 0x3ffffff); a._ishlnsubmul(b, qj, j); while (a.negative !== 0) { qj--; a.negative = 0; a._ishlnsubmul(b, 1, j); if (!a.isZero()) { a.negative ^= 1; } } if (q) { q.words[j] = qj; } } if (q) { q._strip(); } a._strip(); // Denormalize if (mode !== 'div' && shift !== 0) { a.iushrn(shift); } return { div: q || null, mod: a }; }; // NOTE: 1) `mode` can be set to `mod` to request mod only, // to `div` to request div only, or be absent to // request both div & mod // 2) `positive` is true if unsigned mod is requested BN.prototype.divmod = function divmod (num, mode, positive) { assert(!num.isZero()); if (this.isZero()) { return { div: new BN(0), mod: new BN(0) }; } var div, mod, res; if (this.negative !== 0 && num.negative === 0) { res = this.neg().divmod(num, mode); if (mode !== 'mod') { div = res.div.neg(); } if (mode !== 'div') { mod = res.mod.neg(); if (positive && mod.negative !== 0) { mod.iadd(num); } } return { div: div, mod: mod }; } if (this.negative === 0 && num.negative !== 0) { res = this.divmod(num.neg(), mode); if (mode !== 'mod') { div = res.div.neg(); } return { div: div, mod: res.mod }; } if ((this.negative & num.negative) !== 0) { res = this.neg().divmod(num.neg(), mode); if (mode !== 'div') { mod = res.mod.neg(); if (positive && mod.negative !== 0) { mod.isub(num); } } return { div: res.div, mod: mod }; } // Both numbers are positive at this point // Strip both numbers to approximate shift value if (num.length > this.length || this.cmp(num) < 0) { return { div: new BN(0), mod: this }; } // Very short reduction if (num.length === 1) { if (mode === 'div') { return { div: this.divn(num.words[0]), mod: null }; } if (mode === 'mod') { return { div: null, mod: new BN(this.modrn(num.words[0])) }; } return { div: this.divn(num.words[0]), mod: new BN(this.modrn(num.words[0])) }; } return this._wordDiv(num, mode); }; // Find `this` / `num` BN.prototype.div = function div (num) { return this.divmod(num, 'div', false).div; }; // Find `this` % `num` BN.prototype.mod = function mod (num) { return this.divmod(num, 'mod', false).mod; }; BN.prototype.umod = function umod (num) { return this.divmod(num, 'mod', true).mod; }; // Find Round(`this` / `num`) BN.prototype.divRound = function divRound (num) { var dm = this.divmod(num); // Fast case - exact division if (dm.mod.isZero()) return dm.div; var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; var half = num.ushrn(1); var r2 = num.andln(1); var cmp = mod.cmp(half); // Round down if (cmp < 0 || (r2 === 1 && cmp === 0)) return dm.div; // Round up return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); }; BN.prototype.modrn = function modrn (num) { var isNegNum = num < 0; if (isNegNum) num = -num; assert(num <= 0x3ffffff); var p = (1 << 26) % num; var acc = 0; for (var i = this.length - 1; i >= 0; i--) { acc = (p * acc + (this.words[i] | 0)) % num; } return isNegNum ? -acc : acc; }; // WARNING: DEPRECATED BN.prototype.modn = function modn (num) { return this.modrn(num); }; // In-place division by number BN.prototype.idivn = function idivn (num) { var isNegNum = num < 0; if (isNegNum) num = -num; assert(num <= 0x3ffffff); var carry = 0; for (var i = this.length - 1; i >= 0; i--) { var w = (this.words[i] | 0) + carry * 0x4000000; this.words[i] = (w / num) | 0; carry = w % num; } this._strip(); return isNegNum ? this.ineg() : this; }; BN.prototype.divn = function divn (num) { return this.clone().idivn(num); }; BN.prototype.egcd = function egcd (p) { assert(p.negative === 0); assert(!p.isZero()); var x = this; var y = p.clone(); if (x.negative !== 0) { x = x.umod(p); } else { x = x.clone(); } // A * x + B * y = x var A = new BN(1); var B = new BN(0); // C * x + D * y = y var C = new BN(0); var D = new BN(1); var g = 0; while (x.isEven() && y.isEven()) { x.iushrn(1); y.iushrn(1); ++g; } var yp = y.clone(); var xp = x.clone(); while (!x.isZero()) { for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); if (i > 0) { x.iushrn(i); while (i-- > 0) { if (A.isOdd() || B.isOdd()) { A.iadd(yp); B.isub(xp); } A.iushrn(1); B.iushrn(1); } } for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); if (j > 0) { y.iushrn(j); while (j-- > 0) { if (C.isOdd() || D.isOdd()) { C.iadd(yp); D.isub(xp); } C.iushrn(1); D.iushrn(1); } } if (x.cmp(y) >= 0) { x.isub(y); A.isub(C); B.isub(D); } else { y.isub(x); C.isub(A); D.isub(B); } } return { a: C, b: D, gcd: y.iushln(g) }; }; // This is reduced incarnation of the binary EEA // above, designated to invert members of the // _prime_ fields F(p) at a maximal speed BN.prototype._invmp = function _invmp (p) { assert(p.negative === 0); assert(!p.isZero()); var a = this; var b = p.clone(); if (a.negative !== 0) { a = a.umod(p); } else { a = a.clone(); } var x1 = new BN(1); var x2 = new BN(0); var delta = b.clone(); while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); if (i > 0) { a.iushrn(i); while (i-- > 0) { if (x1.isOdd()) { x1.iadd(delta); } x1.iushrn(1); } } for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); if (j > 0) { b.iushrn(j); while (j-- > 0) { if (x2.isOdd()) { x2.iadd(delta); } x2.iushrn(1); } } if (a.cmp(b) >= 0) { a.isub(b); x1.isub(x2); } else { b.isub(a); x2.isub(x1); } } var res; if (a.cmpn(1) === 0) { res = x1; } else { res = x2; } if (res.cmpn(0) < 0) { res.iadd(p); } return res; }; BN.prototype.gcd = function gcd (num) { if (this.isZero()) return num.abs(); if (num.isZero()) return this.abs(); var a = this.clone(); var b = num.clone(); a.negative = 0; b.negative = 0; // Remove common factor of two for (var shift = 0; a.isEven() && b.isEven(); shift++) { a.iushrn(1); b.iushrn(1); } do { while (a.isEven()) { a.iushrn(1); } while (b.isEven()) { b.iushrn(1); } var r = a.cmp(b); if (r < 0) { // Swap `a` and `b` to make `a` always bigger than `b` var t = a; a = b; b = t; } else if (r === 0 || b.cmpn(1) === 0) { break; } a.isub(b); } while (true); return b.iushln(shift); }; // Invert number in the field F(num) BN.prototype.invm = function invm (num) { return this.egcd(num).a.umod(num); }; BN.prototype.isEven = function isEven () { return (this.words[0] & 1) === 0; }; BN.prototype.isOdd = function isOdd () { return (this.words[0] & 1) === 1; }; // And first word and num BN.prototype.andln = function andln (num) { return this.words[0] & num; }; // Increment at the bit position in-line BN.prototype.bincn = function bincn (bit) { assert(typeof bit === 'number'); var r = bit % 26; var s = (bit - r) / 26; var q = 1 << r; // Fast case: bit is much higher than all existing words if (this.length <= s) { this._expand(s + 1); this.words[s] |= q; return this; } // Add bit and propagate, if needed var carry = q; for (var i = s; carry !== 0 && i < this.length; i++) { var w = this.words[i] | 0; w += carry; carry = w >>> 26; w &= 0x3ffffff; this.words[i] = w; } if (carry !== 0) { this.words[i] = carry; this.length++; } return this; }; BN.prototype.isZero = function isZero () { return this.length === 1 && this.words[0] === 0; }; BN.prototype.cmpn = function cmpn (num) { var negative = num < 0; if (this.negative !== 0 && !negative) return -1; if (this.negative === 0 && negative) return 1; this._strip(); var res; if (this.length > 1) { res = 1; } else { if (negative) { num = -num; } assert(num <= 0x3ffffff, 'Number is too big'); var w = this.words[0] | 0; res = w === num ? 0 : w < num ? -1 : 1; } if (this.negative !== 0) return -res | 0; return res; }; // Compare two numbers and return: // 1 - if `this` > `num` // 0 - if `this` == `num` // -1 - if `this` < `num` BN.prototype.cmp = function cmp (num) { if (this.negative !== 0 && num.negative === 0) return -1; if (this.negative === 0 && num.negative !== 0) return 1; var res = this.ucmp(num); if (this.negative !== 0) return -res | 0; return res; }; // Unsigned comparison BN.prototype.ucmp = function ucmp (num) { // At this point both numbers have the same sign if (this.length > num.length) return 1; if (this.length < num.length) return -1; var res = 0; for (var i = this.length - 1; i >= 0; i--) { var a = this.words[i] | 0; var b = num.words[i] | 0; if (a === b) continue; if (a < b) { res = -1; } else if (a > b) { res = 1; } break; } return res; }; BN.prototype.gtn = function gtn (num) { return this.cmpn(num) === 1; }; BN.prototype.gt = function gt (num) { return this.cmp(num) === 1; }; BN.prototype.gten = function gten (num) { return this.cmpn(num) >= 0; }; BN.prototype.gte = function gte (num) { return this.cmp(num) >= 0; }; BN.prototype.ltn = function ltn (num) { return this.cmpn(num) === -1; }; BN.prototype.lt = function lt (num) { return this.cmp(num) === -1; }; BN.prototype.lten = function lten (num) { return this.cmpn(num) <= 0; }; BN.prototype.lte = function lte (num) { return this.cmp(num) <= 0; }; BN.prototype.eqn = function eqn (num) { return this.cmpn(num) === 0; }; BN.prototype.eq = function eq (num) { return this.cmp(num) === 0; }; // // A reduce context, could be using montgomery or something better, depending // on the `m` itself. // BN.red = function red (num) { return new Red(num); }; BN.prototype.toRed = function toRed (ctx) { assert(!this.red, 'Already a number in reduction context'); assert(this.negative === 0, 'red works only with positives'); return ctx.convertTo(this)._forceRed(ctx); }; BN.prototype.fromRed = function fromRed () { assert(this.red, 'fromRed works only with numbers in reduction context'); return this.red.convertFrom(this); }; BN.prototype._forceRed = function _forceRed (ctx) { this.red = ctx; return this; }; BN.prototype.forceRed = function forceRed (ctx) { assert(!this.red, 'Already a number in reduction context'); return this._forceRed(ctx); }; BN.prototype.redAdd = function redAdd (num) { assert(this.red, 'redAdd works only with red numbers'); return this.red.add(this, num); }; BN.prototype.redIAdd = function redIAdd (num) { assert(this.red, 'redIAdd works only with red numbers'); return this.red.iadd(this, num); }; BN.prototype.redSub = function redSub (num) { assert(this.red, 'redSub works only with red numbers'); return this.red.sub(this, num); }; BN.prototype.redISub = function redISub (num) { assert(this.red, 'redISub works only with red numbers'); return this.red.isub(this, num); }; BN.prototype.redShl = function redShl (num) { assert(this.red, 'redShl works only with red numbers'); return this.red.shl(this, num); }; BN.prototype.redMul = function redMul (num) { assert(this.red, 'redMul works only with red numbers'); this.red._verify2(this, num); return this.red.mul(this, num); }; BN.prototype.redIMul = function redIMul (num) { assert(this.red, 'redMul works only with red numbers'); this.red._verify2(this, num); return this.red.imul(this, num); }; BN.prototype.redSqr = function redSqr () { assert(this.red, 'redSqr works only with red numbers'); this.red._verify1(this); return this.red.sqr(this); }; BN.prototype.redISqr = function redISqr () { assert(this.red, 'redISqr works only with red numbers'); this.red._verify1(this); return this.red.isqr(this); }; // Square root over p BN.prototype.redSqrt = function redSqrt () { assert(this.red, 'redSqrt works only with red numbers'); this.red._verify1(this); return this.red.sqrt(this); }; BN.prototype.redInvm = function redInvm () { assert(this.red, 'redInvm works only with red numbers'); this.red._verify1(this); return this.red.invm(this); }; // Return negative clone of `this` % `red modulo` BN.prototype.redNeg = function redNeg () { assert(this.red, 'redNeg works only with red numbers'); this.red._verify1(this); return this.red.neg(this); }; BN.prototype.redPow = function redPow (num) { assert(this.red && !num.red, 'redPow(normalNum)'); this.red._verify1(this); return this.red.pow(this, num); }; // Prime numbers with efficient reduction var primes = { k256: null, p224: null, p192: null, p25519: null }; // Pseudo-Mersenne prime function MPrime (name, p) { // P = 2 ^ N - K this.name = name; this.p = new BN(p, 16); this.n = this.p.bitLength(); this.k = new BN(1).iushln(this.n).isub(this.p); this.tmp = this._tmp(); } MPrime.prototype._tmp = function _tmp () { var tmp = new BN(null); tmp.words = new Array(Math.ceil(this.n / 13)); return tmp; }; MPrime.prototype.ireduce = function ireduce (num) { // Assumes that `num` is less than `P^2` // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) var r = num; var rlen; do { this.split(r, this.tmp); r = this.imulK(r); r = r.iadd(this.tmp); rlen = r.bitLength(); } while (rlen > this.n); var cmp = rlen < this.n ? -1 : r.ucmp(this.p); if (cmp === 0) { r.words[0] = 0; r.length = 1; } else if (cmp > 0) { r.isub(this.p); } else { if (r.strip !== undefined) { // r is a BN v4 instance r.strip(); } else { // r is a BN v5 instance r._strip(); } } return r; }; MPrime.prototype.split = function split (input, out) { input.iushrn(this.n, 0, out); }; MPrime.prototype.imulK = function imulK (num) { return num.imul(this.k); }; function K256 () { MPrime.call( this, 'k256', 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); } inherits(K256, MPrime); K256.prototype.split = function split (input, output) { // 256 = 9 * 26 + 22 var mask = 0x3fffff; var outLen = Math.min(input.length, 9); for (var i = 0; i < outLen; i++) { output.words[i] = input.words[i]; } output.length = outLen; if (input.length <= 9) { input.words[0] = 0; input.length = 1; return; } // Shift by 9 limbs var prev = input.words[9]; output.words[output.length++] = prev & mask; for (i = 10; i < input.length; i++) { var next = input.words[i] | 0; input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); prev = next; } prev >>>= 22; input.words[i - 10] = prev; if (prev === 0 && input.length > 10) { input.length -= 10; } else { input.length -= 9; } }; K256.prototype.imulK = function imulK (num) { // K = 0x1000003d1 = [ 0x40, 0x3d1 ] num.words[num.length] = 0; num.words[num.length + 1] = 0; num.length += 2; // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 var lo = 0; for (var i = 0; i < num.length; i++) { var w = num.words[i] | 0; lo += w * 0x3d1; num.words[i] = lo & 0x3ffffff; lo = w * 0x40 + ((lo / 0x4000000) | 0); } // Fast length reduction if (num.words[num.length - 1] === 0) { num.length--; if (num.words[num.length - 1] === 0) { num.length--; } } return num; }; function P224 () { MPrime.call( this, 'p224', 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); } inherits(P224, MPrime); function P192 () { MPrime.call( this, 'p192', 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); } inherits(P192, MPrime); function P25519 () { // 2 ^ 255 - 19 MPrime.call( this, '25519', '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); } inherits(P25519, MPrime); P25519.prototype.imulK = function imulK (num) { // K = 0x13 var carry = 0; for (var i = 0; i < num.length; i++) { var hi = (num.words[i] | 0) * 0x13 + carry; var lo = hi & 0x3ffffff; hi >>>= 26; num.words[i] = lo; carry = hi; } if (carry !== 0) { num.words[num.length++] = carry; } return num; }; // Exported mostly for testing purposes, use plain name instead BN._prime = function prime (name) { // Cached version of prime if (primes[name]) return primes[name]; var prime; if (name === 'k256') { prime = new K256(); } else if (name === 'p224') { prime = new P224(); } else if (name === 'p192') { prime = new P192(); } else if (name === 'p25519') { prime = new P25519(); } else { throw new Error('Unknown prime ' + name); } primes[name] = prime; return prime; }; // // Base reduction engine // function Red (m) { if (typeof m === 'string') { var prime = BN._prime(m); this.m = prime.p; this.prime = prime; } else { assert(m.gtn(1), 'modulus must be greater than 1'); this.m = m; this.prime = null; } } Red.prototype._verify1 = function _verify1 (a) { assert(a.negative === 0, 'red works only with positives'); assert(a.red, 'red works only with red numbers'); }; Red.prototype._verify2 = function _verify2 (a, b) { assert((a.negative | b.negative) === 0, 'red works only with positives'); assert(a.red && a.red === b.red, 'red works only with red numbers'); }; Red.prototype.imod = function imod (a) { if (this.prime) return this.prime.ireduce(a)._forceRed(this); move(a, a.umod(this.m)._forceRed(this)); return a; }; Red.prototype.neg = function neg (a) { if (a.isZero()) { return a.clone(); } return this.m.sub(a)._forceRed(this); }; Red.prototype.add = function add (a, b) { this._verify2(a, b); var res = a.add(b); if (res.cmp(this.m) >= 0) { res.isub(this.m); } return res._forceRed(this); }; Red.prototype.iadd = function iadd (a, b) { this._verify2(a, b); var res = a.iadd(b); if (res.cmp(this.m) >= 0) { res.isub(this.m); } return res; }; Red.prototype.sub = function sub (a, b) { this._verify2(a, b); var res = a.sub(b); if (res.cmpn(0) < 0) { res.iadd(this.m); } return res._forceRed(this); }; Red.prototype.isub = function isub (a, b) { this._verify2(a, b); var res = a.isub(b); if (res.cmpn(0) < 0) { res.iadd(this.m); } return res; }; Red.prototype.shl = function shl (a, num) { this._verify1(a); return this.imod(a.ushln(num)); }; Red.prototype.imul = function imul (a, b) { this._verify2(a, b); return this.imod(a.imul(b)); }; Red.prototype.mul = function mul (a, b) { this._verify2(a, b); return this.imod(a.mul(b)); }; Red.prototype.isqr = function isqr (a) { return this.imul(a, a.clone()); }; Red.prototype.sqr = function sqr (a) { return this.mul(a, a); }; Red.prototype.sqrt = function sqrt (a) { if (a.isZero()) return a.clone(); var mod3 = this.m.andln(3); assert(mod3 % 2 === 1); // Fast case if (mod3 === 3) { var pow = this.m.add(new BN(1)).iushrn(2); return this.pow(a, pow); } // Tonelli-Shanks algorithm (Totally unoptimized and slow) // // Find Q and S, that Q * 2 ^ S = (P - 1) var q = this.m.subn(1); var s = 0; while (!q.isZero() && q.andln(1) === 0) { s++; q.iushrn(1); } assert(!q.isZero()); var one = new BN(1).toRed(this); var nOne = one.redNeg(); // Find quadratic non-residue // NOTE: Max is such because of generalized Riemann hypothesis. var lpow = this.m.subn(1).iushrn(1); var z = this.m.bitLength(); z = new BN(2 * z * z).toRed(this); while (this.pow(z, lpow).cmp(nOne) !== 0) { z.redIAdd(nOne); } var c = this.pow(z, q); var r = this.pow(a, q.addn(1).iushrn(1)); var t = this.pow(a, q); var m = s; while (t.cmp(one) !== 0) { var tmp = t; for (var i = 0; tmp.cmp(one) !== 0; i++) { tmp = tmp.redSqr(); } assert(i < m); var b = this.pow(c, new BN(1).iushln(m - i - 1)); r = r.redMul(b); c = b.redSqr(); t = t.redMul(c); m = i; } return r; }; Red.prototype.invm = function invm (a) { var inv = a._invmp(this.m); if (inv.negative !== 0) { inv.negative = 0; return this.imod(inv).redNeg(); } else { return this.imod(inv); } }; Red.prototype.pow = function pow (a, num) { if (num.isZero()) return new BN(1).toRed(this); if (num.cmpn(1) === 0) return a.clone(); var windowSize = 4; var wnd = new Array(1 << windowSize); wnd[0] = new BN(1).toRed(this); wnd[1] = a; for (var i = 2; i < wnd.length; i++) { wnd[i] = this.mul(wnd[i - 1], a); } var res = wnd[0]; var current = 0; var currentLen = 0; var start = num.bitLength() % 26; if (start === 0) { start = 26; } for (i = num.length - 1; i >= 0; i--) { var word = num.words[i]; for (var j = start - 1; j >= 0; j--) { var bit = (word >> j) & 1; if (res !== wnd[0]) { res = this.sqr(res); } if (bit === 0 && current === 0) { currentLen = 0; continue; } current <<= 1; current |= bit; currentLen++; if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; res = this.mul(res, wnd[current]); currentLen = 0; current = 0; } start = 26; } return res; }; Red.prototype.convertTo = function convertTo (num) { var r = num.umod(this.m); return r === num ? r.clone() : r; }; Red.prototype.convertFrom = function convertFrom (num) { var res = num.clone(); res.red = null; return res; }; // // Montgomery method engine // BN.mont = function mont (num) { return new Mont(num); }; function Mont (m) { Red.call(this, m); this.shift = this.m.bitLength(); if (this.shift % 26 !== 0) { this.shift += 26 - (this.shift % 26); } this.r = new BN(1).iushln(this.shift); this.r2 = this.imod(this.r.sqr()); this.rinv = this.r._invmp(this.m); this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); this.minv = this.minv.umod(this.r); this.minv = this.r.sub(this.minv); } inherits(Mont, Red); Mont.prototype.convertTo = function convertTo (num) { return this.imod(num.ushln(this.shift)); }; Mont.prototype.convertFrom = function convertFrom (num) { var r = this.imod(num.mul(this.rinv)); r.red = null; return r; }; Mont.prototype.imul = function imul (a, b) { if (a.isZero() || b.isZero()) { a.words[0] = 0; a.length = 1; return a; } var t = a.imul(b); var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); var u = t.isub(c).iushrn(this.shift); var res = u; if (u.cmp(this.m) >= 0) { res = u.isub(this.m); } else if (u.cmpn(0) < 0) { res = u.iadd(this.m); } return res._forceRed(this); }; Mont.prototype.mul = function mul (a, b) { if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); var t = a.mul(b); var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); var u = t.isub(c).iushrn(this.shift); var res = u; if (u.cmp(this.m) >= 0) { res = u.isub(this.m); } else if (u.cmpn(0) < 0) { res = u.iadd(this.m); } return res._forceRed(this); }; Mont.prototype.invm = function invm (a) { // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R var res = this.imod(a._invmp(this.m).mul(this.r2)); return res._forceRed(this); }; })(module, commonjsGlobal); } (bn)); var bnExports = bn.exports; var BN = /*@__PURE__*/getDefaultExportFromCjs(bnExports); var safeBuffer = {exports: {}}; /*! safe-buffer. MIT License. Feross Aboukhadijeh */ (function (module, exports) { /* eslint-disable node/no-deprecated-api */ var buffer$1 = buffer; var Buffer = buffer$1.Buffer; // alternative to using Object.keys for old browsers function copyProps (src, dst) { for (var key in src) { dst[key] = src[key]; } } if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { module.exports = buffer$1; } else { // Copy properties from require('buffer') copyProps(buffer$1, exports); exports.Buffer = SafeBuffer; } function SafeBuffer (arg, encodingOrOffset, length) { return Buffer(arg, encodingOrOffset, length) } SafeBuffer.prototype = Object.create(Buffer.prototype); // Copy static methods from Buffer copyProps(Buffer, SafeBuffer); SafeBuffer.from = function (arg, encodingOrOffset, length) { if (typeof arg === 'number') { throw new TypeError('Argument must not be a number') } return Buffer(arg, encodingOrOffset, length) }; SafeBuffer.alloc = function (size, fill, encoding) { if (typeof size !== 'number') { throw new TypeError('Argument must be a number') } var buf = Buffer(size); if (fill !== undefined) { if (typeof encoding === 'string') { buf.fill(fill, encoding); } else { buf.fill(fill); } } else { buf.fill(0); } return buf }; SafeBuffer.allocUnsafe = function (size) { if (typeof size !== 'number') { throw new TypeError('Argument must be a number') } return Buffer(size) }; SafeBuffer.allocUnsafeSlow = function (size) { if (typeof size !== 'number') { throw new TypeError('Argument must be a number') } return buffer$1.SlowBuffer(size) }; } (safeBuffer, safeBuffer.exports)); var safeBufferExports = safeBuffer.exports; // base-x encoding / decoding // Copyright (c) 2018 base-x contributors // Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp) // Distributed under the MIT software license, see the accompanying // file LICENSE or http://www.opensource.org/licenses/mit-license.php. // @ts-ignore var _Buffer = safeBufferExports.Buffer; function base (ALPHABET) { if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') } var BASE_MAP = new Uint8Array(256); for (var j = 0; j < BASE_MAP.length; j++) { BASE_MAP[j] = 255; } for (var i = 0; i < ALPHABET.length; i++) { var x = ALPHABET.charAt(i); var xc = x.charCodeAt(0); if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') } BASE_MAP[xc] = i; } var BASE = ALPHABET.length; var LEADER = ALPHABET.charAt(0); var FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up var iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up function encode (source) { if (Array.isArray(source) || source instanceof Uint8Array) { source = _Buffer.from(source); } if (!_Buffer.isBuffer(source)) { throw new TypeError('Expected Buffer') } if (source.length === 0) { return '' } // Skip & count leading zeroes. var zeroes = 0; var length = 0; var pbegin = 0; var pend = source.length; while (pbegin !== pend && source[pbegin] === 0) { pbegin++; zeroes++; } // Allocate enough space in big-endian base58 representation. var size = ((pend - pbegin) * iFACTOR + 1) >>> 0; var b58 = new Uint8Array(size); // Process the bytes. while (pbegin !== pend) { var carry = source[pbegin]; // Apply "b58 = b58 * 256 + ch". var i = 0; for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) { carry += (256 * b58[it1]) >>> 0; b58[it1] = (carry % BASE) >>> 0; carry = (carry / BASE) >>> 0; } if (carry !== 0) { throw new Error('Non-zero carry') } length = i; pbegin++; } // Skip leading zeroes in base58 result. var it2 = size - length; while (it2 !== size && b58[it2] === 0) { it2++; } // Translate the result into a string. var str = LEADER.repeat(zeroes); for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]); } return str } function decodeUnsafe (source) { if (typeof source !== 'string') { throw new TypeError('Expected String') } if (source.length === 0) { return _Buffer.alloc(0) } var psz = 0; // Skip and count leading '1's. var zeroes = 0; var length = 0; while (source[psz] === LEADER) { zeroes++; psz++; } // Allocate enough space in big-endian base256 representation. var size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up. var b256 = new Uint8Array(size); // Process the characters. while (source[psz]) { // Decode character var carry = BASE_MAP[source.charCodeAt(psz)]; // Invalid character if (carry === 255) { return } var i = 0; for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) { carry += (BASE * b256[it3]) >>> 0; b256[it3] = (carry % 256) >>> 0; carry = (carry / 256) >>> 0; } if (carry !== 0) { throw new Error('Non-zero carry') } length = i; psz++; } // Skip leading zeroes in b256. var it4 = size - length; while (it4 !== size && b256[it4] === 0) { it4++; } var vch = _Buffer.allocUnsafe(zeroes + (size - it4)); vch.fill(0x00, 0, zeroes); var j = zeroes; while (it4 !== size) { vch[j++] = b256[it4++]; } return vch } function decode (string) { var buffer = decodeUnsafe(string); if (buffer) { return buffer } throw new Error('Non-base' + BASE + ' character') } return { encode: encode, decodeUnsafe: decodeUnsafe, decode: decode } } var src = base; var basex = src; var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; var bs58 = basex(ALPHABET); var bs58$1 = /*@__PURE__*/getDefaultExportFromCjs(bs58); function number$1(n) { if (!Number.isSafeInteger(n) || n < 0) throw new Error(`Wrong positive integer: ${n}`); } // copied from utils function isBytes$1(a) { return (a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); } function bytes(b, ...lengths) { if (!isBytes$1(b)) throw new Error('Expected Uint8Array'); if (lengths.length > 0 && !lengths.includes(b.length)) throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`); } function exists(instance, checkFinished = true) { if (instance.destroyed) throw new Error('Hash instance has been destroyed'); if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called'); } function output(out, instance) { bytes(out); const min = instance.outputLen; if (out.length < min) { throw new Error(`digestInto() expects output buffer of length at least ${min}`); } } /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+. // node.js versions earlier than v19 don't declare it in global scope. // For node.js, package.json#exports field mapping rewrites import // from `crypto` to `cryptoNode`, which imports native module. // Makes the utils un-importable in browsers without a bundler. // Once node.js 18 is deprecated (2025-04-30), we can just drop the import. const u32$1 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); function isBytes(a) { return (a instanceof Uint8Array || (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')); } // Cast array to view const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength); // The rotate right (circular right shift) operation for uint32 const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift); // big-endian hardware is rare. Just in case someone still decides to run hashes: // early-throw an error because we don't support BE yet. // Other libraries would silently corrupt the data instead of throwing an error, // when they don't support it. const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44; if (!isLE) throw new Error('Non little-endian hardware is not supported'); /** * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) */ function utf8ToBytes(str) { if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`); return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 } /** * Normalizes (non-hex) string or Uint8Array to Uint8Array. * Warning: when Uint8Array is passed, it would NOT get copied. * Keep in mind for future mutable operations. */ function toBytes(data) { if (typeof data === 'string') data = utf8ToBytes(data); if (!isBytes(data)) throw new Error(`expected Uint8Array, got ${typeof data}`); return data; } // For runtime check if class implements interface class Hash { // Safe version that clones internal state clone() { return this._cloneInto(); } } function wrapConstructor(hashCons) { const hashC = (msg) => hashCons().update(toBytes(msg)).digest(); const tmp = hashCons(); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = () => hashCons(); return hashC; } // Polyfill for Safari 14 function setBigUint64(view, byteOffset, value, isLE) { if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE); const _32n = BigInt(32); const _u32_max = BigInt(0xffffffff); const wh = Number((value >> _32n) & _u32_max); const wl = Number(value & _u32_max); const h = isLE ? 4 : 0; const l = isLE ? 0 : 4; view.setUint32(byteOffset + h, wh, isLE); view.setUint32(byteOffset + l, wl, isLE); } // Base SHA2 class (RFC 6234) class SHA2 extends Hash { constructor(blockLen, outputLen, padOffset, isLE) { super(); this.blockLen = blockLen; this.outputLen = outputLen; this.padOffset = padOffset; this.isLE = isLE; this.finished = false; this.length = 0; this.pos = 0; this.destroyed = false; this.buffer = new Uint8Array(blockLen); this.view = createView(this.buffer); } update(data) { exists(this); const { view, buffer, blockLen } = this; data = toBytes(data); const len = data.length; for (let pos = 0; pos < len;) { const take = Math.min(blockLen - this.pos, len - pos); // Fast path: we have at least one block in input, cast it to view and process if (take === blockLen) { const dataView = createView(data); for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos); continue; } buffer.set(data.subarray(pos, pos + take), this.pos); this.pos += take; pos += take; if (this.pos === blockLen) { this.process(view, 0); this.pos = 0; } } this.length += data.length; this.roundClean(); return this; } digestInto(out) { exists(this); output(out, this); this.finished = true; // Padding // We can avoid allocation of buffer for padding completely if it // was previously not allocated here. But it won't change performance. const { buffer, view, blockLen, isLE } = this; let { pos } = this; // append the bit '1' to the message buffer[pos++] = 0b10000000; this.buffer.subarray(pos).fill(0); // we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again if (this.padOffset > blockLen - pos) { this.process(view, 0); pos = 0; } // Pad until full block byte with zeros for (let i = pos; i < blockLen; i++) buffer[i] = 0; // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen. // So we just write lowest 64 bits of that value. setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE); this.process(view, 0); const oview = createView(out); const len = this.outputLen; // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit'); const outLen = len / 4; const state = this.get(); if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state'); for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE); } digest() { const { buffer, outputLen } = this; this.digestInto(buffer); const res = buffer.slice(0, outputLen); this.destroy(); return res; } _cloneInto(to) { to || (to = new this.constructor()); to.set(...this.get()); const { blockLen, buffer, length, finished, destroyed, pos } = this; to.length = length; to.pos = pos; to.finished = finished; to.destroyed = destroyed; if (length % blockLen) to.buffer.set(buffer); return to; } } // SHA2-256 need to try 2^128 hashes to execute birthday attack. // BTC network is doing 2^67 hashes/sec as per early 2023. // Choice: a ? b : c const Chi = (a, b, c) => (a & b) ^ (~a & c); // Majority function, true if any two inpust is true const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c); // Round constants: // first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) // prettier-ignore const SHA256_K$1 = /* @__PURE__ */ new Uint32Array([ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]); // Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): // prettier-ignore const IV = /* @__PURE__ */ new Uint32Array([ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]); // Temporary buffer, not used to store anything between runs // Named this way because it matches specification. const SHA256_W$1 = /* @__PURE__ */ new Uint32Array(64); let SHA256$1 = class SHA256 extends SHA2 { constructor() { super(64, 32, 8, false); // We cannot use array here since array allows indexing by variable // which means optimizer/compiler cannot use registers. this.A = IV[0] | 0; this.B = IV[1] | 0; this.C = IV[2] | 0; this.D = IV[3] | 0; this.E = IV[4] | 0; this.F = IV[5] | 0; this.G = IV[6] | 0; this.H = IV[7] | 0; } get() { const { A, B, C, D, E, F, G, H } = this; return [A, B, C, D, E, F, G, H]; } // prettier-ignore set(A, B, C, D, E, F, G, H) { this.A = A | 0; this.B = B | 0; this.C = C | 0; this.D = D | 0; this.E = E | 0; this.F = F | 0; this.G = G | 0; this.H = H | 0; } process(view, offset) { // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array for (let i = 0; i < 16; i++, offset += 4) SHA256_W$1[i] = view.getUint32(offset, false); for (let i = 16; i < 64; i++) { const W15 = SHA256_W$1[i - 15]; const W2 = SHA256_W$1[i - 2]; const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3); const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10); SHA256_W$1[i] = (s1 + SHA256_W$1[i - 7] + s0 + SHA256_W$1[i - 16]) | 0; } // Compression function main loop, 64 rounds let { A, B, C, D, E, F, G, H } = this; for (let i = 0; i < 64; i++) { const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25); const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K$1[i] + SHA256_W$1[i]) | 0; const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22); const T2 = (sigma0 + Maj(A, B, C)) | 0; H = G; G = F; F = E; E = (D + T1) | 0; D = C; C = B; B = A; A = (T1 + T2) | 0; } // Add the compressed chunk to the current hash value A = (A + this.A) | 0; B = (B + this.B) | 0; C = (C + this.C) | 0; D = (D + this.D) | 0; E = (E + this.E) | 0; F = (F + this.F) | 0; G = (G + this.G) | 0; H = (H + this.H) | 0; this.set(A, B, C, D, E, F, G, H); } roundClean() { SHA256_W$1.fill(0); } destroy() { this.set(0, 0, 0, 0, 0, 0, 0, 0); this.buffer.fill(0); } }; /** * SHA2-256 hash function * @param message - data that would be hashed */ const sha256$1 = /* @__PURE__ */ wrapConstructor(() => new SHA256$1()); var lib = {}; var encoding_lib = {}; // This is free and unencumbered software released into the public domain. // See LICENSE.md for more information. // // Utilities // /** * @param {number} a The number to test. * @param {number} min The minimum value in the range, inclusive. * @param {number} max The maximum value in the range, inclusive. * @return {boolean} True if a >= min and a <= max. */ function inRange(a, min, max) { return min <= a && a <= max; } /** * @param {*} o * @return {Object} */ function ToDictionary(o) { if (o === undefined) return {}; if (o === Object(o)) return o; throw TypeError('Could not convert argument to dictionary'); } /** * @param {string} string Input string of UTF-16 code units. * @return {!Array.} Code points. */ function stringToCodePoints(string) { // https://heycam.github.io/webidl/#dfn-obtain-unicode // 1. Let S be the DOMString value. var s = String(string); // 2. Let n be the length of S. var n = s.length; // 3. Initialize i to 0. var i = 0; // 4. Initialize U to be an empty sequence of Unicode characters. var u = []; // 5. While i < n: while (i < n) { // 1. Let c be the code unit in S at index i. var c = s.charCodeAt(i); // 2. Depending on the value of c: // c < 0xD800 or c > 0xDFFF if (c < 0xD800 || c > 0xDFFF) { // Append to U the Unicode character with code point c. u.push(c); } // 0xDC00 ≤ c ≤ 0xDFFF else if (0xDC00 <= c && c <= 0xDFFF) { // Append to U a U+FFFD REPLACEMENT CHARACTER. u.push(0xFFFD); } // 0xD800 ≤ c ≤ 0xDBFF else if (0xD800 <= c && c <= 0xDBFF) { // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT // CHARACTER. if (i === n - 1) { u.push(0xFFFD); } // 2. Otherwise, i < n−1: else { // 1. Let d be the code unit in S at index i+1. var d = string.charCodeAt(i + 1); // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: if (0xDC00 <= d && d <= 0xDFFF) { // 1. Let a be c & 0x3FF. var a = c & 0x3FF; // 2. Let b be d & 0x3FF. var b = d & 0x3FF; // 3. Append to U the Unicode character with code point // 2^16+2^10*a+b. u.push(0x10000 + (a << 10) + b); // 4. Set i to i+1. i += 1; } // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a // U+FFFD REPLACEMENT CHARACTER. else { u.push(0xFFFD); } } } // 3. Set i to i+1. i += 1; } // 6. Return U. return u; } /** * @param {!Array.} code_points Array of code points. * @return {string} string String of UTF-16 code units. */ function codePointsToString(code_points) { var s = ''; for (var i = 0; i < code_points.length; ++i) { var cp = code_points[i]; if (cp <= 0xFFFF) { s += String.fromCharCode(cp); } else { cp -= 0x10000; s += String.fromCharCode((cp >> 10) + 0xD800, (cp & 0x3FF) + 0xDC00); } } return s; } // // Implementation of Encoding specification // https://encoding.spec.whatwg.org/ // // // 3. Terminology // /** * End-of-stream is a special token that signifies no more tokens * are in the stream. * @const */ var end_of_stream = -1; /** * A stream represents an ordered sequence of tokens. * * @constructor * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide the * stream. */ function Stream(tokens) { /** @type {!Array.} */ this.tokens = [].slice.call(tokens); } Stream.prototype = { /** * @return {boolean} True if end-of-stream has been hit. */ endOfStream: function() { return !this.tokens.length; }, /** * When a token is read from a stream, the first token in the * stream must be returned and subsequently removed, and * end-of-stream must be returned otherwise. * * @return {number} Get the next token from the stream, or * end_of_stream. */ read: function() { if (!this.tokens.length) return end_of_stream; return this.tokens.shift(); }, /** * When one or more tokens are prepended to a stream, those tokens * must be inserted, in given order, before the first token in the * stream. * * @param {(number|!Array.)} token The token(s) to prepend to the stream. */ prepend: function(token) { if (Array.isArray(token)) { var tokens = /**@type {!Array.}*/(token); while (tokens.length) this.tokens.unshift(tokens.pop()); } else { this.tokens.unshift(token); } }, /** * When one or more tokens are pushed to a stream, those tokens * must be inserted, in given order, after the last token in the * stream. * * @param {(number|!Array.)} token The tokens(s) to prepend to the stream. */ push: function(token) { if (Array.isArray(token)) { var tokens = /**@type {!Array.}*/(token); while (tokens.length) this.tokens.push(tokens.shift()); } else { this.tokens.push(token); } } }; // // 4. Encodings // // 4.1 Encoders and decoders /** @const */ var finished = -1; /** * @param {boolean} fatal If true, decoding errors raise an exception. * @param {number=} opt_code_point Override the standard fallback code point. * @return {number} The code point to insert on a decoding error. */ function decoderError(fatal, opt_code_point) { if (fatal) throw TypeError('Decoder error'); return opt_code_point || 0xFFFD; } // // 7. API // /** @const */ var DEFAULT_ENCODING = 'utf-8'; // 7.1 Interface TextDecoder /** * @constructor * @param {string=} encoding The label of the encoding; * defaults to 'utf-8'. * @param {Object=} options */ function TextDecoder$1(encoding, options) { if (!(this instanceof TextDecoder$1)) { return new TextDecoder$1(encoding, options); } encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; if (encoding !== DEFAULT_ENCODING) { throw new Error('Encoding not supported. Only utf-8 is supported'); } options = ToDictionary(options); /** @private @type {boolean} */ this._streaming = false; /** @private @type {boolean} */ this._BOMseen = false; /** @private @type {?Decoder} */ this._decoder = null; /** @private @type {boolean} */ this._fatal = Boolean(options['fatal']); /** @private @type {boolean} */ this._ignoreBOM = Boolean(options['ignoreBOM']); Object.defineProperty(this, 'encoding', {value: 'utf-8'}); Object.defineProperty(this, 'fatal', {value: this._fatal}); Object.defineProperty(this, 'ignoreBOM', {value: this._ignoreBOM}); } TextDecoder$1.prototype = { /** * @param {ArrayBufferView=} input The buffer of bytes to decode. * @param {Object=} options * @return {string} The decoded string. */ decode: function decode(input, options) { var bytes; if (typeof input === 'object' && input instanceof ArrayBuffer) { bytes = new Uint8Array(input); } else if (typeof input === 'object' && 'buffer' in input && input.buffer instanceof ArrayBuffer) { bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength); } else { bytes = new Uint8Array(0); } options = ToDictionary(options); if (!this._streaming) { this._decoder = new UTF8Decoder({fatal: this._fatal}); this._BOMseen = false; } this._streaming = Boolean(options['stream']); var input_stream = new Stream(bytes); var code_points = []; /** @type {?(number|!Array.)} */ var result; while (!input_stream.endOfStream()) { result = this._decoder.handler(input_stream, input_stream.read()); if (result === finished) break; if (result === null) continue; if (Array.isArray(result)) code_points.push.apply(code_points, /**@type {!Array.}*/(result)); else code_points.push(result); } if (!this._streaming) { do { result = this._decoder.handler(input_stream, input_stream.read()); if (result === finished) break; if (result === null) continue; if (Array.isArray(result)) code_points.push.apply(code_points, /**@type {!Array.}*/(result)); else code_points.push(result); } while (!input_stream.endOfStream()); this._decoder = null; } if (code_points.length) { // If encoding is one of utf-8, utf-16be, and utf-16le, and // ignore BOM flag and BOM seen flag are unset, run these // subsubsteps: if (['utf-8'].indexOf(this.encoding) !== -1 && !this._ignoreBOM && !this._BOMseen) { // If token is U+FEFF, set BOM seen flag. if (code_points[0] === 0xFEFF) { this._BOMseen = true; code_points.shift(); } else { // Otherwise, if token is not end-of-stream, set BOM seen // flag and append token to output. this._BOMseen = true; } } } return codePointsToString(code_points); } }; // 7.2 Interface TextEncoder /** * @constructor * @param {string=} encoding The label of the encoding; * defaults to 'utf-8'. * @param {Object=} options */ function TextEncoder$1(encoding, options) { if (!(this instanceof TextEncoder$1)) return new TextEncoder$1(encoding, options); encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; if (encoding !== DEFAULT_ENCODING) { throw new Error('Encoding not supported. Only utf-8 is supported'); } options = ToDictionary(options); /** @private @type {boolean} */ this._streaming = false; /** @private @type {?Encoder} */ this._encoder = null; /** @private @type {{fatal: boolean}} */ this._options = {fatal: Boolean(options['fatal'])}; Object.defineProperty(this, 'encoding', {value: 'utf-8'}); } TextEncoder$1.prototype = { /** * @param {string=} opt_string The string to encode. * @param {Object=} options * @return {Uint8Array} Encoded bytes, as a Uint8Array. */ encode: function encode(opt_string, options) { opt_string = opt_string ? String(opt_string) : ''; options = ToDictionary(options); // NOTE: This option is nonstandard. None of the encodings // permitted for encoding (i.e. UTF-8, UTF-16) are stateful, // so streaming is not necessary. if (!this._streaming) this._encoder = new UTF8Encoder(this._options); this._streaming = Boolean(options['stream']); var bytes = []; var input_stream = new Stream(stringToCodePoints(opt_string)); /** @type {?(number|!Array.)} */ var result; while (!input_stream.endOfStream()) { result = this._encoder.handler(input_stream, input_stream.read()); if (result === finished) break; if (Array.isArray(result)) bytes.push.apply(bytes, /**@type {!Array.}*/(result)); else bytes.push(result); } if (!this._streaming) { while (true) { result = this._encoder.handler(input_stream, input_stream.read()); if (result === finished) break; if (Array.isArray(result)) bytes.push.apply(bytes, /**@type {!Array.}*/(result)); else bytes.push(result); } this._encoder = null; } return new Uint8Array(bytes); } }; // // 8. The encoding // // 8.1 utf-8 /** * @constructor * @implements {Decoder} * @param {{fatal: boolean}} options */ function UTF8Decoder(options) { var fatal = options.fatal; // utf-8's decoder's has an associated utf-8 code point, utf-8 // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 // lower boundary (initially 0x80), and a utf-8 upper boundary // (initially 0xBF). var /** @type {number} */ utf8_code_point = 0, /** @type {number} */ utf8_bytes_seen = 0, /** @type {number} */ utf8_bytes_needed = 0, /** @type {number} */ utf8_lower_boundary = 0x80, /** @type {number} */ utf8_upper_boundary = 0xBF; /** * @param {Stream} stream The stream of bytes being decoded. * @param {number} bite The next byte read from the stream. * @return {?(number|!Array.)} The next code point(s) * decoded, or null if not enough data exists in the input * stream to decode a complete code point. */ this.handler = function(stream, bite) { // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, // set utf-8 bytes needed to 0 and return error. if (bite === end_of_stream && utf8_bytes_needed !== 0) { utf8_bytes_needed = 0; return decoderError(fatal); } // 2. If byte is end-of-stream, return finished. if (bite === end_of_stream) return finished; // 3. If utf-8 bytes needed is 0, based on byte: if (utf8_bytes_needed === 0) { // 0x00 to 0x7F if (inRange(bite, 0x00, 0x7F)) { // Return a code point whose value is byte. return bite; } // 0xC2 to 0xDF if (inRange(bite, 0xC2, 0xDF)) { // Set utf-8 bytes needed to 1 and utf-8 code point to byte // − 0xC0. utf8_bytes_needed = 1; utf8_code_point = bite - 0xC0; } // 0xE0 to 0xEF else if (inRange(bite, 0xE0, 0xEF)) { // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. if (bite === 0xE0) utf8_lower_boundary = 0xA0; // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. if (bite === 0xED) utf8_upper_boundary = 0x9F; // 3. Set utf-8 bytes needed to 2 and utf-8 code point to // byte − 0xE0. utf8_bytes_needed = 2; utf8_code_point = bite - 0xE0; } // 0xF0 to 0xF4 else if (inRange(bite, 0xF0, 0xF4)) { // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. if (bite === 0xF0) utf8_lower_boundary = 0x90; // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. if (bite === 0xF4) utf8_upper_boundary = 0x8F; // 3. Set utf-8 bytes needed to 3 and utf-8 code point to // byte − 0xF0. utf8_bytes_needed = 3; utf8_code_point = bite - 0xF0; } // Otherwise else { // Return error. return decoderError(fatal); } // Then (byte is in the range 0xC2 to 0xF4) set utf-8 code // point to utf-8 code point << (6 × utf-8 bytes needed) and // return continue. utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed); return null; } // 4. If byte is not in the range utf-8 lower boundary to utf-8 // upper boundary, run these substeps: if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 // bytes seen to 0, set utf-8 lower boundary to 0x80, and set // utf-8 upper boundary to 0xBF. utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; utf8_lower_boundary = 0x80; utf8_upper_boundary = 0xBF; // 2. Prepend byte to stream. stream.prepend(bite); // 3. Return error. return decoderError(fatal); } // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary // to 0xBF. utf8_lower_boundary = 0x80; utf8_upper_boundary = 0xBF; // 6. Increase utf-8 bytes seen by one and set utf-8 code point // to utf-8 code point + (byte − 0x80) << (6 × (utf-8 bytes // needed − utf-8 bytes seen)). utf8_bytes_seen += 1; utf8_code_point += (bite - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen)); // 7. If utf-8 bytes seen is not equal to utf-8 bytes needed, // continue. if (utf8_bytes_seen !== utf8_bytes_needed) return null; // 8. Let code point be utf-8 code point. var code_point = utf8_code_point; // 9. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes // seen to 0. utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; // 10. Return a code point whose value is code point. return code_point; }; } /** * @constructor * @implements {Encoder} * @param {{fatal: boolean}} options */ function UTF8Encoder(options) { options.fatal; /** * @param {Stream} stream Input stream. * @param {number} code_point Next code point read from the stream. * @return {(number|!Array.)} Byte(s) to emit. */ this.handler = function(stream, code_point) { // 1. If code point is end-of-stream, return finished. if (code_point === end_of_stream) return finished; // 2. If code point is in the range U+0000 to U+007F, return a // byte whose value is code point. if (inRange(code_point, 0x0000, 0x007f)) return code_point; // 3. Set count and offset based on the range code point is in: var count, offset; // U+0080 to U+07FF: 1 and 0xC0 if (inRange(code_point, 0x0080, 0x07FF)) { count = 1; offset = 0xC0; } // U+0800 to U+FFFF: 2 and 0xE0 else if (inRange(code_point, 0x0800, 0xFFFF)) { count = 2; offset = 0xE0; } // U+10000 to U+10FFFF: 3 and 0xF0 else if (inRange(code_point, 0x10000, 0x10FFFF)) { count = 3; offset = 0xF0; } // 4.Let bytes be a byte sequence whose first byte is (code // point >> (6 × count)) + offset. var bytes = [(code_point >> (6 * count)) + offset]; // 5. Run these substeps while count is greater than 0: while (count > 0) { // 1. Set temp to code point >> (6 × (count − 1)). var temp = code_point >> (6 * (count - 1)); // 2. Append to bytes 0x80 | (temp & 0x3F). bytes.push(0x80 | (temp & 0x3F)); // 3. Decrease count by one. count -= 1; } // 6. Return bytes bytes, in order. return bytes; }; } encoding_lib.TextEncoder = TextEncoder$1; encoding_lib.TextDecoder = TextDecoder$1; var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (commonjsGlobal && commonjsGlobal.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(lib, "__esModule", { value: true }); var deserializeUnchecked_1 = lib.deserializeUnchecked = deserialize_1 = lib.deserialize = serialize_1 = lib.serialize = lib.BinaryReader = lib.BinaryWriter = lib.BorshError = lib.baseDecode = lib.baseEncode = void 0; const bn_js_1 = __importDefault(bnExports); const bs58_1 = __importDefault(bs58); // TODO: Make sure this polyfill not included when not required const encoding = __importStar(encoding_lib); const ResolvedTextDecoder = typeof TextDecoder !== "function" ? encoding.TextDecoder : TextDecoder; const textDecoder = new ResolvedTextDecoder("utf-8", { fatal: true }); function baseEncode(value) { if (typeof value === "string") { value = Buffer.from(value, "utf8"); } return bs58_1.default.encode(Buffer.from(value)); } lib.baseEncode = baseEncode; function baseDecode(value) { return Buffer.from(bs58_1.default.decode(value)); } lib.baseDecode = baseDecode; const INITIAL_LENGTH = 1024; class BorshError extends Error { constructor(message) { super(message); this.fieldPath = []; this.originalMessage = message; } addToFieldPath(fieldName) { this.fieldPath.splice(0, 0, fieldName); // NOTE: Modifying message directly as jest doesn't use .toString() this.message = this.originalMessage + ": " + this.fieldPath.join("."); } } lib.BorshError = BorshError; /// Binary encoder. class BinaryWriter { constructor() { this.buf = Buffer.alloc(INITIAL_LENGTH); this.length = 0; } maybeResize() { if (this.buf.length < 16 + this.length) { this.buf = Buffer.concat([this.buf, Buffer.alloc(INITIAL_LENGTH)]); } } writeU8(value) { this.maybeResize(); this.buf.writeUInt8(value, this.length); this.length += 1; } writeU16(value) { this.maybeResize(); this.buf.writeUInt16LE(value, this.length); this.length += 2; } writeU32(value) { this.maybeResize(); this.buf.writeUInt32LE(value, this.length); this.length += 4; } writeU64(value) { this.maybeResize(); this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 8))); } writeU128(value) { this.maybeResize(); this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 16))); } writeU256(value) { this.maybeResize(); this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 32))); } writeU512(value) { this.maybeResize(); this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 64))); } writeBuffer(buffer) { // Buffer.from is needed as this.buf.subarray can return plain Uint8Array in browser this.buf = Buffer.concat([ Buffer.from(this.buf.subarray(0, this.length)), buffer, Buffer.alloc(INITIAL_LENGTH), ]); this.length += buffer.length; } writeString(str) { this.maybeResize(); const b = Buffer.from(str, "utf8"); this.writeU32(b.length); this.writeBuffer(b); } writeFixedArray(array) { this.writeBuffer(Buffer.from(array)); } writeArray(array, fn) { this.maybeResize(); this.writeU32(array.length); for (const elem of array) { this.maybeResize(); fn(elem); } } toArray() { return this.buf.subarray(0, this.length); } } lib.BinaryWriter = BinaryWriter; function handlingRangeError(target, propertyKey, propertyDescriptor) { const originalMethod = propertyDescriptor.value; propertyDescriptor.value = function (...args) { try { return originalMethod.apply(this, args); } catch (e) { if (e instanceof RangeError) { const code = e.code; if (["ERR_BUFFER_OUT_OF_BOUNDS", "ERR_OUT_OF_RANGE"].indexOf(code) >= 0) { throw new BorshError("Reached the end of buffer when deserializing"); } } throw e; } }; } class BinaryReader { constructor(buf) { this.buf = buf; this.offset = 0; } readU8() { const value = this.buf.readUInt8(this.offset); this.offset += 1; return value; } readU16() { const value = this.buf.readUInt16LE(this.offset); this.offset += 2; return value; } readU32() { const value = this.buf.readUInt32LE(this.offset); this.offset += 4; return value; } readU64() { const buf = this.readBuffer(8); return new bn_js_1.default(buf, "le"); } readU128() { const buf = this.readBuffer(16); return new bn_js_1.default(buf, "le"); } readU256() { const buf = this.readBuffer(32); return new bn_js_1.default(buf, "le"); } readU512() { const buf = this.readBuffer(64); return new bn_js_1.default(buf, "le"); } readBuffer(len) { if (this.offset + len > this.buf.length) { throw new BorshError(`Expected buffer length ${len} isn't within bounds`); } const result = this.buf.slice(this.offset, this.offset + len); this.offset += len; return result; } readString() { const len = this.readU32(); const buf = this.readBuffer(len); try { // NOTE: Using TextDecoder to fail on invalid UTF-8 return textDecoder.decode(buf); } catch (e) { throw new BorshError(`Error decoding UTF-8 string: ${e}`); } } readFixedArray(len) { return new Uint8Array(this.readBuffer(len)); } readArray(fn) { const len = this.readU32(); const result = Array(); for (let i = 0; i < len; ++i) { result.push(fn()); } return result; } } __decorate([ handlingRangeError ], BinaryReader.prototype, "readU8", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU16", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU32", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU64", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU128", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU256", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readU512", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readString", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readFixedArray", null); __decorate([ handlingRangeError ], BinaryReader.prototype, "readArray", null); lib.BinaryReader = BinaryReader; function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function serializeField(schema, fieldName, value, fieldType, writer) { try { // TODO: Handle missing values properly (make sure they never result in just skipped write) if (typeof fieldType === "string") { writer[`write${capitalizeFirstLetter(fieldType)}`](value); } else if (fieldType instanceof Array) { if (typeof fieldType[0] === "number") { if (value.length !== fieldType[0]) { throw new BorshError(`Expecting byte array of length ${fieldType[0]}, but got ${value.length} bytes`); } writer.writeFixedArray(value); } else if (fieldType.length === 2 && typeof fieldType[1] === "number") { if (value.length !== fieldType[1]) { throw new BorshError(`Expecting byte array of length ${fieldType[1]}, but got ${value.length} bytes`); } for (let i = 0; i < fieldType[1]; i++) { serializeField(schema, null, value[i], fieldType[0], writer); } } else { writer.writeArray(value, (item) => { serializeField(schema, fieldName, item, fieldType[0], writer); }); } } else if (fieldType.kind !== undefined) { switch (fieldType.kind) { case "option": { if (value === null || value === undefined) { writer.writeU8(0); } else { writer.writeU8(1); serializeField(schema, fieldName, value, fieldType.type, writer); } break; } case "map": { writer.writeU32(value.size); value.forEach((val, key) => { serializeField(schema, fieldName, key, fieldType.key, writer); serializeField(schema, fieldName, val, fieldType.value, writer); }); break; } default: throw new BorshError(`FieldType ${fieldType} unrecognized`); } } else { serializeStruct(schema, value, writer); } } catch (error) { if (error instanceof BorshError) { error.addToFieldPath(fieldName); } throw error; } } function serializeStruct(schema, obj, writer) { if (typeof obj.borshSerialize === "function") { obj.borshSerialize(writer); return; } const structSchema = schema.get(obj.constructor); if (!structSchema) { throw new BorshError(`Class ${obj.constructor.name} is missing in schema`); } if (structSchema.kind === "struct") { structSchema.fields.map(([fieldName, fieldType]) => { serializeField(schema, fieldName, obj[fieldName], fieldType, writer); }); } else if (structSchema.kind === "enum") { const name = obj[structSchema.field]; for (let idx = 0; idx < structSchema.values.length; ++idx) { const [fieldName, fieldType] = structSchema.values[idx]; if (fieldName === name) { writer.writeU8(idx); serializeField(schema, fieldName, obj[fieldName], fieldType, writer); break; } } } else { throw new BorshError(`Unexpected schema kind: ${structSchema.kind} for ${obj.constructor.name}`); } } /// Serialize given object using schema of the form: /// { class_name -> [ [field_name, field_type], .. ], .. } function serialize(schema, obj, Writer = BinaryWriter) { const writer = new Writer(); serializeStruct(schema, obj, writer); return writer.toArray(); } var serialize_1 = lib.serialize = serialize; function deserializeField(schema, fieldName, fieldType, reader) { try { if (typeof fieldType === "string") { return reader[`read${capitalizeFirstLetter(fieldType)}`](); } if (fieldType instanceof Array) { if (typeof fieldType[0] === "number") { return reader.readFixedArray(fieldType[0]); } else if (typeof fieldType[1] === "number") { const arr = []; for (let i = 0; i < fieldType[1]; i++) { arr.push(deserializeField(schema, null, fieldType[0], reader)); } return arr; } else { return reader.readArray(() => deserializeField(schema, fieldName, fieldType[0], reader)); } } if (fieldType.kind === "option") { const option = reader.readU8(); if (option) { return deserializeField(schema, fieldName, fieldType.type, reader); } return undefined; } if (fieldType.kind === "map") { let map = new Map(); const length = reader.readU32(); for (let i = 0; i < length; i++) { const key = deserializeField(schema, fieldName, fieldType.key, reader); const val = deserializeField(schema, fieldName, fieldType.value, reader); map.set(key, val); } return map; } return deserializeStruct(schema, fieldType, reader); } catch (error) { if (error instanceof BorshError) { error.addToFieldPath(fieldName); } throw error; } } function deserializeStruct(schema, classType, reader) { if (typeof classType.borshDeserialize === "function") { return classType.borshDeserialize(reader); } const structSchema = schema.get(classType); if (!structSchema) { throw new BorshError(`Class ${classType.name} is missing in schema`); } if (structSchema.kind === "struct") { const result = {}; for (const [fieldName, fieldType] of schema.get(classType).fields) { result[fieldName] = deserializeField(schema, fieldName, fieldType, reader); } return new classType(result); } if (structSchema.kind === "enum") { const idx = reader.readU8(); if (idx >= structSchema.values.length) { throw new BorshError(`Enum index: ${idx} is out of range`); } const [fieldName, fieldType] = structSchema.values[idx]; const fieldValue = deserializeField(schema, fieldName, fieldType, reader); return new classType({ [fieldName]: fieldValue }); } throw new BorshError(`Unexpected schema kind: ${structSchema.kind} for ${classType.constructor.name}`); } /// Deserializes object from bytes using schema. function deserialize(schema, classType, buffer, Reader = BinaryReader) { const reader = new Reader(buffer); const result = deserializeStruct(schema, classType, reader); if (reader.offset < buffer.length) { throw new BorshError(`Unexpected ${buffer.length - reader.offset} bytes after deserialized data`); } return result; } var deserialize_1 = lib.deserialize = deserialize; /// Deserializes object from bytes using schema, without checking the length read function deserializeUnchecked(schema, classType, buffer, Reader = BinaryReader) { const reader = new Reader(buffer); return deserializeStruct(schema, classType, reader); } deserializeUnchecked_1 = lib.deserializeUnchecked = deserializeUnchecked; // Class wrapping a plain object let Struct$1 = class Struct { constructor(properties) { Object.assign(this, properties); } encode() { return buffer.Buffer.from(serialize_1(SOLANA_SCHEMA, this)); } static decode(data) { return deserialize_1(SOLANA_SCHEMA, this, data); } static decodeUnchecked(data) { return deserializeUnchecked_1(SOLANA_SCHEMA, this, data); } }; // Class representing a Rust-compatible enum, since enums are only strings or // numbers in pure JS class Enum extends Struct$1 { constructor(properties) { super(properties); this.enum = ''; if (Object.keys(properties).length !== 1) { throw new Error('Enum can only take single value'); } Object.keys(properties).map(key => { this.enum = key; }); } } const SOLANA_SCHEMA = new Map(); var _class; let _Symbol$toStringTag; /** * Maximum length of derived pubkey seed */ const MAX_SEED_LENGTH = 32; /** * Size of public key in bytes */ const PUBLIC_KEY_LENGTH = 32; /** * Value to be converted into public key */ /** * JSON object representation of PublicKey class */ function isPublicKeyData(value) { return value._bn !== undefined; } // local counter used by PublicKey.unique() let uniquePublicKeyCounter = 1; /** * A public key */ _Symbol$toStringTag = Symbol.toStringTag; class PublicKey extends Struct$1 { /** * Create a new PublicKey object * @param value ed25519 public key as buffer or base-58 encoded string */ constructor(value) { super({}); /** @internal */ this._bn = void 0; if (isPublicKeyData(value)) { this._bn = value._bn; } else { if (typeof value === 'string') { // assume base 58 encoding by default const decoded = bs58$1.decode(value); if (decoded.length != PUBLIC_KEY_LENGTH) { throw new Error(`Invalid public key input`); } this._bn = new BN(decoded); } else { this._bn = new BN(value); } if (this._bn.byteLength() > PUBLIC_KEY_LENGTH) { throw new Error(`Invalid public key input`); } } } /** * Returns a unique PublicKey for tests and benchmarks using a counter */ static unique() { const key = new PublicKey(uniquePublicKeyCounter); uniquePublicKeyCounter += 1; return new PublicKey(key.toBuffer()); } /** * Default public key value. The base58-encoded string representation is all ones (as seen below) * The underlying BN number is 32 bytes that are all zeros */ /** * Checks if two publicKeys are equal */ equals(publicKey) { return this._bn.eq(publicKey._bn); } /** * Return the base-58 representation of the public key */ toBase58() { return bs58$1.encode(this.toBytes()); } toJSON() { return this.toBase58(); } /** * Return the byte array representation of the public key in big endian */ toBytes() { const buf = this.toBuffer(); return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); } /** * Return the Buffer representation of the public key in big endian */ toBuffer() { const b = this._bn.toArrayLike(buffer.Buffer); if (b.length === PUBLIC_KEY_LENGTH) { return b; } const zeroPad = buffer.Buffer.alloc(32); b.copy(zeroPad, 32 - b.length); return zeroPad; } get [_Symbol$toStringTag]() { return `PublicKey(${this.toString()})`; } /** * Return the base-58 representation of the public key */ toString() { return this.toBase58(); } /** * Derive a public key from another key, a seed, and a program ID. * The program ID will also serve as the owner of the public key, giving * it permission to write data to the account. */ /* eslint-disable require-await */ static async createWithSeed(fromPublicKey, seed, programId) { const buffer$1 = buffer.Buffer.concat([fromPublicKey.toBuffer(), buffer.Buffer.from(seed), programId.toBuffer()]); const publicKeyBytes = sha256$1(buffer$1); return new PublicKey(publicKeyBytes); } /** * Derive a program address from seeds and a program ID. */ /* eslint-disable require-await */ static createProgramAddressSync(seeds, programId) { let buffer$1 = buffer.Buffer.alloc(0); seeds.forEach(function (seed) { if (seed.length > MAX_SEED_LENGTH) { throw new TypeError(`Max seed length exceeded`); } buffer$1 = buffer.Buffer.concat([buffer$1, toBuffer(seed)]); }); buffer$1 = buffer.Buffer.concat([buffer$1, programId.toBuffer(), buffer.Buffer.from('ProgramDerivedAddress')]); const publicKeyBytes = sha256$1(buffer$1); if (isOnCurve(publicKeyBytes)) { throw new Error(`Invalid seeds, address must fall off the curve`); } return new PublicKey(publicKeyBytes); } /** * Async version of createProgramAddressSync * For backwards compatibility * * @deprecated Use {@link createProgramAddressSync} instead */ /* eslint-disable require-await */ static async createProgramAddress(seeds, programId) { return this.createProgramAddressSync(seeds, programId); } /** * Find a valid program address * * Valid program addresses must fall off the ed25519 curve. This function * iterates a nonce until it finds one that when combined with the seeds * results in a valid program address. */ static findProgramAddressSync(seeds, programId) { let nonce = 255; let address; while (nonce != 0) { try { const seedsWithNonce = seeds.concat(buffer.Buffer.from([nonce])); address = this.createProgramAddressSync(seedsWithNonce, programId); } catch (err) { if (err instanceof TypeError) { throw err; } nonce--; continue; } return [address, nonce]; } throw new Error(`Unable to find a viable program address nonce`); } /** * Async version of findProgramAddressSync * For backwards compatibility * * @deprecated Use {@link findProgramAddressSync} instead */ static async findProgramAddress(seeds, programId) { return this.findProgramAddressSync(seeds, programId); } /** * Check that a pubkey is on the ed25519 curve. */ static isOnCurve(pubkeyData) { const pubkey = new PublicKey(pubkeyData); return isOnCurve(pubkey.toBytes()); } } _class = PublicKey; PublicKey.default = new _class('11111111111111111111111111111111'); SOLANA_SCHEMA.set(PublicKey, { kind: 'struct', fields: [['_bn', 'u256']] }); /** * An account key pair (public and secret keys). * * @deprecated since v1.10.0, please use {@link Keypair} instead. */ class Account { /** * Create a new Account object * * If the secretKey parameter is not provided a new key pair is randomly * created for the account * * @param secretKey Secret key for the account */ constructor(secretKey) { /** @internal */ this._publicKey = void 0; /** @internal */ this._secretKey = void 0; if (secretKey) { const secretKeyBuffer = toBuffer(secretKey); if (secretKey.length !== 64) { throw new Error('bad secret key size'); } this._publicKey = secretKeyBuffer.slice(32, 64); this._secretKey = secretKeyBuffer.slice(0, 32); } else { this._secretKey = toBuffer(generatePrivateKey()); this._publicKey = toBuffer(getPublicKey(this._secretKey)); } } /** * The public key for this account */ get publicKey() { return new PublicKey(this._publicKey); } /** * The **unencrypted** secret key for this account. The first 32 bytes * is the private scalar and the last 32 bytes is the public key. * Read more: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ */ get secretKey() { return buffer.Buffer.concat([this._secretKey, this._publicKey], 64); } } const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader1111111111111111111111111111111111'); var Layout$1 = {}; /* The MIT License (MIT) * * Copyright 2015-2018 Peter A. Bigot * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ Object.defineProperty(Layout$1, "__esModule", { value: true }); Layout$1.s16 = Layout$1.s8 = Layout$1.nu64be = Layout$1.u48be = Layout$1.u40be = Layout$1.u32be = Layout$1.u24be = Layout$1.u16be = nu64 = Layout$1.nu64 = Layout$1.u48 = Layout$1.u40 = u32 = Layout$1.u32 = Layout$1.u24 = u16 = Layout$1.u16 = u8 = Layout$1.u8 = offset = Layout$1.offset = Layout$1.greedy = Layout$1.Constant = Layout$1.UTF8 = Layout$1.CString = Layout$1.Blob = Layout$1.Boolean = Layout$1.BitField = Layout$1.BitStructure = Layout$1.VariantLayout = Layout$1.Union = Layout$1.UnionLayoutDiscriminator = Layout$1.UnionDiscriminator = Layout$1.Structure = Layout$1.Sequence = Layout$1.DoubleBE = Layout$1.Double = Layout$1.FloatBE = Layout$1.Float = Layout$1.NearInt64BE = Layout$1.NearInt64 = Layout$1.NearUInt64BE = Layout$1.NearUInt64 = Layout$1.IntBE = Layout$1.Int = Layout$1.UIntBE = Layout$1.UInt = Layout$1.OffsetLayout = Layout$1.GreedyCount = Layout$1.ExternalLayout = Layout$1.bindConstructorLayout = Layout$1.nameWithProperty = Layout$1.Layout = Layout$1.uint8ArrayToBuffer = Layout$1.checkUint8Array = void 0; Layout$1.constant = Layout$1.utf8 = Layout$1.cstr = blob = Layout$1.blob = Layout$1.unionLayoutDiscriminator = Layout$1.union = seq = Layout$1.seq = Layout$1.bits = struct = Layout$1.struct = Layout$1.f64be = Layout$1.f64 = Layout$1.f32be = Layout$1.f32 = Layout$1.ns64be = Layout$1.s48be = Layout$1.s40be = Layout$1.s32be = Layout$1.s24be = Layout$1.s16be = ns64 = Layout$1.ns64 = Layout$1.s48 = Layout$1.s40 = Layout$1.s32 = Layout$1.s24 = void 0; const buffer_1 = buffer; /* Check if a value is a Uint8Array. * * @ignore */ function checkUint8Array(b) { if (!(b instanceof Uint8Array)) { throw new TypeError('b must be a Uint8Array'); } } Layout$1.checkUint8Array = checkUint8Array; /* Create a Buffer instance from a Uint8Array. * * @ignore */ function uint8ArrayToBuffer(b) { checkUint8Array(b); return buffer_1.Buffer.from(b.buffer, b.byteOffset, b.length); } Layout$1.uint8ArrayToBuffer = uint8ArrayToBuffer; /** * Base class for layout objects. * * **NOTE** This is an abstract base class; you can create instances * if it amuses you, but they won't support the {@link * Layout#encode|encode} or {@link Layout#decode|decode} functions. * * @param {Number} span - Initializer for {@link Layout#span|span}. The * parameter must be an integer; a negative value signifies that the * span is {@link Layout#getSpan|value-specific}. * * @param {string} [property] - Initializer for {@link * Layout#property|property}. * * @abstract */ class Layout { constructor(span, property) { if (!Number.isInteger(span)) { throw new TypeError('span must be an integer'); } /** The span of the layout in bytes. * * Positive values are generally expected. * * Zero will only appear in {@link Constant}s and in {@link * Sequence}s where the {@link Sequence#count|count} is zero. * * A negative value indicates that the span is value-specific, and * must be obtained using {@link Layout#getSpan|getSpan}. */ this.span = span; /** The property name used when this layout is represented in an * Object. * * Used only for layouts that {@link Layout#decode|decode} to Object * instances. If left undefined the span of the unnamed layout will * be treated as padding: it will not be mutated by {@link * Layout#encode|encode} nor represented as a property in the * decoded Object. */ this.property = property; } /** Function to create an Object into which decoded properties will * be written. * * Used only for layouts that {@link Layout#decode|decode} to Object * instances, which means: * * {@link Structure} * * {@link Union} * * {@link VariantLayout} * * {@link BitStructure} * * If left undefined the JavaScript representation of these layouts * will be Object instances. * * See {@link bindConstructorLayout}. */ makeDestinationObject() { return {}; } /** * Calculate the span of a specific instance of a layout. * * @param {Uint8Array} b - the buffer that contains an encoded instance. * * @param {Number} [offset] - the offset at which the encoded instance * starts. If absent a zero offset is inferred. * * @return {Number} - the number of bytes covered by the layout * instance. If this method is not overridden in a subclass the * definition-time constant {@link Layout#span|span} will be * returned. * * @throws {RangeError} - if the length of the value cannot be * determined. */ getSpan(b, offset) { if (0 > this.span) { throw new RangeError('indeterminate span'); } return this.span; } /** * Replicate the layout using a new property. * * This function must be used to get a structurally-equivalent layout * with a different name since all {@link Layout} instances are * immutable. * * **NOTE** This is a shallow copy. All fields except {@link * Layout#property|property} are strictly equal to the origin layout. * * @param {String} property - the value for {@link * Layout#property|property} in the replica. * * @returns {Layout} - the copy with {@link Layout#property|property} * set to `property`. */ replicate(property) { const rv = Object.create(this.constructor.prototype); Object.assign(rv, this); rv.property = property; return rv; } /** * Create an object from layout properties and an array of values. * * **NOTE** This function returns `undefined` if invoked on a layout * that does not return its value as an Object. Objects are * returned for things that are a {@link Structure}, which includes * {@link VariantLayout|variant layouts} if they are structures, and * excludes {@link Union}s. If you want this feature for a union * you must use {@link Union.getVariant|getVariant} to select the * desired layout. * * @param {Array} values - an array of values that correspond to the * default order for properties. As with {@link Layout#decode|decode} * layout elements that have no property name are skipped when * iterating over the array values. Only the top-level properties are * assigned; arguments are not assigned to properties of contained * layouts. Any unused values are ignored. * * @return {(Object|undefined)} */ fromArray(values) { return undefined; } } Layout$1.Layout = Layout; /* Provide text that carries a name (such as for a function that will * be throwing an error) annotated with the property of a given layout * (such as one for which the value was unacceptable). * * @ignore */ function nameWithProperty(name, lo) { if (lo.property) { return name + '[' + lo.property + ']'; } return name; } Layout$1.nameWithProperty = nameWithProperty; /** * Augment a class so that instances can be encoded/decoded using a * given layout. * * Calling this function couples `Class` with `layout` in several ways: * * * `Class.layout_` becomes a static member property equal to `layout`; * * `layout.boundConstructor_` becomes a static member property equal * to `Class`; * * The {@link Layout#makeDestinationObject|makeDestinationObject()} * property of `layout` is set to a function that returns a `new * Class()`; * * `Class.decode(b, offset)` becomes a static member function that * delegates to {@link Layout#decode|layout.decode}. The * synthesized function may be captured and extended. * * `Class.prototype.encode(b, offset)` provides an instance member * function that delegates to {@link Layout#encode|layout.encode} * with `src` set to `this`. The synthesized function may be * captured and extended, but when the extension is invoked `this` * must be explicitly bound to the instance. * * @param {class} Class - a JavaScript class with a nullary * constructor. * * @param {Layout} layout - the {@link Layout} instance used to encode * instances of `Class`. */ // `Class` must be a constructor Function, but the assignment of a `layout_` property to it makes it difficult to type // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function bindConstructorLayout(Class, layout) { if ('function' !== typeof Class) { throw new TypeError('Class must be constructor'); } if (Object.prototype.hasOwnProperty.call(Class, 'layout_')) { throw new Error('Class is already bound to a layout'); } if (!(layout && (layout instanceof Layout))) { throw new TypeError('layout must be a Layout'); } if (Object.prototype.hasOwnProperty.call(layout, 'boundConstructor_')) { throw new Error('layout is already bound to a constructor'); } Class.layout_ = layout; layout.boundConstructor_ = Class; layout.makeDestinationObject = (() => new Class()); Object.defineProperty(Class.prototype, 'encode', { value(b, offset) { return layout.encode(this, b, offset); }, writable: true, }); Object.defineProperty(Class, 'decode', { value(b, offset) { return layout.decode(b, offset); }, writable: true, }); } Layout$1.bindConstructorLayout = bindConstructorLayout; /** * An object that behaves like a layout but does not consume space * within its containing layout. * * This is primarily used to obtain metadata about a member, such as a * {@link OffsetLayout} that can provide data about a {@link * Layout#getSpan|value-specific span}. * * **NOTE** This is an abstract base class; you can create instances * if it amuses you, but they won't support {@link * ExternalLayout#isCount|isCount} or other {@link Layout} functions. * * @param {Number} span - initializer for {@link Layout#span|span}. * The parameter can range from 1 through 6. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @abstract * @augments {Layout} */ class ExternalLayout extends Layout { /** * Return `true` iff the external layout decodes to an unsigned * integer layout. * * In that case it can be used as the source of {@link * Sequence#count|Sequence counts}, {@link Blob#length|Blob lengths}, * or as {@link UnionLayoutDiscriminator#layout|external union * discriminators}. * * @abstract */ isCount() { throw new Error('ExternalLayout is abstract'); } } Layout$1.ExternalLayout = ExternalLayout; /** * An {@link ExternalLayout} that determines its {@link * Layout#decode|value} based on offset into and length of the buffer * on which it is invoked. * * *Factory*: {@link module:Layout.greedy|greedy} * * @param {Number} [elementSpan] - initializer for {@link * GreedyCount#elementSpan|elementSpan}. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {ExternalLayout} */ class GreedyCount extends ExternalLayout { constructor(elementSpan = 1, property) { if ((!Number.isInteger(elementSpan)) || (0 >= elementSpan)) { throw new TypeError('elementSpan must be a (positive) integer'); } super(-1, property); /** The layout for individual elements of the sequence. The value * must be a positive integer. If not provided, the value will be * 1. */ this.elementSpan = elementSpan; } /** @override */ isCount() { return true; } /** @override */ decode(b, offset = 0) { checkUint8Array(b); const rem = b.length - offset; return Math.floor(rem / this.elementSpan); } /** @override */ encode(src, b, offset) { return 0; } } Layout$1.GreedyCount = GreedyCount; /** * An {@link ExternalLayout} that supports accessing a {@link Layout} * at a fixed offset from the start of another Layout. The offset may * be before, within, or after the base layout. * * *Factory*: {@link module:Layout.offset|offset} * * @param {Layout} layout - initializer for {@link * OffsetLayout#layout|layout}, modulo `property`. * * @param {Number} [offset] - Initializes {@link * OffsetLayout#offset|offset}. Defaults to zero. * * @param {string} [property] - Optional new property name for a * {@link Layout#replicate| replica} of `layout` to be used as {@link * OffsetLayout#layout|layout}. If not provided the `layout` is used * unchanged. * * @augments {Layout} */ class OffsetLayout extends ExternalLayout { constructor(layout, offset = 0, property) { if (!(layout instanceof Layout)) { throw new TypeError('layout must be a Layout'); } if (!Number.isInteger(offset)) { throw new TypeError('offset must be integer or undefined'); } super(layout.span, property || layout.property); /** The subordinated layout. */ this.layout = layout; /** The location of {@link OffsetLayout#layout} relative to the * start of another layout. * * The value may be positive or negative, but an error will thrown * if at the point of use it goes outside the span of the Uint8Array * being accessed. */ this.offset = offset; } /** @override */ isCount() { return ((this.layout instanceof UInt) || (this.layout instanceof UIntBE)); } /** @override */ decode(b, offset = 0) { return this.layout.decode(b, offset + this.offset); } /** @override */ encode(src, b, offset = 0) { return this.layout.encode(src, b, offset + this.offset); } } Layout$1.OffsetLayout = OffsetLayout; /** * Represent an unsigned integer in little-endian format. * * *Factory*: {@link module:Layout.u8|u8}, {@link * module:Layout.u16|u16}, {@link module:Layout.u24|u24}, {@link * module:Layout.u32|u32}, {@link module:Layout.u40|u40}, {@link * module:Layout.u48|u48} * * @param {Number} span - initializer for {@link Layout#span|span}. * The parameter can range from 1 through 6. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class UInt extends Layout { constructor(span, property) { super(span, property); if (6 < this.span) { throw new RangeError('span must not exceed 6 bytes'); } } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readUIntLE(offset, this.span); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeUIntLE(src, offset, this.span); return this.span; } } Layout$1.UInt = UInt; /** * Represent an unsigned integer in big-endian format. * * *Factory*: {@link module:Layout.u8be|u8be}, {@link * module:Layout.u16be|u16be}, {@link module:Layout.u24be|u24be}, * {@link module:Layout.u32be|u32be}, {@link * module:Layout.u40be|u40be}, {@link module:Layout.u48be|u48be} * * @param {Number} span - initializer for {@link Layout#span|span}. * The parameter can range from 1 through 6. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class UIntBE extends Layout { constructor(span, property) { super(span, property); if (6 < this.span) { throw new RangeError('span must not exceed 6 bytes'); } } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readUIntBE(offset, this.span); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeUIntBE(src, offset, this.span); return this.span; } } Layout$1.UIntBE = UIntBE; /** * Represent a signed integer in little-endian format. * * *Factory*: {@link module:Layout.s8|s8}, {@link * module:Layout.s16|s16}, {@link module:Layout.s24|s24}, {@link * module:Layout.s32|s32}, {@link module:Layout.s40|s40}, {@link * module:Layout.s48|s48} * * @param {Number} span - initializer for {@link Layout#span|span}. * The parameter can range from 1 through 6. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Int extends Layout { constructor(span, property) { super(span, property); if (6 < this.span) { throw new RangeError('span must not exceed 6 bytes'); } } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readIntLE(offset, this.span); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeIntLE(src, offset, this.span); return this.span; } } Layout$1.Int = Int; /** * Represent a signed integer in big-endian format. * * *Factory*: {@link module:Layout.s8be|s8be}, {@link * module:Layout.s16be|s16be}, {@link module:Layout.s24be|s24be}, * {@link module:Layout.s32be|s32be}, {@link * module:Layout.s40be|s40be}, {@link module:Layout.s48be|s48be} * * @param {Number} span - initializer for {@link Layout#span|span}. * The parameter can range from 1 through 6. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class IntBE extends Layout { constructor(span, property) { super(span, property); if (6 < this.span) { throw new RangeError('span must not exceed 6 bytes'); } } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readIntBE(offset, this.span); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeIntBE(src, offset, this.span); return this.span; } } Layout$1.IntBE = IntBE; const V2E32 = Math.pow(2, 32); /* True modulus high and low 32-bit words, where low word is always * non-negative. */ function divmodInt64(src) { const hi32 = Math.floor(src / V2E32); const lo32 = src - (hi32 * V2E32); return { hi32, lo32 }; } /* Reconstruct Number from quotient and non-negative remainder */ function roundedInt64(hi32, lo32) { return hi32 * V2E32 + lo32; } /** * Represent an unsigned 64-bit integer in little-endian format when * encoded and as a near integral JavaScript Number when decoded. * * *Factory*: {@link module:Layout.nu64|nu64} * * **NOTE** Values with magnitude greater than 2^52 may not decode to * the exact value of the encoded representation. * * @augments {Layout} */ class NearUInt64 extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { const buffer = uint8ArrayToBuffer(b); const lo32 = buffer.readUInt32LE(offset); const hi32 = buffer.readUInt32LE(offset + 4); return roundedInt64(hi32, lo32); } /** @override */ encode(src, b, offset = 0) { const split = divmodInt64(src); const buffer = uint8ArrayToBuffer(b); buffer.writeUInt32LE(split.lo32, offset); buffer.writeUInt32LE(split.hi32, offset + 4); return 8; } } Layout$1.NearUInt64 = NearUInt64; /** * Represent an unsigned 64-bit integer in big-endian format when * encoded and as a near integral JavaScript Number when decoded. * * *Factory*: {@link module:Layout.nu64be|nu64be} * * **NOTE** Values with magnitude greater than 2^52 may not decode to * the exact value of the encoded representation. * * @augments {Layout} */ class NearUInt64BE extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { const buffer = uint8ArrayToBuffer(b); const hi32 = buffer.readUInt32BE(offset); const lo32 = buffer.readUInt32BE(offset + 4); return roundedInt64(hi32, lo32); } /** @override */ encode(src, b, offset = 0) { const split = divmodInt64(src); const buffer = uint8ArrayToBuffer(b); buffer.writeUInt32BE(split.hi32, offset); buffer.writeUInt32BE(split.lo32, offset + 4); return 8; } } Layout$1.NearUInt64BE = NearUInt64BE; /** * Represent a signed 64-bit integer in little-endian format when * encoded and as a near integral JavaScript Number when decoded. * * *Factory*: {@link module:Layout.ns64|ns64} * * **NOTE** Values with magnitude greater than 2^52 may not decode to * the exact value of the encoded representation. * * @augments {Layout} */ class NearInt64 extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { const buffer = uint8ArrayToBuffer(b); const lo32 = buffer.readUInt32LE(offset); const hi32 = buffer.readInt32LE(offset + 4); return roundedInt64(hi32, lo32); } /** @override */ encode(src, b, offset = 0) { const split = divmodInt64(src); const buffer = uint8ArrayToBuffer(b); buffer.writeUInt32LE(split.lo32, offset); buffer.writeInt32LE(split.hi32, offset + 4); return 8; } } Layout$1.NearInt64 = NearInt64; /** * Represent a signed 64-bit integer in big-endian format when * encoded and as a near integral JavaScript Number when decoded. * * *Factory*: {@link module:Layout.ns64be|ns64be} * * **NOTE** Values with magnitude greater than 2^52 may not decode to * the exact value of the encoded representation. * * @augments {Layout} */ class NearInt64BE extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { const buffer = uint8ArrayToBuffer(b); const hi32 = buffer.readInt32BE(offset); const lo32 = buffer.readUInt32BE(offset + 4); return roundedInt64(hi32, lo32); } /** @override */ encode(src, b, offset = 0) { const split = divmodInt64(src); const buffer = uint8ArrayToBuffer(b); buffer.writeInt32BE(split.hi32, offset); buffer.writeUInt32BE(split.lo32, offset + 4); return 8; } } Layout$1.NearInt64BE = NearInt64BE; /** * Represent a 32-bit floating point number in little-endian format. * * *Factory*: {@link module:Layout.f32|f32} * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Float extends Layout { constructor(property) { super(4, property); } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readFloatLE(offset); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeFloatLE(src, offset); return 4; } } Layout$1.Float = Float; /** * Represent a 32-bit floating point number in big-endian format. * * *Factory*: {@link module:Layout.f32be|f32be} * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class FloatBE extends Layout { constructor(property) { super(4, property); } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readFloatBE(offset); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeFloatBE(src, offset); return 4; } } Layout$1.FloatBE = FloatBE; /** * Represent a 64-bit floating point number in little-endian format. * * *Factory*: {@link module:Layout.f64|f64} * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Double extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readDoubleLE(offset); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeDoubleLE(src, offset); return 8; } } Layout$1.Double = Double; /** * Represent a 64-bit floating point number in big-endian format. * * *Factory*: {@link module:Layout.f64be|f64be} * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class DoubleBE extends Layout { constructor(property) { super(8, property); } /** @override */ decode(b, offset = 0) { return uint8ArrayToBuffer(b).readDoubleBE(offset); } /** @override */ encode(src, b, offset = 0) { uint8ArrayToBuffer(b).writeDoubleBE(src, offset); return 8; } } Layout$1.DoubleBE = DoubleBE; /** * Represent a contiguous sequence of a specific layout as an Array. * * *Factory*: {@link module:Layout.seq|seq} * * @param {Layout} elementLayout - initializer for {@link * Sequence#elementLayout|elementLayout}. * * @param {(Number|ExternalLayout)} count - initializer for {@link * Sequence#count|count}. The parameter must be either a positive * integer or an instance of {@link ExternalLayout}. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Sequence extends Layout { constructor(elementLayout, count, property) { if (!(elementLayout instanceof Layout)) { throw new TypeError('elementLayout must be a Layout'); } if (!(((count instanceof ExternalLayout) && count.isCount()) || (Number.isInteger(count) && (0 <= count)))) { throw new TypeError('count must be non-negative integer ' + 'or an unsigned integer ExternalLayout'); } let span = -1; if ((!(count instanceof ExternalLayout)) && (0 < elementLayout.span)) { span = count * elementLayout.span; } super(span, property); /** The layout for individual elements of the sequence. */ this.elementLayout = elementLayout; /** The number of elements in the sequence. * * This will be either a non-negative integer or an instance of * {@link ExternalLayout} for which {@link * ExternalLayout#isCount|isCount()} is `true`. */ this.count = count; } /** @override */ getSpan(b, offset = 0) { if (0 <= this.span) { return this.span; } let span = 0; let count = this.count; if (count instanceof ExternalLayout) { count = count.decode(b, offset); } if (0 < this.elementLayout.span) { span = count * this.elementLayout.span; } else { let idx = 0; while (idx < count) { span += this.elementLayout.getSpan(b, offset + span); ++idx; } } return span; } /** @override */ decode(b, offset = 0) { const rv = []; let i = 0; let count = this.count; if (count instanceof ExternalLayout) { count = count.decode(b, offset); } while (i < count) { rv.push(this.elementLayout.decode(b, offset)); offset += this.elementLayout.getSpan(b, offset); i += 1; } return rv; } /** Implement {@link Layout#encode|encode} for {@link Sequence}. * * **NOTE** If `src` is shorter than {@link Sequence#count|count} then * the unused space in the buffer is left unchanged. If `src` is * longer than {@link Sequence#count|count} the unneeded elements are * ignored. * * **NOTE** If {@link Layout#count|count} is an instance of {@link * ExternalLayout} then the length of `src` will be encoded as the * count after `src` is encoded. */ encode(src, b, offset = 0) { const elo = this.elementLayout; const span = src.reduce((span, v) => { return span + elo.encode(v, b, offset + span); }, 0); if (this.count instanceof ExternalLayout) { this.count.encode(src.length, b, offset); } return span; } } Layout$1.Sequence = Sequence; /** * Represent a contiguous sequence of arbitrary layout elements as an * Object. * * *Factory*: {@link module:Layout.struct|struct} * * **NOTE** The {@link Layout#span|span} of the structure is variable * if any layout in {@link Structure#fields|fields} has a variable * span. When {@link Layout#encode|encoding} we must have a value for * all variable-length fields, or we wouldn't be able to figure out * how much space to use for storage. We can only identify the value * for a field when it has a {@link Layout#property|property}. As * such, although a structure may contain both unnamed fields and * variable-length fields, it cannot contain an unnamed * variable-length field. * * @param {Layout[]} fields - initializer for {@link * Structure#fields|fields}. An error is raised if this contains a * variable-length field for which a {@link Layout#property|property} * is not defined. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @param {Boolean} [decodePrefixes] - initializer for {@link * Structure#decodePrefixes|property}. * * @throws {Error} - if `fields` contains an unnamed variable-length * layout. * * @augments {Layout} */ class Structure extends Layout { constructor(fields, property, decodePrefixes) { if (!(Array.isArray(fields) && fields.reduce((acc, v) => acc && (v instanceof Layout), true))) { throw new TypeError('fields must be array of Layout instances'); } if (('boolean' === typeof property) && (undefined === decodePrefixes)) { decodePrefixes = property; property = undefined; } /* Verify absence of unnamed variable-length fields. */ for (const fd of fields) { if ((0 > fd.span) && (undefined === fd.property)) { throw new Error('fields cannot contain unnamed variable-length layout'); } } let span = -1; try { span = fields.reduce((span, fd) => span + fd.getSpan(), 0); } catch (e) { // ignore error } super(span, property); /** The sequence of {@link Layout} values that comprise the * structure. * * The individual elements need not be the same type, and may be * either scalar or aggregate layouts. If a member layout leaves * its {@link Layout#property|property} undefined the * corresponding region of the buffer associated with the element * will not be mutated. * * @type {Layout[]} */ this.fields = fields; /** Control behavior of {@link Layout#decode|decode()} given short * buffers. * * In some situations a structure many be extended with additional * fields over time, with older installations providing only a * prefix of the full structure. If this property is `true` * decoding will accept those buffers and leave subsequent fields * undefined, as long as the buffer ends at a field boundary. * Defaults to `false`. */ this.decodePrefixes = !!decodePrefixes; } /** @override */ getSpan(b, offset = 0) { if (0 <= this.span) { return this.span; } let span = 0; try { span = this.fields.reduce((span, fd) => { const fsp = fd.getSpan(b, offset); offset += fsp; return span + fsp; }, 0); } catch (e) { throw new RangeError('indeterminate span'); } return span; } /** @override */ decode(b, offset = 0) { checkUint8Array(b); const dest = this.makeDestinationObject(); for (const fd of this.fields) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(b, offset); } offset += fd.getSpan(b, offset); if (this.decodePrefixes && (b.length === offset)) { break; } } return dest; } /** Implement {@link Layout#encode|encode} for {@link Structure}. * * If `src` is missing a property for a member with a defined {@link * Layout#property|property} the corresponding region of the buffer is * left unmodified. */ encode(src, b, offset = 0) { const firstOffset = offset; let lastOffset = 0; let lastWrote = 0; for (const fd of this.fields) { let span = fd.span; lastWrote = (0 < span) ? span : 0; if (undefined !== fd.property) { const fv = src[fd.property]; if (undefined !== fv) { lastWrote = fd.encode(fv, b, offset); if (0 > span) { /* Read the as-encoded span, which is not necessarily the * same as what we wrote. */ span = fd.getSpan(b, offset); } } } lastOffset = offset; offset += span; } /* Use (lastOffset + lastWrote) instead of offset because the last * item may have had a dynamic length and we don't want to include * the padding between it and the end of the space reserved for * it. */ return (lastOffset + lastWrote) - firstOffset; } /** @override */ fromArray(values) { const dest = this.makeDestinationObject(); for (const fd of this.fields) { if ((undefined !== fd.property) && (0 < values.length)) { dest[fd.property] = values.shift(); } } return dest; } /** * Get access to the layout of a given property. * * @param {String} property - the structure member of interest. * * @return {Layout} - the layout associated with `property`, or * undefined if there is no such property. */ layoutFor(property) { if ('string' !== typeof property) { throw new TypeError('property must be string'); } for (const fd of this.fields) { if (fd.property === property) { return fd; } } return undefined; } /** * Get the offset of a structure member. * * @param {String} property - the structure member of interest. * * @return {Number} - the offset in bytes to the start of `property` * within the structure, or undefined if `property` is not a field * within the structure. If the property is a member but follows a * variable-length structure member a negative number will be * returned. */ offsetOf(property) { if ('string' !== typeof property) { throw new TypeError('property must be string'); } let offset = 0; for (const fd of this.fields) { if (fd.property === property) { return offset; } if (0 > fd.span) { offset = -1; } else if (0 <= offset) { offset += fd.span; } } return undefined; } } Layout$1.Structure = Structure; /** * An object that can provide a {@link * Union#discriminator|discriminator} API for {@link Union}. * * **NOTE** This is an abstract base class; you can create instances * if it amuses you, but they won't support the {@link * UnionDiscriminator#encode|encode} or {@link * UnionDiscriminator#decode|decode} functions. * * @param {string} [property] - Default for {@link * UnionDiscriminator#property|property}. * * @abstract */ class UnionDiscriminator { constructor(property) { /** The {@link Layout#property|property} to be used when the * discriminator is referenced in isolation (generally when {@link * Union#decode|Union decode} cannot delegate to a specific * variant). */ this.property = property; } /** Analog to {@link Layout#decode|Layout decode} for union discriminators. * * The implementation of this method need not reference the buffer if * variant information is available through other means. */ decode(b, offset) { throw new Error('UnionDiscriminator is abstract'); } /** Analog to {@link Layout#decode|Layout encode} for union discriminators. * * The implementation of this method need not store the value if * variant information is maintained through other means. */ encode(src, b, offset) { throw new Error('UnionDiscriminator is abstract'); } } Layout$1.UnionDiscriminator = UnionDiscriminator; /** * An object that can provide a {@link * UnionDiscriminator|discriminator API} for {@link Union} using an * unsigned integral {@link Layout} instance located either inside or * outside the union. * * @param {ExternalLayout} layout - initializes {@link * UnionLayoutDiscriminator#layout|layout}. Must satisfy {@link * ExternalLayout#isCount|isCount()}. * * @param {string} [property] - Default for {@link * UnionDiscriminator#property|property}, superseding the property * from `layout`, but defaulting to `variant` if neither `property` * nor layout provide a property name. * * @augments {UnionDiscriminator} */ class UnionLayoutDiscriminator extends UnionDiscriminator { constructor(layout, property) { if (!((layout instanceof ExternalLayout) && layout.isCount())) { throw new TypeError('layout must be an unsigned integer ExternalLayout'); } super(property || layout.property || 'variant'); /** The {@link ExternalLayout} used to access the discriminator * value. */ this.layout = layout; } /** Delegate decoding to {@link UnionLayoutDiscriminator#layout|layout}. */ decode(b, offset) { return this.layout.decode(b, offset); } /** Delegate encoding to {@link UnionLayoutDiscriminator#layout|layout}. */ encode(src, b, offset) { return this.layout.encode(src, b, offset); } } Layout$1.UnionLayoutDiscriminator = UnionLayoutDiscriminator; /** * Represent any number of span-compatible layouts. * * *Factory*: {@link module:Layout.union|union} * * If the union has a {@link Union#defaultLayout|default layout} that * layout must have a non-negative {@link Layout#span|span}. The span * of a fixed-span union includes its {@link * Union#discriminator|discriminator} if the variant is a {@link * Union#usesPrefixDiscriminator|prefix of the union}, plus the span * of its {@link Union#defaultLayout|default layout}. * * If the union does not have a default layout then the encoded span * of the union depends on the encoded span of its variant (which may * be fixed or variable). * * {@link VariantLayout#layout|Variant layout}s are added through * {@link Union#addVariant|addVariant}. If the union has a default * layout, the span of the {@link VariantLayout#layout|layout * contained by the variant} must not exceed the span of the {@link * Union#defaultLayout|default layout} (minus the span of a {@link * Union#usesPrefixDiscriminator|prefix disriminator}, if used). The * span of the variant will equal the span of the union itself. * * The variant for a buffer can only be identified from the {@link * Union#discriminator|discriminator} {@link * UnionDiscriminator#property|property} (in the case of the {@link * Union#defaultLayout|default layout}), or by using {@link * Union#getVariant|getVariant} and examining the resulting {@link * VariantLayout} instance. * * A variant compatible with a JavaScript object can be identified * using {@link Union#getSourceVariant|getSourceVariant}. * * @param {(UnionDiscriminator|ExternalLayout|Layout)} discr - How to * identify the layout used to interpret the union contents. The * parameter must be an instance of {@link UnionDiscriminator}, an * {@link ExternalLayout} that satisfies {@link * ExternalLayout#isCount|isCount()}, or {@link UInt} (or {@link * UIntBE}). When a non-external layout element is passed the layout * appears at the start of the union. In all cases the (synthesized) * {@link UnionDiscriminator} instance is recorded as {@link * Union#discriminator|discriminator}. * * @param {(Layout|null)} defaultLayout - initializer for {@link * Union#defaultLayout|defaultLayout}. If absent defaults to `null`. * If `null` there is no default layout: the union has data-dependent * length and attempts to decode or encode unrecognized variants will * throw an exception. A {@link Layout} instance must have a * non-negative {@link Layout#span|span}, and if it lacks a {@link * Layout#property|property} the {@link * Union#defaultLayout|defaultLayout} will be a {@link * Layout#replicate|replica} with property `content`. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Union extends Layout { constructor(discr, defaultLayout, property) { let discriminator; if ((discr instanceof UInt) || (discr instanceof UIntBE)) { discriminator = new UnionLayoutDiscriminator(new OffsetLayout(discr)); } else if ((discr instanceof ExternalLayout) && discr.isCount()) { discriminator = new UnionLayoutDiscriminator(discr); } else if (!(discr instanceof UnionDiscriminator)) { throw new TypeError('discr must be a UnionDiscriminator ' + 'or an unsigned integer layout'); } else { discriminator = discr; } if (undefined === defaultLayout) { defaultLayout = null; } if (!((null === defaultLayout) || (defaultLayout instanceof Layout))) { throw new TypeError('defaultLayout must be null or a Layout'); } if (null !== defaultLayout) { if (0 > defaultLayout.span) { throw new Error('defaultLayout must have constant span'); } if (undefined === defaultLayout.property) { defaultLayout = defaultLayout.replicate('content'); } } /* The union span can be estimated only if there's a default * layout. The union spans its default layout, plus any prefix * variant layout. By construction both layouts, if present, have * non-negative span. */ let span = -1; if (defaultLayout) { span = defaultLayout.span; if ((0 <= span) && ((discr instanceof UInt) || (discr instanceof UIntBE))) { span += discriminator.layout.span; } } super(span, property); /** The interface for the discriminator value in isolation. * * This a {@link UnionDiscriminator} either passed to the * constructor or synthesized from the `discr` constructor * argument. {@link * Union#usesPrefixDiscriminator|usesPrefixDiscriminator} will be * `true` iff the `discr` parameter was a non-offset {@link * Layout} instance. */ this.discriminator = discriminator; /** `true` if the {@link Union#discriminator|discriminator} is the * first field in the union. * * If `false` the discriminator is obtained from somewhere * else. */ this.usesPrefixDiscriminator = (discr instanceof UInt) || (discr instanceof UIntBE); /** The layout for non-discriminator content when the value of the * discriminator is not recognized. * * This is the value passed to the constructor. It is * structurally equivalent to the second component of {@link * Union#layout|layout} but may have a different property * name. */ this.defaultLayout = defaultLayout; /** A registry of allowed variants. * * The keys are unsigned integers which should be compatible with * {@link Union.discriminator|discriminator}. The property value * is the corresponding {@link VariantLayout} instances assigned * to this union by {@link Union#addVariant|addVariant}. * * **NOTE** The registry remains mutable so that variants can be * {@link Union#addVariant|added} at any time. Users should not * manipulate the content of this property. */ this.registry = {}; /* Private variable used when invoking getSourceVariant */ let boundGetSourceVariant = this.defaultGetSourceVariant.bind(this); /** Function to infer the variant selected by a source object. * * Defaults to {@link * Union#defaultGetSourceVariant|defaultGetSourceVariant} but may * be overridden using {@link * Union#configGetSourceVariant|configGetSourceVariant}. * * @param {Object} src - as with {@link * Union#defaultGetSourceVariant|defaultGetSourceVariant}. * * @returns {(undefined|VariantLayout)} The default variant * (`undefined`) or first registered variant that uses a property * available in `src`. */ this.getSourceVariant = function (src) { return boundGetSourceVariant(src); }; /** Function to override the implementation of {@link * Union#getSourceVariant|getSourceVariant}. * * Use this if the desired variant cannot be identified using the * algorithm of {@link * Union#defaultGetSourceVariant|defaultGetSourceVariant}. * * **NOTE** The provided function will be invoked bound to this * Union instance, providing local access to {@link * Union#registry|registry}. * * @param {Function} gsv - a function that follows the API of * {@link Union#defaultGetSourceVariant|defaultGetSourceVariant}. */ this.configGetSourceVariant = function (gsv) { boundGetSourceVariant = gsv.bind(this); }; } /** @override */ getSpan(b, offset = 0) { if (0 <= this.span) { return this.span; } /* Default layouts always have non-negative span, so we don't have * one and we have to recognize the variant which will in turn * determine the span. */ const vlo = this.getVariant(b, offset); if (!vlo) { throw new Error('unable to determine span for unrecognized variant'); } return vlo.getSpan(b, offset); } /** * Method to infer a registered Union variant compatible with `src`. * * The first satisfied rule in the following sequence defines the * return value: * * If `src` has properties matching the Union discriminator and * the default layout, `undefined` is returned regardless of the * value of the discriminator property (this ensures the default * layout will be used); * * If `src` has a property matching the Union discriminator, the * value of the discriminator identifies a registered variant, and * either (a) the variant has no layout, or (b) `src` has the * variant's property, then the variant is returned (because the * source satisfies the constraints of the variant it identifies); * * If `src` does not have a property matching the Union * discriminator, but does have a property matching a registered * variant, then the variant is returned (because the source * matches a variant without an explicit conflict); * * An error is thrown (because we either can't identify a variant, * or we were explicitly told the variant but can't satisfy it). * * @param {Object} src - an object presumed to be compatible with * the content of the Union. * * @return {(undefined|VariantLayout)} - as described above. * * @throws {Error} - if `src` cannot be associated with a default or * registered variant. */ defaultGetSourceVariant(src) { if (Object.prototype.hasOwnProperty.call(src, this.discriminator.property)) { if (this.defaultLayout && this.defaultLayout.property && Object.prototype.hasOwnProperty.call(src, this.defaultLayout.property)) { return undefined; } const vlo = this.registry[src[this.discriminator.property]]; if (vlo && ((!vlo.layout) || (vlo.property && Object.prototype.hasOwnProperty.call(src, vlo.property)))) { return vlo; } } else { for (const tag in this.registry) { const vlo = this.registry[tag]; if (vlo.property && Object.prototype.hasOwnProperty.call(src, vlo.property)) { return vlo; } } } throw new Error('unable to infer src variant'); } /** Implement {@link Layout#decode|decode} for {@link Union}. * * If the variant is {@link Union#addVariant|registered} the return * value is an instance of that variant, with no explicit * discriminator. Otherwise the {@link Union#defaultLayout|default * layout} is used to decode the content. */ decode(b, offset = 0) { let dest; const dlo = this.discriminator; const discr = dlo.decode(b, offset); const clo = this.registry[discr]; if (undefined === clo) { const defaultLayout = this.defaultLayout; let contentOffset = 0; if (this.usesPrefixDiscriminator) { contentOffset = dlo.layout.span; } dest = this.makeDestinationObject(); dest[dlo.property] = discr; // defaultLayout.property can be undefined, but this is allowed by buffer-layout // eslint-disable-next-line @typescript-eslint/no-non-null-assertion dest[defaultLayout.property] = defaultLayout.decode(b, offset + contentOffset); } else { dest = clo.decode(b, offset); } return dest; } /** Implement {@link Layout#encode|encode} for {@link Union}. * * This API assumes the `src` object is consistent with the union's * {@link Union#defaultLayout|default layout}. To encode variants * use the appropriate variant-specific {@link VariantLayout#encode} * method. */ encode(src, b, offset = 0) { const vlo = this.getSourceVariant(src); if (undefined === vlo) { const dlo = this.discriminator; // this.defaultLayout is not undefined when vlo is undefined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const clo = this.defaultLayout; let contentOffset = 0; if (this.usesPrefixDiscriminator) { contentOffset = dlo.layout.span; } dlo.encode(src[dlo.property], b, offset); // clo.property is not undefined when vlo is undefined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return contentOffset + clo.encode(src[clo.property], b, offset + contentOffset); } return vlo.encode(src, b, offset); } /** Register a new variant structure within a union. The newly * created variant is returned. * * @param {Number} variant - initializer for {@link * VariantLayout#variant|variant}. * * @param {Layout} layout - initializer for {@link * VariantLayout#layout|layout}. * * @param {String} property - initializer for {@link * Layout#property|property}. * * @return {VariantLayout} */ addVariant(variant, layout, property) { const rv = new VariantLayout(this, variant, layout, property); this.registry[variant] = rv; return rv; } /** * Get the layout associated with a registered variant. * * If `vb` does not produce a registered variant the function returns * `undefined`. * * @param {(Number|Uint8Array)} vb - either the variant number, or a * buffer from which the discriminator is to be read. * * @param {Number} offset - offset into `vb` for the start of the * union. Used only when `vb` is an instance of {Uint8Array}. * * @return {({VariantLayout}|undefined)} */ getVariant(vb, offset = 0) { let variant; if (vb instanceof Uint8Array) { variant = this.discriminator.decode(vb, offset); } else { variant = vb; } return this.registry[variant]; } } Layout$1.Union = Union; /** * Represent a specific variant within a containing union. * * **NOTE** The {@link Layout#span|span} of the variant may include * the span of the {@link Union#discriminator|discriminator} used to * identify it, but values read and written using the variant strictly * conform to the content of {@link VariantLayout#layout|layout}. * * **NOTE** User code should not invoke this constructor directly. Use * the union {@link Union#addVariant|addVariant} helper method. * * @param {Union} union - initializer for {@link * VariantLayout#union|union}. * * @param {Number} variant - initializer for {@link * VariantLayout#variant|variant}. * * @param {Layout} [layout] - initializer for {@link * VariantLayout#layout|layout}. If absent the variant carries no * data. * * @param {String} [property] - initializer for {@link * Layout#property|property}. Unlike many other layouts, variant * layouts normally include a property name so they can be identified * within their containing {@link Union}. The property identifier may * be absent only if `layout` is is absent. * * @augments {Layout} */ class VariantLayout extends Layout { constructor(union, variant, layout, property) { if (!(union instanceof Union)) { throw new TypeError('union must be a Union'); } if ((!Number.isInteger(variant)) || (0 > variant)) { throw new TypeError('variant must be a (non-negative) integer'); } if (('string' === typeof layout) && (undefined === property)) { property = layout; layout = null; } if (layout) { if (!(layout instanceof Layout)) { throw new TypeError('layout must be a Layout'); } if ((null !== union.defaultLayout) && (0 <= layout.span) && (layout.span > union.defaultLayout.span)) { throw new Error('variant span exceeds span of containing union'); } if ('string' !== typeof property) { throw new TypeError('variant must have a String property'); } } let span = union.span; if (0 > union.span) { span = layout ? layout.span : 0; if ((0 <= span) && union.usesPrefixDiscriminator) { span += union.discriminator.layout.span; } } super(span, property); /** The {@link Union} to which this variant belongs. */ this.union = union; /** The unsigned integral value identifying this variant within * the {@link Union#discriminator|discriminator} of the containing * union. */ this.variant = variant; /** The {@link Layout} to be used when reading/writing the * non-discriminator part of the {@link * VariantLayout#union|union}. If `null` the variant carries no * data. */ this.layout = layout || null; } /** @override */ getSpan(b, offset = 0) { if (0 <= this.span) { /* Will be equal to the containing union span if that is not * variable. */ return this.span; } let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } /* Span is defined solely by the variant (and prefix discriminator) */ let span = 0; if (this.layout) { span = this.layout.getSpan(b, offset + contentOffset); } return contentOffset + span; } /** @override */ decode(b, offset = 0) { const dest = this.makeDestinationObject(); if (this !== this.union.getVariant(b, offset)) { throw new Error('variant mismatch'); } let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } if (this.layout) { dest[this.property] = this.layout.decode(b, offset + contentOffset); } else if (this.property) { dest[this.property] = true; } else if (this.union.usesPrefixDiscriminator) { dest[this.union.discriminator.property] = this.variant; } return dest; } /** @override */ encode(src, b, offset = 0) { let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } if (this.layout && (!Object.prototype.hasOwnProperty.call(src, this.property))) { throw new TypeError('variant lacks property ' + this.property); } this.union.discriminator.encode(this.variant, b, offset); let span = contentOffset; if (this.layout) { this.layout.encode(src[this.property], b, offset + contentOffset); span += this.layout.getSpan(b, offset + contentOffset); if ((0 <= this.union.span) && (span > this.union.span)) { throw new Error('encoded variant overruns containing union'); } } return span; } /** Delegate {@link Layout#fromArray|fromArray} to {@link * VariantLayout#layout|layout}. */ fromArray(values) { if (this.layout) { return this.layout.fromArray(values); } return undefined; } } Layout$1.VariantLayout = VariantLayout; /** JavaScript chose to define bitwise operations as operating on * signed 32-bit values in 2's complement form, meaning any integer * with bit 31 set is going to look negative. For right shifts that's * not a problem, because `>>>` is a logical shift, but for every * other bitwise operator we have to compensate for possible negative * results. */ function fixBitwiseResult(v) { if (0 > v) { v += 0x100000000; } return v; } /** * Contain a sequence of bit fields as an unsigned integer. * * *Factory*: {@link module:Layout.bits|bits} * * This is a container element; within it there are {@link BitField} * instances that provide the extracted properties. The container * simply defines the aggregate representation and its bit ordering. * The representation is an object containing properties with numeric * or {@link Boolean} values. * * {@link BitField}s are added with the {@link * BitStructure#addField|addField} and {@link * BitStructure#addBoolean|addBoolean} methods. * @param {Layout} word - initializer for {@link * BitStructure#word|word}. The parameter must be an instance of * {@link UInt} (or {@link UIntBE}) that is no more than 4 bytes wide. * * @param {bool} [msb] - `true` if the bit numbering starts at the * most significant bit of the containing word; `false` (default) if * it starts at the least significant bit of the containing word. If * the parameter at this position is a string and `property` is * `undefined` the value of this argument will instead be used as the * value of `property`. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class BitStructure extends Layout { constructor(word, msb, property) { if (!((word instanceof UInt) || (word instanceof UIntBE))) { throw new TypeError('word must be a UInt or UIntBE layout'); } if (('string' === typeof msb) && (undefined === property)) { property = msb; msb = false; } if (4 < word.span) { throw new RangeError('word cannot exceed 32 bits'); } super(word.span, property); /** The layout used for the packed value. {@link BitField} * instances are packed sequentially depending on {@link * BitStructure#msb|msb}. */ this.word = word; /** Whether the bit sequences are packed starting at the most * significant bit growing down (`true`), or the least significant * bit growing up (`false`). * * **NOTE** Regardless of this value, the least significant bit of * any {@link BitField} value is the least significant bit of the * corresponding section of the packed value. */ this.msb = !!msb; /** The sequence of {@link BitField} layouts that comprise the * packed structure. * * **NOTE** The array remains mutable to allow fields to be {@link * BitStructure#addField|added} after construction. Users should * not manipulate the content of this property.*/ this.fields = []; /* Storage for the value. Capture a variable instead of using an * instance property because we don't want anything to change the * value without going through the mutator. */ let value = 0; this._packedSetValue = function (v) { value = fixBitwiseResult(v); return this; }; this._packedGetValue = function () { return value; }; } /** @override */ decode(b, offset = 0) { const dest = this.makeDestinationObject(); const value = this.word.decode(b, offset); this._packedSetValue(value); for (const fd of this.fields) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(b); } } return dest; } /** Implement {@link Layout#encode|encode} for {@link BitStructure}. * * If `src` is missing a property for a member with a defined {@link * Layout#property|property} the corresponding region of the packed * value is left unmodified. Unused bits are also left unmodified. */ encode(src, b, offset = 0) { const value = this.word.decode(b, offset); this._packedSetValue(value); for (const fd of this.fields) { if (undefined !== fd.property) { const fv = src[fd.property]; if (undefined !== fv) { fd.encode(fv); } } } return this.word.encode(this._packedGetValue(), b, offset); } /** Register a new bitfield with a containing bit structure. The * resulting bitfield is returned. * * @param {Number} bits - initializer for {@link BitField#bits|bits}. * * @param {string} property - initializer for {@link * Layout#property|property}. * * @return {BitField} */ addField(bits, property) { const bf = new BitField(this, bits, property); this.fields.push(bf); return bf; } /** As with {@link BitStructure#addField|addField} for single-bit * fields with `boolean` value representation. * * @param {string} property - initializer for {@link * Layout#property|property}. * * @return {Boolean} */ // `Boolean` conflicts with the native primitive type // eslint-disable-next-line @typescript-eslint/ban-types addBoolean(property) { // This is my Boolean, not the Javascript one. const bf = new Boolean$1(this, property); this.fields.push(bf); return bf; } /** * Get access to the bit field for a given property. * * @param {String} property - the bit field of interest. * * @return {BitField} - the field associated with `property`, or * undefined if there is no such property. */ fieldFor(property) { if ('string' !== typeof property) { throw new TypeError('property must be string'); } for (const fd of this.fields) { if (fd.property === property) { return fd; } } return undefined; } } Layout$1.BitStructure = BitStructure; /** * Represent a sequence of bits within a {@link BitStructure}. * * All bit field values are represented as unsigned integers. * * **NOTE** User code should not invoke this constructor directly. * Use the container {@link BitStructure#addField|addField} helper * method. * * **NOTE** BitField instances are not instances of {@link Layout} * since {@link Layout#span|span} measures 8-bit units. * * @param {BitStructure} container - initializer for {@link * BitField#container|container}. * * @param {Number} bits - initializer for {@link BitField#bits|bits}. * * @param {string} [property] - initializer for {@link * Layout#property|property}. */ class BitField { constructor(container, bits, property) { if (!(container instanceof BitStructure)) { throw new TypeError('container must be a BitStructure'); } if ((!Number.isInteger(bits)) || (0 >= bits)) { throw new TypeError('bits must be positive integer'); } const totalBits = 8 * container.span; const usedBits = container.fields.reduce((sum, fd) => sum + fd.bits, 0); if ((bits + usedBits) > totalBits) { throw new Error('bits too long for span remainder (' + (totalBits - usedBits) + ' of ' + totalBits + ' remain)'); } /** The {@link BitStructure} instance to which this bit field * belongs. */ this.container = container; /** The span of this value in bits. */ this.bits = bits; /** A mask of {@link BitField#bits|bits} bits isolating value bits * that fit within the field. * * That is, it masks a value that has not yet been shifted into * position within its containing packed integer. */ this.valueMask = (1 << bits) - 1; if (32 === bits) { // shifted value out of range this.valueMask = 0xFFFFFFFF; } /** The offset of the value within the containing packed unsigned * integer. The least significant bit of the packed value is at * offset zero, regardless of bit ordering used. */ this.start = usedBits; if (this.container.msb) { this.start = totalBits - usedBits - bits; } /** A mask of {@link BitField#bits|bits} isolating the field value * within the containing packed unsigned integer. */ this.wordMask = fixBitwiseResult(this.valueMask << this.start); /** The property name used when this bitfield is represented in an * Object. * * Intended to be functionally equivalent to {@link * Layout#property}. * * If left undefined the corresponding span of bits will be * treated as padding: it will not be mutated by {@link * Layout#encode|encode} nor represented as a property in the * decoded Object. */ this.property = property; } /** Store a value into the corresponding subsequence of the containing * bit field. */ decode(b, offset) { const word = this.container._packedGetValue(); const wordValue = fixBitwiseResult(word & this.wordMask); const value = wordValue >>> this.start; return value; } /** Store a value into the corresponding subsequence of the containing * bit field. * * **NOTE** This is not a specialization of {@link * Layout#encode|Layout.encode} and there is no return value. */ encode(value) { if ('number' !== typeof value || !Number.isInteger(value) || (value !== fixBitwiseResult(value & this.valueMask))) { throw new TypeError(nameWithProperty('BitField.encode', this) + ' value must be integer not exceeding ' + this.valueMask); } const word = this.container._packedGetValue(); const wordValue = fixBitwiseResult(value << this.start); this.container._packedSetValue(fixBitwiseResult(word & ~this.wordMask) | wordValue); } } Layout$1.BitField = BitField; /** * Represent a single bit within a {@link BitStructure} as a * JavaScript boolean. * * **NOTE** User code should not invoke this constructor directly. * Use the container {@link BitStructure#addBoolean|addBoolean} helper * method. * * @param {BitStructure} container - initializer for {@link * BitField#container|container}. * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @augments {BitField} */ /* eslint-disable no-extend-native */ let Boolean$1 = class Boolean extends BitField { constructor(container, property) { super(container, 1, property); } /** Override {@link BitField#decode|decode} for {@link Boolean|Boolean}. * * @returns {boolean} */ decode(b, offset) { return !!super.decode(b, offset); } /** @override */ encode(value) { if ('boolean' === typeof value) { // BitField requires integer values value = +value; } super.encode(value); } }; Layout$1.Boolean = Boolean$1; /* eslint-enable no-extend-native */ /** * Contain a fixed-length block of arbitrary data, represented as a * Uint8Array. * * *Factory*: {@link module:Layout.blob|blob} * * @param {(Number|ExternalLayout)} length - initializes {@link * Blob#length|length}. * * @param {String} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Blob extends Layout { constructor(length, property) { if (!(((length instanceof ExternalLayout) && length.isCount()) || (Number.isInteger(length) && (0 <= length)))) { throw new TypeError('length must be positive integer ' + 'or an unsigned integer ExternalLayout'); } let span = -1; if (!(length instanceof ExternalLayout)) { span = length; } super(span, property); /** The number of bytes in the blob. * * This may be a non-negative integer, or an instance of {@link * ExternalLayout} that satisfies {@link * ExternalLayout#isCount|isCount()}. */ this.length = length; } /** @override */ getSpan(b, offset) { let span = this.span; if (0 > span) { span = this.length.decode(b, offset); } return span; } /** @override */ decode(b, offset = 0) { let span = this.span; if (0 > span) { span = this.length.decode(b, offset); } return uint8ArrayToBuffer(b).slice(offset, offset + span); } /** Implement {@link Layout#encode|encode} for {@link Blob}. * * **NOTE** If {@link Layout#count|count} is an instance of {@link * ExternalLayout} then the length of `src` will be encoded as the * count after `src` is encoded. */ encode(src, b, offset) { let span = this.length; if (this.length instanceof ExternalLayout) { span = src.length; } if (!(src instanceof Uint8Array && span === src.length)) { throw new TypeError(nameWithProperty('Blob.encode', this) + ' requires (length ' + span + ') Uint8Array as src'); } if ((offset + span) > b.length) { throw new RangeError('encoding overruns Uint8Array'); } const srcBuffer = uint8ArrayToBuffer(src); uint8ArrayToBuffer(b).write(srcBuffer.toString('hex'), offset, span, 'hex'); if (this.length instanceof ExternalLayout) { this.length.encode(span, b, offset); } return span; } } Layout$1.Blob = Blob; /** * Contain a `NUL`-terminated UTF8 string. * * *Factory*: {@link module:Layout.cstr|cstr} * * **NOTE** Any UTF8 string that incorporates a zero-valued byte will * not be correctly decoded by this layout. * * @param {String} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class CString extends Layout { constructor(property) { super(-1, property); } /** @override */ getSpan(b, offset = 0) { checkUint8Array(b); let idx = offset; while ((idx < b.length) && (0 !== b[idx])) { idx += 1; } return 1 + idx - offset; } /** @override */ decode(b, offset = 0) { const span = this.getSpan(b, offset); return uint8ArrayToBuffer(b).slice(offset, offset + span - 1).toString('utf-8'); } /** @override */ encode(src, b, offset = 0) { /* Must force this to a string, lest it be a number and the * "utf8-encoding" below actually allocate a buffer of length * src */ if ('string' !== typeof src) { src = String(src); } const srcb = buffer_1.Buffer.from(src, 'utf8'); const span = srcb.length; if ((offset + span) > b.length) { throw new RangeError('encoding overruns Buffer'); } const buffer = uint8ArrayToBuffer(b); srcb.copy(buffer, offset); buffer[offset + span] = 0; return span + 1; } } Layout$1.CString = CString; /** * Contain a UTF8 string with implicit length. * * *Factory*: {@link module:Layout.utf8|utf8} * * **NOTE** Because the length is implicit in the size of the buffer * this layout should be used only in isolation, or in a situation * where the length can be expressed by operating on a slice of the * containing buffer. * * @param {Number} [maxSpan] - the maximum length allowed for encoded * string content. If not provided there is no bound on the allowed * content. * * @param {String} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class UTF8 extends Layout { constructor(maxSpan, property) { if (('string' === typeof maxSpan) && (undefined === property)) { property = maxSpan; maxSpan = undefined; } if (undefined === maxSpan) { maxSpan = -1; } else if (!Number.isInteger(maxSpan)) { throw new TypeError('maxSpan must be an integer'); } super(-1, property); /** The maximum span of the layout in bytes. * * Positive values are generally expected. Zero is abnormal. * Attempts to encode or decode a value that exceeds this length * will throw a `RangeError`. * * A negative value indicates that there is no bound on the length * of the content. */ this.maxSpan = maxSpan; } /** @override */ getSpan(b, offset = 0) { checkUint8Array(b); return b.length - offset; } /** @override */ decode(b, offset = 0) { const span = this.getSpan(b, offset); if ((0 <= this.maxSpan) && (this.maxSpan < span)) { throw new RangeError('text length exceeds maxSpan'); } return uint8ArrayToBuffer(b).slice(offset, offset + span).toString('utf-8'); } /** @override */ encode(src, b, offset = 0) { /* Must force this to a string, lest it be a number and the * "utf8-encoding" below actually allocate a buffer of length * src */ if ('string' !== typeof src) { src = String(src); } const srcb = buffer_1.Buffer.from(src, 'utf8'); const span = srcb.length; if ((0 <= this.maxSpan) && (this.maxSpan < span)) { throw new RangeError('text length exceeds maxSpan'); } if ((offset + span) > b.length) { throw new RangeError('encoding overruns Buffer'); } srcb.copy(uint8ArrayToBuffer(b), offset); return span; } } Layout$1.UTF8 = UTF8; /** * Contain a constant value. * * This layout may be used in cases where a JavaScript value can be * inferred without an expression in the binary encoding. An example * would be a {@link VariantLayout|variant layout} where the content * is implied by the union {@link Union#discriminator|discriminator}. * * @param {Object|Number|String} value - initializer for {@link * Constant#value|value}. If the value is an object (or array) and * the application intends the object to remain unchanged regardless * of what is done to values decoded by this layout, the value should * be frozen prior passing it to this constructor. * * @param {String} [property] - initializer for {@link * Layout#property|property}. * * @augments {Layout} */ class Constant extends Layout { constructor(value, property) { super(0, property); /** The value produced by this constant when the layout is {@link * Constant#decode|decoded}. * * Any JavaScript value including `null` and `undefined` is * permitted. * * **WARNING** If `value` passed in the constructor was not * frozen, it is possible for users of decoded values to change * the content of the value. */ this.value = value; } /** @override */ decode(b, offset) { return this.value; } /** @override */ encode(src, b, offset) { /* Constants take no space */ return 0; } } Layout$1.Constant = Constant; /** Factory for {@link GreedyCount}. */ Layout$1.greedy = ((elementSpan, property) => new GreedyCount(elementSpan, property)); /** Factory for {@link OffsetLayout}. */ var offset = Layout$1.offset = ((layout, offset, property) => new OffsetLayout(layout, offset, property)); /** Factory for {@link UInt|unsigned int layouts} spanning one * byte. */ var u8 = Layout$1.u8 = ((property) => new UInt(1, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning two bytes. */ var u16 = Layout$1.u16 = ((property) => new UInt(2, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning three bytes. */ Layout$1.u24 = ((property) => new UInt(3, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning four bytes. */ var u32 = Layout$1.u32 = ((property) => new UInt(4, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning five bytes. */ Layout$1.u40 = ((property) => new UInt(5, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning six bytes. */ Layout$1.u48 = ((property) => new UInt(6, property)); /** Factory for {@link NearUInt64|little-endian unsigned int * layouts} interpreted as Numbers. */ var nu64 = Layout$1.nu64 = ((property) => new NearUInt64(property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning two bytes. */ Layout$1.u16be = ((property) => new UIntBE(2, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning three bytes. */ Layout$1.u24be = ((property) => new UIntBE(3, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning four bytes. */ Layout$1.u32be = ((property) => new UIntBE(4, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning five bytes. */ Layout$1.u40be = ((property) => new UIntBE(5, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning six bytes. */ Layout$1.u48be = ((property) => new UIntBE(6, property)); /** Factory for {@link NearUInt64BE|big-endian unsigned int * layouts} interpreted as Numbers. */ Layout$1.nu64be = ((property) => new NearUInt64BE(property)); /** Factory for {@link Int|signed int layouts} spanning one * byte. */ Layout$1.s8 = ((property) => new Int(1, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning two bytes. */ Layout$1.s16 = ((property) => new Int(2, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning three bytes. */ Layout$1.s24 = ((property) => new Int(3, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning four bytes. */ Layout$1.s32 = ((property) => new Int(4, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning five bytes. */ Layout$1.s40 = ((property) => new Int(5, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning six bytes. */ Layout$1.s48 = ((property) => new Int(6, property)); /** Factory for {@link NearInt64|little-endian signed int layouts} * interpreted as Numbers. */ var ns64 = Layout$1.ns64 = ((property) => new NearInt64(property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning two bytes. */ Layout$1.s16be = ((property) => new IntBE(2, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning three bytes. */ Layout$1.s24be = ((property) => new IntBE(3, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning four bytes. */ Layout$1.s32be = ((property) => new IntBE(4, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning five bytes. */ Layout$1.s40be = ((property) => new IntBE(5, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning six bytes. */ Layout$1.s48be = ((property) => new IntBE(6, property)); /** Factory for {@link NearInt64BE|big-endian signed int layouts} * interpreted as Numbers. */ Layout$1.ns64be = ((property) => new NearInt64BE(property)); /** Factory for {@link Float|little-endian 32-bit floating point} values. */ Layout$1.f32 = ((property) => new Float(property)); /** Factory for {@link FloatBE|big-endian 32-bit floating point} values. */ Layout$1.f32be = ((property) => new FloatBE(property)); /** Factory for {@link Double|little-endian 64-bit floating point} values. */ Layout$1.f64 = ((property) => new Double(property)); /** Factory for {@link DoubleBE|big-endian 64-bit floating point} values. */ Layout$1.f64be = ((property) => new DoubleBE(property)); /** Factory for {@link Structure} values. */ var struct = Layout$1.struct = ((fields, property, decodePrefixes) => new Structure(fields, property, decodePrefixes)); /** Factory for {@link BitStructure} values. */ Layout$1.bits = ((word, msb, property) => new BitStructure(word, msb, property)); /** Factory for {@link Sequence} values. */ var seq = Layout$1.seq = ((elementLayout, count, property) => new Sequence(elementLayout, count, property)); /** Factory for {@link Union} values. */ Layout$1.union = ((discr, defaultLayout, property) => new Union(discr, defaultLayout, property)); /** Factory for {@link UnionLayoutDiscriminator} values. */ Layout$1.unionLayoutDiscriminator = ((layout, property) => new UnionLayoutDiscriminator(layout, property)); /** Factory for {@link Blob} values. */ var blob = Layout$1.blob = ((length, property) => new Blob(length, property)); /** Factory for {@link CString} values. */ Layout$1.cstr = ((property) => new CString(property)); /** Factory for {@link UTF8} values. */ Layout$1.utf8 = ((maxSpan, property) => new UTF8(maxSpan, property)); /** Factory for {@link Constant} values. */ Layout$1.constant = ((value, property) => new Constant(value, property)); /** * Maximum over-the-wire size of a Transaction * * 1280 is IPv6 minimum MTU * 40 bytes is the size of the IPv6 header * 8 bytes is the size of the fragment header */ const PACKET_DATA_SIZE = 1280 - 40 - 8; const VERSION_PREFIX_MASK = 0x7f; const SIGNATURE_LENGTH_IN_BYTES = 64; class TransactionExpiredBlockheightExceededError extends Error { constructor(signature) { super(`Signature ${signature} has expired: block height exceeded.`); this.signature = void 0; this.signature = signature; } } Object.defineProperty(TransactionExpiredBlockheightExceededError.prototype, 'name', { value: 'TransactionExpiredBlockheightExceededError' }); class TransactionExpiredTimeoutError extends Error { constructor(signature, timeoutSeconds) { super(`Transaction was not confirmed in ${timeoutSeconds.toFixed(2)} seconds. It is ` + 'unknown if it succeeded or failed. Check signature ' + `${signature} using the Solana Explorer or CLI tools.`); this.signature = void 0; this.signature = signature; } } Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', { value: 'TransactionExpiredTimeoutError' }); class TransactionExpiredNonceInvalidError extends Error { constructor(signature) { super(`Signature ${signature} has expired: the nonce is no longer valid.`); this.signature = void 0; this.signature = signature; } } Object.defineProperty(TransactionExpiredNonceInvalidError.prototype, 'name', { value: 'TransactionExpiredNonceInvalidError' }); class MessageAccountKeys { constructor(staticAccountKeys, accountKeysFromLookups) { this.staticAccountKeys = void 0; this.accountKeysFromLookups = void 0; this.staticAccountKeys = staticAccountKeys; this.accountKeysFromLookups = accountKeysFromLookups; } keySegments() { const keySegments = [this.staticAccountKeys]; if (this.accountKeysFromLookups) { keySegments.push(this.accountKeysFromLookups.writable); keySegments.push(this.accountKeysFromLookups.readonly); } return keySegments; } get(index) { for (const keySegment of this.keySegments()) { if (index < keySegment.length) { return keySegment[index]; } else { index -= keySegment.length; } } return; } get length() { return this.keySegments().flat().length; } compileInstructions(instructions) { // Bail early if any account indexes would overflow a u8 const U8_MAX = 255; if (this.length > U8_MAX + 1) { throw new Error('Account index overflow encountered during compilation'); } const keyIndexMap = new Map(); this.keySegments().flat().forEach((key, index) => { keyIndexMap.set(key.toBase58(), index); }); const findKeyIndex = key => { const keyIndex = keyIndexMap.get(key.toBase58()); if (keyIndex === undefined) throw new Error('Encountered an unknown instruction account key during compilation'); return keyIndex; }; return instructions.map(instruction => { return { programIdIndex: findKeyIndex(instruction.programId), accountKeyIndexes: instruction.keys.map(meta => findKeyIndex(meta.pubkey)), data: instruction.data }; }); } } /** * Layout for a public key */ const publicKey = (property = 'publicKey') => { return blob(32, property); }; /** * Layout for a signature */ const signature = (property = 'signature') => { return blob(64, property); }; /** * Layout for a Rust String type */ const rustString = (property = 'string') => { const rsl = struct([u32('length'), u32('lengthPadding'), blob(offset(u32(), -8), 'chars')], property); const _decode = rsl.decode.bind(rsl); const _encode = rsl.encode.bind(rsl); const rslShim = rsl; rslShim.decode = (b, offset) => { const data = _decode(b, offset); return data['chars'].toString(); }; rslShim.encode = (str, b, offset) => { const data = { chars: buffer.Buffer.from(str, 'utf8') }; return _encode(data, b, offset); }; rslShim.alloc = str => { return u32().span + u32().span + buffer.Buffer.from(str, 'utf8').length; }; return rslShim; }; /** * Layout for an Authorized object */ const authorized = (property = 'authorized') => { return struct([publicKey('staker'), publicKey('withdrawer')], property); }; /** * Layout for a Lockup object */ const lockup = (property = 'lockup') => { return struct([ns64('unixTimestamp'), ns64('epoch'), publicKey('custodian')], property); }; /** * Layout for a VoteInit object */ const voteInit = (property = 'voteInit') => { return struct([publicKey('nodePubkey'), publicKey('authorizedVoter'), publicKey('authorizedWithdrawer'), u8('commission')], property); }; /** * Layout for a VoteAuthorizeWithSeedArgs object */ const voteAuthorizeWithSeedArgs = (property = 'voteAuthorizeWithSeedArgs') => { return struct([u32('voteAuthorizationType'), publicKey('currentAuthorityDerivedKeyOwnerPubkey'), rustString('currentAuthorityDerivedKeySeed'), publicKey('newAuthorized')], property); }; function getAlloc(type, fields) { const getItemAlloc = item => { if (item.span >= 0) { return item.span; } else if (typeof item.alloc === 'function') { return item.alloc(fields[item.property]); } else if ('count' in item && 'elementLayout' in item) { const field = fields[item.property]; if (Array.isArray(field)) { return field.length * getItemAlloc(item.elementLayout); } } else if ('fields' in item) { // This is a `Structure` whose size needs to be recursively measured. return getAlloc({ layout: item }, fields[item.property]); } // Couldn't determine allocated size of layout return 0; }; let alloc = 0; type.layout.fields.forEach(item => { alloc += getItemAlloc(item); }); return alloc; } function decodeLength(bytes) { let len = 0; let size = 0; for (;;) { let elem = bytes.shift(); len |= (elem & 0x7f) << size * 7; size += 1; if ((elem & 0x80) === 0) { break; } } return len; } function encodeLength(bytes, len) { let rem_len = len; for (;;) { let elem = rem_len & 0x7f; rem_len >>= 7; if (rem_len == 0) { bytes.push(elem); break; } else { elem |= 0x80; bytes.push(elem); } } } function assert$1 (condition, message) { if (!condition) { throw new Error(message || 'Assertion failed'); } } class CompiledKeys { constructor(payer, keyMetaMap) { this.payer = void 0; this.keyMetaMap = void 0; this.payer = payer; this.keyMetaMap = keyMetaMap; } static compile(instructions, payer) { const keyMetaMap = new Map(); const getOrInsertDefault = pubkey => { const address = pubkey.toBase58(); let keyMeta = keyMetaMap.get(address); if (keyMeta === undefined) { keyMeta = { isSigner: false, isWritable: false, isInvoked: false }; keyMetaMap.set(address, keyMeta); } return keyMeta; }; const payerKeyMeta = getOrInsertDefault(payer); payerKeyMeta.isSigner = true; payerKeyMeta.isWritable = true; for (const ix of instructions) { getOrInsertDefault(ix.programId).isInvoked = true; for (const accountMeta of ix.keys) { const keyMeta = getOrInsertDefault(accountMeta.pubkey); keyMeta.isSigner ||= accountMeta.isSigner; keyMeta.isWritable ||= accountMeta.isWritable; } } return new CompiledKeys(payer, keyMetaMap); } getMessageComponents() { const mapEntries = [...this.keyMetaMap.entries()]; assert$1(mapEntries.length <= 256, 'Max static account keys length exceeded'); const writableSigners = mapEntries.filter(([, meta]) => meta.isSigner && meta.isWritable); const readonlySigners = mapEntries.filter(([, meta]) => meta.isSigner && !meta.isWritable); const writableNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && meta.isWritable); const readonlyNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && !meta.isWritable); const header = { numRequiredSignatures: writableSigners.length + readonlySigners.length, numReadonlySignedAccounts: readonlySigners.length, numReadonlyUnsignedAccounts: readonlyNonSigners.length }; // sanity checks { assert$1(writableSigners.length > 0, 'Expected at least one writable signer key'); const [payerAddress] = writableSigners[0]; assert$1(payerAddress === this.payer.toBase58(), 'Expected first writable signer key to be the fee payer'); } 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))]; return [header, staticAccountKeys]; } extractTableLookup(lookupTable) { const [writableIndexes, drainedWritableKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && keyMeta.isWritable); const [readonlyIndexes, drainedReadonlyKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && !keyMeta.isWritable); // Don't extract lookup if no keys were found if (writableIndexes.length === 0 && readonlyIndexes.length === 0) { return; } return [{ accountKey: lookupTable.key, writableIndexes, readonlyIndexes }, { writable: drainedWritableKeys, readonly: drainedReadonlyKeys }]; } /** @internal */ drainKeysFoundInLookupTable(lookupTableEntries, keyMetaFilter) { const lookupTableIndexes = new Array(); const drainedKeys = new Array(); for (const [address, keyMeta] of this.keyMetaMap.entries()) { if (keyMetaFilter(keyMeta)) { const key = new PublicKey(address); const lookupTableIndex = lookupTableEntries.findIndex(entry => entry.equals(key)); if (lookupTableIndex >= 0) { assert$1(lookupTableIndex < 256, 'Max lookup table index exceeded'); lookupTableIndexes.push(lookupTableIndex); drainedKeys.push(key); this.keyMetaMap.delete(address); } } } return [lookupTableIndexes, drainedKeys]; } } const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly'; /** * Delegates to `Array#shift`, but throws if the array is zero-length. */ function guardedShift(byteArray) { if (byteArray.length === 0) { throw new Error(END_OF_BUFFER_ERROR_MESSAGE); } return byteArray.shift(); } /** * Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of * the array. */ function guardedSplice(byteArray, ...args) { const [start] = args; if (args.length === 2 // Implies that `deleteCount` was supplied ? start + (args[1] ?? 0) > byteArray.length : start >= byteArray.length) { throw new Error(END_OF_BUFFER_ERROR_MESSAGE); } return byteArray.splice(...args); } /** * An instruction to execute by a program * * @property {number} programIdIndex * @property {number[]} accounts * @property {string} data */ /** * Message constructor arguments */ /** * List of instructions to be processed atomically */ class Message { constructor(args) { this.header = void 0; this.accountKeys = void 0; this.recentBlockhash = void 0; this.instructions = void 0; this.indexToProgramIds = new Map(); this.header = args.header; this.accountKeys = args.accountKeys.map(account => new PublicKey(account)); this.recentBlockhash = args.recentBlockhash; this.instructions = args.instructions; this.instructions.forEach(ix => this.indexToProgramIds.set(ix.programIdIndex, this.accountKeys[ix.programIdIndex])); } get version() { return 'legacy'; } get staticAccountKeys() { return this.accountKeys; } get compiledInstructions() { return this.instructions.map(ix => ({ programIdIndex: ix.programIdIndex, accountKeyIndexes: ix.accounts, data: bs58$1.decode(ix.data) })); } get addressTableLookups() { return []; } getAccountKeys() { return new MessageAccountKeys(this.staticAccountKeys); } static compile(args) { const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey); const [header, staticAccountKeys] = compiledKeys.getMessageComponents(); const accountKeys = new MessageAccountKeys(staticAccountKeys); const instructions = accountKeys.compileInstructions(args.instructions).map(ix => ({ programIdIndex: ix.programIdIndex, accounts: ix.accountKeyIndexes, data: bs58$1.encode(ix.data) })); return new Message({ header, accountKeys: staticAccountKeys, recentBlockhash: args.recentBlockhash, instructions }); } isAccountSigner(index) { return index < this.header.numRequiredSignatures; } isAccountWritable(index) { const numSignedAccounts = this.header.numRequiredSignatures; if (index >= this.header.numRequiredSignatures) { const unsignedAccountIndex = index - numSignedAccounts; const numUnsignedAccounts = this.accountKeys.length - numSignedAccounts; const numWritableUnsignedAccounts = numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts; return unsignedAccountIndex < numWritableUnsignedAccounts; } else { const numWritableSignedAccounts = numSignedAccounts - this.header.numReadonlySignedAccounts; return index < numWritableSignedAccounts; } } isProgramId(index) { return this.indexToProgramIds.has(index); } programIds() { return [...this.indexToProgramIds.values()]; } nonProgramIds() { return this.accountKeys.filter((_, index) => !this.isProgramId(index)); } serialize() { const numKeys = this.accountKeys.length; let keyCount = []; encodeLength(keyCount, numKeys); const instructions = this.instructions.map(instruction => { const { accounts, programIdIndex } = instruction; const data = Array.from(bs58$1.decode(instruction.data)); let keyIndicesCount = []; encodeLength(keyIndicesCount, accounts.length); let dataCount = []; encodeLength(dataCount, data.length); return { programIdIndex, keyIndicesCount: buffer.Buffer.from(keyIndicesCount), keyIndices: accounts, dataLength: buffer.Buffer.from(dataCount), data }; }); let instructionCount = []; encodeLength(instructionCount, instructions.length); let instructionBuffer = buffer.Buffer.alloc(PACKET_DATA_SIZE); buffer.Buffer.from(instructionCount).copy(instructionBuffer); let instructionBufferLength = instructionCount.length; instructions.forEach(instruction => { const instructionLayout = struct([u8('programIdIndex'), blob(instruction.keyIndicesCount.length, 'keyIndicesCount'), seq(u8('keyIndex'), instruction.keyIndices.length, 'keyIndices'), blob(instruction.dataLength.length, 'dataLength'), seq(u8('userdatum'), instruction.data.length, 'data')]); const length = instructionLayout.encode(instruction, instructionBuffer, instructionBufferLength); instructionBufferLength += length; }); instructionBuffer = instructionBuffer.slice(0, instructionBufferLength); const signDataLayout = struct([blob(1, 'numRequiredSignatures'), blob(1, 'numReadonlySignedAccounts'), blob(1, 'numReadonlyUnsignedAccounts'), blob(keyCount.length, 'keyCount'), seq(publicKey('key'), numKeys, 'keys'), publicKey('recentBlockhash')]); const transaction = { numRequiredSignatures: buffer.Buffer.from([this.header.numRequiredSignatures]), numReadonlySignedAccounts: buffer.Buffer.from([this.header.numReadonlySignedAccounts]), numReadonlyUnsignedAccounts: buffer.Buffer.from([this.header.numReadonlyUnsignedAccounts]), keyCount: buffer.Buffer.from(keyCount), keys: this.accountKeys.map(key => toBuffer(key.toBytes())), recentBlockhash: bs58$1.decode(this.recentBlockhash) }; let signData = buffer.Buffer.alloc(2048); const length = signDataLayout.encode(transaction, signData); instructionBuffer.copy(signData, length); return signData.slice(0, length + instructionBuffer.length); } /** * Decode a compiled message into a Message object. */ static from(buffer$1) { // Slice up wire data let byteArray = [...buffer$1]; const numRequiredSignatures = guardedShift(byteArray); if (numRequiredSignatures !== (numRequiredSignatures & VERSION_PREFIX_MASK)) { throw new Error('Versioned messages must be deserialized with VersionedMessage.deserialize()'); } const numReadonlySignedAccounts = guardedShift(byteArray); const numReadonlyUnsignedAccounts = guardedShift(byteArray); const accountCount = decodeLength(byteArray); let accountKeys = []; for (let i = 0; i < accountCount; i++) { const account = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH); accountKeys.push(new PublicKey(buffer.Buffer.from(account))); } const recentBlockhash = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH); const instructionCount = decodeLength(byteArray); let instructions = []; for (let i = 0; i < instructionCount; i++) { const programIdIndex = guardedShift(byteArray); const accountCount = decodeLength(byteArray); const accounts = guardedSplice(byteArray, 0, accountCount); const dataLength = decodeLength(byteArray); const dataSlice = guardedSplice(byteArray, 0, dataLength); const data = bs58$1.encode(buffer.Buffer.from(dataSlice)); instructions.push({ programIdIndex, accounts, data }); } const messageArgs = { header: { numRequiredSignatures, numReadonlySignedAccounts, numReadonlyUnsignedAccounts }, recentBlockhash: bs58$1.encode(buffer.Buffer.from(recentBlockhash)), accountKeys, instructions }; return new Message(messageArgs); } } /** * Message constructor arguments */ class MessageV0 { constructor(args) { this.header = void 0; this.staticAccountKeys = void 0; this.recentBlockhash = void 0; this.compiledInstructions = void 0; this.addressTableLookups = void 0; this.header = args.header; this.staticAccountKeys = args.staticAccountKeys; this.recentBlockhash = args.recentBlockhash; this.compiledInstructions = args.compiledInstructions; this.addressTableLookups = args.addressTableLookups; } get version() { return 0; } get numAccountKeysFromLookups() { let count = 0; for (const lookup of this.addressTableLookups) { count += lookup.readonlyIndexes.length + lookup.writableIndexes.length; } return count; } getAccountKeys(args) { let accountKeysFromLookups; if (args && 'accountKeysFromLookups' in args && args.accountKeysFromLookups) { if (this.numAccountKeysFromLookups != args.accountKeysFromLookups.writable.length + args.accountKeysFromLookups.readonly.length) { throw new Error('Failed to get account keys because of a mismatch in the number of account keys from lookups'); } accountKeysFromLookups = args.accountKeysFromLookups; } else if (args && 'addressLookupTableAccounts' in args && args.addressLookupTableAccounts) { accountKeysFromLookups = this.resolveAddressTableLookups(args.addressLookupTableAccounts); } else if (this.addressTableLookups.length > 0) { throw new Error('Failed to get account keys because address table lookups were not resolved'); } return new MessageAccountKeys(this.staticAccountKeys, accountKeysFromLookups); } isAccountSigner(index) { return index < this.header.numRequiredSignatures; } isAccountWritable(index) { const numSignedAccounts = this.header.numRequiredSignatures; const numStaticAccountKeys = this.staticAccountKeys.length; if (index >= numStaticAccountKeys) { const lookupAccountKeysIndex = index - numStaticAccountKeys; const numWritableLookupAccountKeys = this.addressTableLookups.reduce((count, lookup) => count + lookup.writableIndexes.length, 0); return lookupAccountKeysIndex < numWritableLookupAccountKeys; } else if (index >= this.header.numRequiredSignatures) { const unsignedAccountIndex = index - numSignedAccounts; const numUnsignedAccounts = numStaticAccountKeys - numSignedAccounts; const numWritableUnsignedAccounts = numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts; return unsignedAccountIndex < numWritableUnsignedAccounts; } else { const numWritableSignedAccounts = numSignedAccounts - this.header.numReadonlySignedAccounts; return index < numWritableSignedAccounts; } } resolveAddressTableLookups(addressLookupTableAccounts) { const accountKeysFromLookups = { writable: [], readonly: [] }; for (const tableLookup of this.addressTableLookups) { const tableAccount = addressLookupTableAccounts.find(account => account.key.equals(tableLookup.accountKey)); if (!tableAccount) { throw new Error(`Failed to find address lookup table account for table key ${tableLookup.accountKey.toBase58()}`); } for (const index of tableLookup.writableIndexes) { if (index < tableAccount.state.addresses.length) { accountKeysFromLookups.writable.push(tableAccount.state.addresses[index]); } else { throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`); } } for (const index of tableLookup.readonlyIndexes) { if (index < tableAccount.state.addresses.length) { accountKeysFromLookups.readonly.push(tableAccount.state.addresses[index]); } else { throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`); } } } return accountKeysFromLookups; } static compile(args) { const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey); const addressTableLookups = new Array(); const accountKeysFromLookups = { writable: new Array(), readonly: new Array() }; const lookupTableAccounts = args.addressLookupTableAccounts || []; for (const lookupTable of lookupTableAccounts) { const extractResult = compiledKeys.extractTableLookup(lookupTable); if (extractResult !== undefined) { const [addressTableLookup, { writable, readonly }] = extractResult; addressTableLookups.push(addressTableLookup); accountKeysFromLookups.writable.push(...writable); accountKeysFromLookups.readonly.push(...readonly); } } const [header, staticAccountKeys] = compiledKeys.getMessageComponents(); const accountKeys = new MessageAccountKeys(staticAccountKeys, accountKeysFromLookups); const compiledInstructions = accountKeys.compileInstructions(args.instructions); return new MessageV0({ header, staticAccountKeys, recentBlockhash: args.recentBlockhash, compiledInstructions, addressTableLookups }); } serialize() { const encodedStaticAccountKeysLength = Array(); encodeLength(encodedStaticAccountKeysLength, this.staticAccountKeys.length); const serializedInstructions = this.serializeInstructions(); const encodedInstructionsLength = Array(); encodeLength(encodedInstructionsLength, this.compiledInstructions.length); const serializedAddressTableLookups = this.serializeAddressTableLookups(); const encodedAddressTableLookupsLength = Array(); encodeLength(encodedAddressTableLookupsLength, this.addressTableLookups.length); const messageLayout = struct([u8('prefix'), struct([u8('numRequiredSignatures'), u8('numReadonlySignedAccounts'), u8('numReadonlyUnsignedAccounts')], 'header'), blob(encodedStaticAccountKeysLength.length, 'staticAccountKeysLength'), seq(publicKey(), this.staticAccountKeys.length, 'staticAccountKeys'), publicKey('recentBlockhash'), blob(encodedInstructionsLength.length, 'instructionsLength'), blob(serializedInstructions.length, 'serializedInstructions'), blob(encodedAddressTableLookupsLength.length, 'addressTableLookupsLength'), blob(serializedAddressTableLookups.length, 'serializedAddressTableLookups')]); const serializedMessage = new Uint8Array(PACKET_DATA_SIZE); const MESSAGE_VERSION_0_PREFIX = 1 << 7; const serializedMessageLength = messageLayout.encode({ prefix: MESSAGE_VERSION_0_PREFIX, header: this.header, staticAccountKeysLength: new Uint8Array(encodedStaticAccountKeysLength), staticAccountKeys: this.staticAccountKeys.map(key => key.toBytes()), recentBlockhash: bs58$1.decode(this.recentBlockhash), instructionsLength: new Uint8Array(encodedInstructionsLength), serializedInstructions, addressTableLookupsLength: new Uint8Array(encodedAddressTableLookupsLength), serializedAddressTableLookups }, serializedMessage); return serializedMessage.slice(0, serializedMessageLength); } serializeInstructions() { let serializedLength = 0; const serializedInstructions = new Uint8Array(PACKET_DATA_SIZE); for (const instruction of this.compiledInstructions) { const encodedAccountKeyIndexesLength = Array(); encodeLength(encodedAccountKeyIndexesLength, instruction.accountKeyIndexes.length); const encodedDataLength = Array(); encodeLength(encodedDataLength, instruction.data.length); const instructionLayout = struct([u8('programIdIndex'), blob(encodedAccountKeyIndexesLength.length, 'encodedAccountKeyIndexesLength'), seq(u8(), instruction.accountKeyIndexes.length, 'accountKeyIndexes'), blob(encodedDataLength.length, 'encodedDataLength'), blob(instruction.data.length, 'data')]); serializedLength += instructionLayout.encode({ programIdIndex: instruction.programIdIndex, encodedAccountKeyIndexesLength: new Uint8Array(encodedAccountKeyIndexesLength), accountKeyIndexes: instruction.accountKeyIndexes, encodedDataLength: new Uint8Array(encodedDataLength), data: instruction.data }, serializedInstructions, serializedLength); } return serializedInstructions.slice(0, serializedLength); } serializeAddressTableLookups() { let serializedLength = 0; const serializedAddressTableLookups = new Uint8Array(PACKET_DATA_SIZE); for (const lookup of this.addressTableLookups) { const encodedWritableIndexesLength = Array(); encodeLength(encodedWritableIndexesLength, lookup.writableIndexes.length); const encodedReadonlyIndexesLength = Array(); encodeLength(encodedReadonlyIndexesLength, lookup.readonlyIndexes.length); const addressTableLookupLayout = struct([publicKey('accountKey'), blob(encodedWritableIndexesLength.length, 'encodedWritableIndexesLength'), seq(u8(), lookup.writableIndexes.length, 'writableIndexes'), blob(encodedReadonlyIndexesLength.length, 'encodedReadonlyIndexesLength'), seq(u8(), lookup.readonlyIndexes.length, 'readonlyIndexes')]); serializedLength += addressTableLookupLayout.encode({ accountKey: lookup.accountKey.toBytes(), encodedWritableIndexesLength: new Uint8Array(encodedWritableIndexesLength), writableIndexes: lookup.writableIndexes, encodedReadonlyIndexesLength: new Uint8Array(encodedReadonlyIndexesLength), readonlyIndexes: lookup.readonlyIndexes }, serializedAddressTableLookups, serializedLength); } return serializedAddressTableLookups.slice(0, serializedLength); } static deserialize(serializedMessage) { let byteArray = [...serializedMessage]; const prefix = guardedShift(byteArray); const maskedPrefix = prefix & VERSION_PREFIX_MASK; assert$1(prefix !== maskedPrefix, `Expected versioned message but received legacy message`); const version = maskedPrefix; assert$1(version === 0, `Expected versioned message with version 0 but found version ${version}`); const header = { numRequiredSignatures: guardedShift(byteArray), numReadonlySignedAccounts: guardedShift(byteArray), numReadonlyUnsignedAccounts: guardedShift(byteArray) }; const staticAccountKeys = []; const staticAccountKeysLength = decodeLength(byteArray); for (let i = 0; i < staticAccountKeysLength; i++) { staticAccountKeys.push(new PublicKey(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH))); } const recentBlockhash = bs58$1.encode(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH)); const instructionCount = decodeLength(byteArray); const compiledInstructions = []; for (let i = 0; i < instructionCount; i++) { const programIdIndex = guardedShift(byteArray); const accountKeyIndexesLength = decodeLength(byteArray); const accountKeyIndexes = guardedSplice(byteArray, 0, accountKeyIndexesLength); const dataLength = decodeLength(byteArray); const data = new Uint8Array(guardedSplice(byteArray, 0, dataLength)); compiledInstructions.push({ programIdIndex, accountKeyIndexes, data }); } const addressTableLookupsCount = decodeLength(byteArray); const addressTableLookups = []; for (let i = 0; i < addressTableLookupsCount; i++) { const accountKey = new PublicKey(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH)); const writableIndexesLength = decodeLength(byteArray); const writableIndexes = guardedSplice(byteArray, 0, writableIndexesLength); const readonlyIndexesLength = decodeLength(byteArray); const readonlyIndexes = guardedSplice(byteArray, 0, readonlyIndexesLength); addressTableLookups.push({ accountKey, writableIndexes, readonlyIndexes }); } return new MessageV0({ header, staticAccountKeys, recentBlockhash, compiledInstructions, addressTableLookups }); } } // eslint-disable-next-line no-redeclare const VersionedMessage = { deserializeMessageVersion(serializedMessage) { const prefix = serializedMessage[0]; const maskedPrefix = prefix & VERSION_PREFIX_MASK; // if the highest bit of the prefix is not set, the message is not versioned if (maskedPrefix === prefix) { return 'legacy'; } // the lower 7 bits of the prefix indicate the message version return maskedPrefix; }, deserialize: serializedMessage => { const version = VersionedMessage.deserializeMessageVersion(serializedMessage); if (version === 'legacy') { return Message.from(serializedMessage); } if (version === 0) { return MessageV0.deserialize(serializedMessage); } else { throw new Error(`Transaction message version ${version} deserialization is not supported`); } } }; /** @internal */ /** * Transaction signature as base-58 encoded string */ let TransactionStatus = /*#__PURE__*/function (TransactionStatus) { TransactionStatus[TransactionStatus["BLOCKHEIGHT_EXCEEDED"] = 0] = "BLOCKHEIGHT_EXCEEDED"; TransactionStatus[TransactionStatus["PROCESSED"] = 1] = "PROCESSED"; TransactionStatus[TransactionStatus["TIMED_OUT"] = 2] = "TIMED_OUT"; TransactionStatus[TransactionStatus["NONCE_INVALID"] = 3] = "NONCE_INVALID"; return TransactionStatus; }({}); /** * Default (empty) signature */ const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0); /** * Account metadata used to define instructions */ /** * List of TransactionInstruction object fields that may be initialized at construction */ /** * Configuration object for Transaction.serialize() */ /** * @internal */ /** * Transaction Instruction class */ class TransactionInstruction { constructor(opts) { /** * Public keys to include in this transaction * Boolean represents whether this pubkey needs to sign the transaction */ this.keys = void 0; /** * Program Id to execute */ this.programId = void 0; /** * Program input */ this.data = buffer.Buffer.alloc(0); this.programId = opts.programId; this.keys = opts.keys; if (opts.data) { this.data = opts.data; } } /** * @internal */ toJSON() { return { keys: this.keys.map(({ pubkey, isSigner, isWritable }) => ({ pubkey: pubkey.toJSON(), isSigner, isWritable })), programId: this.programId.toJSON(), data: [...this.data] }; } } /** * Pair of signature and corresponding public key */ /** * List of Transaction object fields that may be initialized at construction */ // For backward compatibility; an unfortunate consequence of being // forced to over-export types by the documentation generator. // See https://github.com/solana-labs/solana/pull/25820 /** * Blockhash-based transactions have a lifetime that are defined by * the blockhash they include. Any transaction whose blockhash is * too old will be rejected. */ /** * Use these options to construct a durable nonce transaction. */ /** * Nonce information to be used to build an offline Transaction. */ /** * @internal */ /** * Transaction class */ class Transaction { /** * The first (payer) Transaction signature * * @returns {Buffer | null} Buffer of payer's signature */ get signature() { if (this.signatures.length > 0) { return this.signatures[0].signature; } return null; } /** * The transaction fee payer */ // Construct a transaction with a blockhash and lastValidBlockHeight // Construct a transaction using a durable nonce /** * @deprecated `TransactionCtorFields` has been deprecated and will be removed in a future version. * Please supply a `TransactionBlockhashCtor` instead. */ /** * Construct an empty Transaction */ constructor(opts) { /** * Signatures for the transaction. Typically created by invoking the * `sign()` method */ this.signatures = []; this.feePayer = void 0; /** * The instructions to atomically execute */ this.instructions = []; /** * A recent transaction id. Must be populated by the caller */ this.recentBlockhash = void 0; /** * the last block chain can advance to before tx is declared expired * */ this.lastValidBlockHeight = void 0; /** * Optional Nonce information. If populated, transaction will use a durable * Nonce hash instead of a recentBlockhash. Must be populated by the caller */ this.nonceInfo = void 0; /** * If this is a nonce transaction this represents the minimum slot from which * to evaluate if the nonce has advanced when attempting to confirm the * transaction. This protects against a case where the transaction confirmation * logic loads the nonce account from an old slot and assumes the mismatch in * nonce value implies that the nonce has been advanced. */ this.minNonceContextSlot = void 0; /** * @internal */ this._message = void 0; /** * @internal */ this._json = void 0; if (!opts) { return; } if (opts.feePayer) { this.feePayer = opts.feePayer; } if (opts.signatures) { this.signatures = opts.signatures; } if (Object.prototype.hasOwnProperty.call(opts, 'nonceInfo')) { const { minContextSlot, nonceInfo } = opts; this.minNonceContextSlot = minContextSlot; this.nonceInfo = nonceInfo; } else if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) { const { blockhash, lastValidBlockHeight } = opts; this.recentBlockhash = blockhash; this.lastValidBlockHeight = lastValidBlockHeight; } else { const { recentBlockhash, nonceInfo } = opts; if (nonceInfo) { this.nonceInfo = nonceInfo; } this.recentBlockhash = recentBlockhash; } } /** * @internal */ toJSON() { return { recentBlockhash: this.recentBlockhash || null, feePayer: this.feePayer ? this.feePayer.toJSON() : null, nonceInfo: this.nonceInfo ? { nonce: this.nonceInfo.nonce, nonceInstruction: this.nonceInfo.nonceInstruction.toJSON() } : null, instructions: this.instructions.map(instruction => instruction.toJSON()), signers: this.signatures.map(({ publicKey }) => { return publicKey.toJSON(); }) }; } /** * Add one or more instructions to this Transaction * * @param {Array< Transaction | TransactionInstruction | TransactionInstructionCtorFields >} items - Instructions to add to the Transaction */ add(...items) { if (items.length === 0) { throw new Error('No instructions'); } items.forEach(item => { if ('instructions' in item) { this.instructions = this.instructions.concat(item.instructions); } else if ('data' in item && 'programId' in item && 'keys' in item) { this.instructions.push(item); } else { this.instructions.push(new TransactionInstruction(item)); } }); return this; } /** * Compile transaction data */ compileMessage() { if (this._message && JSON.stringify(this.toJSON()) === JSON.stringify(this._json)) { return this._message; } let recentBlockhash; let instructions; if (this.nonceInfo) { recentBlockhash = this.nonceInfo.nonce; if (this.instructions[0] != this.nonceInfo.nonceInstruction) { instructions = [this.nonceInfo.nonceInstruction, ...this.instructions]; } else { instructions = this.instructions; } } else { recentBlockhash = this.recentBlockhash; instructions = this.instructions; } if (!recentBlockhash) { throw new Error('Transaction recentBlockhash required'); } if (instructions.length < 1) { console.warn('No instructions provided'); } let feePayer; if (this.feePayer) { feePayer = this.feePayer; } else if (this.signatures.length > 0 && this.signatures[0].publicKey) { // Use implicit fee payer feePayer = this.signatures[0].publicKey; } else { throw new Error('Transaction fee payer required'); } for (let i = 0; i < instructions.length; i++) { if (instructions[i].programId === undefined) { throw new Error(`Transaction instruction index ${i} has undefined program id`); } } const programIds = []; const accountMetas = []; instructions.forEach(instruction => { instruction.keys.forEach(accountMeta => { accountMetas.push({ ...accountMeta }); }); const programId = instruction.programId.toString(); if (!programIds.includes(programId)) { programIds.push(programId); } }); // Append programID account metas programIds.forEach(programId => { accountMetas.push({ pubkey: new PublicKey(programId), isSigner: false, isWritable: false }); }); // Cull duplicate account metas const uniqueMetas = []; accountMetas.forEach(accountMeta => { const pubkeyString = accountMeta.pubkey.toString(); const uniqueIndex = uniqueMetas.findIndex(x => { return x.pubkey.toString() === pubkeyString; }); if (uniqueIndex > -1) { uniqueMetas[uniqueIndex].isWritable = uniqueMetas[uniqueIndex].isWritable || accountMeta.isWritable; uniqueMetas[uniqueIndex].isSigner = uniqueMetas[uniqueIndex].isSigner || accountMeta.isSigner; } else { uniqueMetas.push(accountMeta); } }); // Sort. Prioritizing first by signer, then by writable uniqueMetas.sort(function (x, y) { if (x.isSigner !== y.isSigner) { // Signers always come before non-signers return x.isSigner ? -1 : 1; } if (x.isWritable !== y.isWritable) { // Writable accounts always come before read-only accounts return x.isWritable ? -1 : 1; } // Otherwise, sort by pubkey, stringwise. const options = { localeMatcher: 'best fit', usage: 'sort', sensitivity: 'variant', ignorePunctuation: false, numeric: false, caseFirst: 'lower' }; return x.pubkey.toBase58().localeCompare(y.pubkey.toBase58(), 'en', options); }); // Move fee payer to the front const feePayerIndex = uniqueMetas.findIndex(x => { return x.pubkey.equals(feePayer); }); if (feePayerIndex > -1) { const [payerMeta] = uniqueMetas.splice(feePayerIndex, 1); payerMeta.isSigner = true; payerMeta.isWritable = true; uniqueMetas.unshift(payerMeta); } else { uniqueMetas.unshift({ pubkey: feePayer, isSigner: true, isWritable: true }); } // Disallow unknown signers for (const signature of this.signatures) { const uniqueIndex = uniqueMetas.findIndex(x => { return x.pubkey.equals(signature.publicKey); }); if (uniqueIndex > -1) { if (!uniqueMetas[uniqueIndex].isSigner) { uniqueMetas[uniqueIndex].isSigner = true; console.warn('Transaction references a signature that is unnecessary, ' + 'only the fee payer and instruction signer accounts should sign a transaction. ' + 'This behavior is deprecated and will throw an error in the next major version release.'); } } else { throw new Error(`unknown signer: ${signature.publicKey.toString()}`); } } let numRequiredSignatures = 0; let numReadonlySignedAccounts = 0; let numReadonlyUnsignedAccounts = 0; // Split out signing from non-signing keys and count header values const signedKeys = []; const unsignedKeys = []; uniqueMetas.forEach(({ pubkey, isSigner, isWritable }) => { if (isSigner) { signedKeys.push(pubkey.toString()); numRequiredSignatures += 1; if (!isWritable) { numReadonlySignedAccounts += 1; } } else { unsignedKeys.push(pubkey.toString()); if (!isWritable) { numReadonlyUnsignedAccounts += 1; } } }); const accountKeys = signedKeys.concat(unsignedKeys); const compiledInstructions = instructions.map(instruction => { const { data, programId } = instruction; return { programIdIndex: accountKeys.indexOf(programId.toString()), accounts: instruction.keys.map(meta => accountKeys.indexOf(meta.pubkey.toString())), data: bs58$1.encode(data) }; }); compiledInstructions.forEach(instruction => { assert$1(instruction.programIdIndex >= 0); instruction.accounts.forEach(keyIndex => assert$1(keyIndex >= 0)); }); return new Message({ header: { numRequiredSignatures, numReadonlySignedAccounts, numReadonlyUnsignedAccounts }, accountKeys, recentBlockhash, instructions: compiledInstructions }); } /** * @internal */ _compile() { const message = this.compileMessage(); const signedKeys = message.accountKeys.slice(0, message.header.numRequiredSignatures); if (this.signatures.length === signedKeys.length) { const valid = this.signatures.every((pair, index) => { return signedKeys[index].equals(pair.publicKey); }); if (valid) return message; } this.signatures = signedKeys.map(publicKey => ({ signature: null, publicKey })); return message; } /** * Get a buffer of the Transaction data that need to be covered by signatures */ serializeMessage() { return this._compile().serialize(); } /** * Get the estimated fee associated with a transaction * * @param {Connection} connection Connection to RPC Endpoint. * * @returns {Promise} The estimated fee for the transaction */ async getEstimatedFee(connection) { return (await connection.getFeeForMessage(this.compileMessage())).value; } /** * Specify the public keys which will be used to sign the Transaction. * The first signer will be used as the transaction fee payer account. * * Signatures can be added with either `partialSign` or `addSignature` * * @deprecated Deprecated since v0.84.0. Only the fee payer needs to be * specified and it can be set in the Transaction constructor or with the * `feePayer` property. */ setSigners(...signers) { if (signers.length === 0) { throw new Error('No signers'); } const seen = new Set(); this.signatures = signers.filter(publicKey => { const key = publicKey.toString(); if (seen.has(key)) { return false; } else { seen.add(key); return true; } }).map(publicKey => ({ signature: null, publicKey })); } /** * Sign the Transaction with the specified signers. Multiple signatures may * be applied to a Transaction. The first signature is considered "primary" * and is used identify and confirm transactions. * * If the Transaction `feePayer` is not set, the first signer will be used * as the transaction fee payer account. * * Transaction fields should not be modified after the first call to `sign`, * as doing so may invalidate the signature and cause the Transaction to be * rejected. * * The Transaction must be assigned a valid `recentBlockhash` before invoking this method * * @param {Array} signers Array of signers that will sign the transaction */ sign(...signers) { if (signers.length === 0) { throw new Error('No signers'); } // Dedupe signers const seen = new Set(); const uniqueSigners = []; for (const signer of signers) { const key = signer.publicKey.toString(); if (seen.has(key)) { continue; } else { seen.add(key); uniqueSigners.push(signer); } } this.signatures = uniqueSigners.map(signer => ({ signature: null, publicKey: signer.publicKey })); const message = this._compile(); this._partialSign(message, ...uniqueSigners); } /** * Partially sign a transaction with the specified accounts. All accounts must * correspond to either the fee payer or a signer account in the transaction * instructions. * * All the caveats from the `sign` method apply to `partialSign` * * @param {Array} signers Array of signers that will sign the transaction */ partialSign(...signers) { if (signers.length === 0) { throw new Error('No signers'); } // Dedupe signers const seen = new Set(); const uniqueSigners = []; for (const signer of signers) { const key = signer.publicKey.toString(); if (seen.has(key)) { continue; } else { seen.add(key); uniqueSigners.push(signer); } } const message = this._compile(); this._partialSign(message, ...uniqueSigners); } /** * @internal */ _partialSign(message, ...signers) { const signData = message.serialize(); signers.forEach(signer => { const signature = sign(signData, signer.secretKey); this._addSignature(signer.publicKey, toBuffer(signature)); }); } /** * Add an externally created signature to a transaction. The public key * must correspond to either the fee payer or a signer account in the transaction * instructions. * * @param {PublicKey} pubkey Public key that will be added to the transaction. * @param {Buffer} signature An externally created signature to add to the transaction. */ addSignature(pubkey, signature) { this._compile(); // Ensure signatures array is populated this._addSignature(pubkey, signature); } /** * @internal */ _addSignature(pubkey, signature) { assert$1(signature.length === 64); const index = this.signatures.findIndex(sigpair => pubkey.equals(sigpair.publicKey)); if (index < 0) { throw new Error(`unknown signer: ${pubkey.toString()}`); } this.signatures[index].signature = buffer.Buffer.from(signature); } /** * Verify signatures of a Transaction * Optional parameter specifies if we're expecting a fully signed Transaction or a partially signed one. * If no boolean is provided, we expect a fully signed Transaction by default. * * @param {boolean} [requireAllSignatures=true] Require a fully signed Transaction */ verifySignatures(requireAllSignatures = true) { const signatureErrors = this._getMessageSignednessErrors(this.serializeMessage(), requireAllSignatures); return !signatureErrors; } /** * @internal */ _getMessageSignednessErrors(message, requireAllSignatures) { const errors = {}; for (const { signature, publicKey } of this.signatures) { if (signature === null) { if (requireAllSignatures) { (errors.missing ||= []).push(publicKey); } } else { if (!verify(signature, message, publicKey.toBytes())) { (errors.invalid ||= []).push(publicKey); } } } return errors.invalid || errors.missing ? errors : undefined; } /** * Serialize the Transaction in the wire format. * * @param {Buffer} [config] Config of transaction. * * @returns {Buffer} Signature of transaction in wire format. */ serialize(config) { const { requireAllSignatures, verifySignatures } = Object.assign({ requireAllSignatures: true, verifySignatures: true }, config); const signData = this.serializeMessage(); if (verifySignatures) { const sigErrors = this._getMessageSignednessErrors(signData, requireAllSignatures); if (sigErrors) { let errorMessage = 'Signature verification failed.'; if (sigErrors.invalid) { errorMessage += `\nInvalid signature for public key${sigErrors.invalid.length === 1 ? '' : '(s)'} [\`${sigErrors.invalid.map(p => p.toBase58()).join('`, `')}\`].`; } if (sigErrors.missing) { errorMessage += `\nMissing signature for public key${sigErrors.missing.length === 1 ? '' : '(s)'} [\`${sigErrors.missing.map(p => p.toBase58()).join('`, `')}\`].`; } throw new Error(errorMessage); } } return this._serialize(signData); } /** * @internal */ _serialize(signData) { const { signatures } = this; const signatureCount = []; encodeLength(signatureCount, signatures.length); const transactionLength = signatureCount.length + signatures.length * 64 + signData.length; const wireTransaction = buffer.Buffer.alloc(transactionLength); assert$1(signatures.length < 256); buffer.Buffer.from(signatureCount).copy(wireTransaction, 0); signatures.forEach(({ signature }, index) => { if (signature !== null) { assert$1(signature.length === 64, `signature has invalid length`); buffer.Buffer.from(signature).copy(wireTransaction, signatureCount.length + index * 64); } }); signData.copy(wireTransaction, signatureCount.length + signatures.length * 64); assert$1(wireTransaction.length <= PACKET_DATA_SIZE, `Transaction too large: ${wireTransaction.length} > ${PACKET_DATA_SIZE}`); return wireTransaction; } /** * Deprecated method * @internal */ get keys() { assert$1(this.instructions.length === 1); return this.instructions[0].keys.map(keyObj => keyObj.pubkey); } /** * Deprecated method * @internal */ get programId() { assert$1(this.instructions.length === 1); return this.instructions[0].programId; } /** * Deprecated method * @internal */ get data() { assert$1(this.instructions.length === 1); return this.instructions[0].data; } /** * Parse a wire transaction into a Transaction object. * * @param {Buffer | Uint8Array | Array} buffer Signature of wire Transaction * * @returns {Transaction} Transaction associated with the signature */ static from(buffer$1) { // Slice up wire data let byteArray = [...buffer$1]; const signatureCount = decodeLength(byteArray); let signatures = []; for (let i = 0; i < signatureCount; i++) { const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES); signatures.push(bs58$1.encode(buffer.Buffer.from(signature))); } return Transaction.populate(Message.from(byteArray), signatures); } /** * Populate Transaction object from message and signatures * * @param {Message} message Message of transaction * @param {Array} signatures List of signatures to assign to the transaction * * @returns {Transaction} The populated Transaction */ static populate(message, signatures = []) { const transaction = new Transaction(); transaction.recentBlockhash = message.recentBlockhash; if (message.header.numRequiredSignatures > 0) { transaction.feePayer = message.accountKeys[0]; } signatures.forEach((signature, index) => { const sigPubkeyPair = { signature: signature == bs58$1.encode(DEFAULT_SIGNATURE) ? null : bs58$1.decode(signature), publicKey: message.accountKeys[index] }; transaction.signatures.push(sigPubkeyPair); }); message.instructions.forEach(instruction => { const keys = instruction.accounts.map(account => { const pubkey = message.accountKeys[account]; return { pubkey, isSigner: transaction.signatures.some(keyObj => keyObj.publicKey.toString() === pubkey.toString()) || message.isAccountSigner(account), isWritable: message.isAccountWritable(account) }; }); transaction.instructions.push(new TransactionInstruction({ keys, programId: message.accountKeys[instruction.programIdIndex], data: bs58$1.decode(instruction.data) })); }); transaction._message = message; transaction._json = transaction.toJSON(); return transaction; } } class TransactionMessage { constructor(args) { this.payerKey = void 0; this.instructions = void 0; this.recentBlockhash = void 0; this.payerKey = args.payerKey; this.instructions = args.instructions; this.recentBlockhash = args.recentBlockhash; } static decompile(message, args) { const { header, compiledInstructions, recentBlockhash } = message; const { numRequiredSignatures, numReadonlySignedAccounts, numReadonlyUnsignedAccounts } = header; const numWritableSignedAccounts = numRequiredSignatures - numReadonlySignedAccounts; assert$1(numWritableSignedAccounts > 0, 'Message header is invalid'); const numWritableUnsignedAccounts = message.staticAccountKeys.length - numRequiredSignatures - numReadonlyUnsignedAccounts; assert$1(numWritableUnsignedAccounts >= 0, 'Message header is invalid'); const accountKeys = message.getAccountKeys(args); const payerKey = accountKeys.get(0); if (payerKey === undefined) { throw new Error('Failed to decompile message because no account keys were found'); } const instructions = []; for (const compiledIx of compiledInstructions) { const keys = []; for (const keyIndex of compiledIx.accountKeyIndexes) { const pubkey = accountKeys.get(keyIndex); if (pubkey === undefined) { throw new Error(`Failed to find key for account key index ${keyIndex}`); } const isSigner = keyIndex < numRequiredSignatures; let isWritable; if (isSigner) { isWritable = keyIndex < numWritableSignedAccounts; } else if (keyIndex < accountKeys.staticAccountKeys.length) { isWritable = keyIndex - numRequiredSignatures < numWritableUnsignedAccounts; } else { isWritable = keyIndex - accountKeys.staticAccountKeys.length < // accountKeysFromLookups cannot be undefined because we already found a pubkey for this index above accountKeys.accountKeysFromLookups.writable.length; } keys.push({ pubkey, isSigner: keyIndex < header.numRequiredSignatures, isWritable }); } const programId = accountKeys.get(compiledIx.programIdIndex); if (programId === undefined) { throw new Error(`Failed to find program id for program id index ${compiledIx.programIdIndex}`); } instructions.push(new TransactionInstruction({ programId, data: toBuffer(compiledIx.data), keys })); } return new TransactionMessage({ payerKey, instructions, recentBlockhash }); } compileToLegacyMessage() { return Message.compile({ payerKey: this.payerKey, recentBlockhash: this.recentBlockhash, instructions: this.instructions }); } compileToV0Message(addressLookupTableAccounts) { return MessageV0.compile({ payerKey: this.payerKey, recentBlockhash: this.recentBlockhash, instructions: this.instructions, addressLookupTableAccounts }); } } /** * Versioned transaction class */ class VersionedTransaction { get version() { return this.message.version; } constructor(message, signatures) { this.signatures = void 0; this.message = void 0; if (signatures !== undefined) { assert$1(signatures.length === message.header.numRequiredSignatures, 'Expected signatures length to be equal to the number of required signatures'); this.signatures = signatures; } else { const defaultSignatures = []; for (let i = 0; i < message.header.numRequiredSignatures; i++) { defaultSignatures.push(new Uint8Array(SIGNATURE_LENGTH_IN_BYTES)); } this.signatures = defaultSignatures; } this.message = message; } serialize() { const serializedMessage = this.message.serialize(); const encodedSignaturesLength = Array(); encodeLength(encodedSignaturesLength, this.signatures.length); const transactionLayout = struct([blob(encodedSignaturesLength.length, 'encodedSignaturesLength'), seq(signature(), this.signatures.length, 'signatures'), blob(serializedMessage.length, 'serializedMessage')]); const serializedTransaction = new Uint8Array(2048); const serializedTransactionLength = transactionLayout.encode({ encodedSignaturesLength: new Uint8Array(encodedSignaturesLength), signatures: this.signatures, serializedMessage }, serializedTransaction); return serializedTransaction.slice(0, serializedTransactionLength); } static deserialize(serializedTransaction) { let byteArray = [...serializedTransaction]; const signatures = []; const signaturesLength = decodeLength(byteArray); for (let i = 0; i < signaturesLength; i++) { signatures.push(new Uint8Array(guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES))); } const message = VersionedMessage.deserialize(new Uint8Array(byteArray)); return new VersionedTransaction(message, signatures); } sign(signers) { const messageData = this.message.serialize(); const signerPubkeys = this.message.staticAccountKeys.slice(0, this.message.header.numRequiredSignatures); for (const signer of signers) { const signerIndex = signerPubkeys.findIndex(pubkey => pubkey.equals(signer.publicKey)); assert$1(signerIndex >= 0, `Cannot sign with non signer key ${signer.publicKey.toBase58()}`); this.signatures[signerIndex] = sign(messageData, signer.secretKey); } } addSignature(publicKey, signature) { assert$1(signature.byteLength === 64, 'Signature must be 64 bytes long'); const signerPubkeys = this.message.staticAccountKeys.slice(0, this.message.header.numRequiredSignatures); const signerIndex = signerPubkeys.findIndex(pubkey => pubkey.equals(publicKey)); assert$1(signerIndex >= 0, `Can not add signature; \`${publicKey.toBase58()}\` is not required to sign this transaction`); this.signatures[signerIndex] = signature; } } // TODO: These constants should be removed in favor of reading them out of a // Syscall account /** * @internal */ const NUM_TICKS_PER_SECOND = 160; /** * @internal */ const DEFAULT_TICKS_PER_SLOT = 64; /** * @internal */ const NUM_SLOTS_PER_SECOND = NUM_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT; /** * @internal */ const MS_PER_SLOT = 1000 / NUM_SLOTS_PER_SECOND; const SYSVAR_CLOCK_PUBKEY = new PublicKey('SysvarC1ock11111111111111111111111111111111'); const SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey('SysvarEpochSchedu1e111111111111111111111111'); const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey('Sysvar1nstructions1111111111111111111111111'); const SYSVAR_RECENT_BLOCKHASHES_PUBKEY = new PublicKey('SysvarRecentB1ockHashes11111111111111111111'); const SYSVAR_RENT_PUBKEY = new PublicKey('SysvarRent111111111111111111111111111111111'); const SYSVAR_REWARDS_PUBKEY = new PublicKey('SysvarRewards111111111111111111111111111111'); const SYSVAR_SLOT_HASHES_PUBKEY = new PublicKey('SysvarS1otHashes111111111111111111111111111'); const SYSVAR_SLOT_HISTORY_PUBKEY = new PublicKey('SysvarS1otHistory11111111111111111111111111'); const SYSVAR_STAKE_HISTORY_PUBKEY = new PublicKey('SysvarStakeHistory1111111111111111111111111'); /** * Sign, send and confirm a transaction. * * If `commitment` option is not specified, defaults to 'max' commitment. * * @param {Connection} connection * @param {Transaction} transaction * @param {Array} signers * @param {ConfirmOptions} [options] * @returns {Promise} */ async function sendAndConfirmTransaction(connection, transaction, signers, options) { const sendOptions = options && { skipPreflight: options.skipPreflight, preflightCommitment: options.preflightCommitment || options.commitment, maxRetries: options.maxRetries, minContextSlot: options.minContextSlot }; const signature = await connection.sendTransaction(transaction, signers, sendOptions); let status; if (transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null) { status = (await connection.confirmTransaction({ abortSignal: options?.abortSignal, signature: signature, blockhash: transaction.recentBlockhash, lastValidBlockHeight: transaction.lastValidBlockHeight }, options && options.commitment)).value; } else if (transaction.minNonceContextSlot != null && transaction.nonceInfo != null) { const { nonceInstruction } = transaction.nonceInfo; const nonceAccountPubkey = nonceInstruction.keys[0].pubkey; status = (await connection.confirmTransaction({ abortSignal: options?.abortSignal, minContextSlot: transaction.minNonceContextSlot, nonceAccountPubkey, nonceValue: transaction.nonceInfo.nonce, signature }, options && options.commitment)).value; } else { if (options?.abortSignal != null) { 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.'); } status = (await connection.confirmTransaction(signature, options && options.commitment)).value; } if (status.err) { throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`); } return signature; } // zzz function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * @internal */ /** * Populate a buffer of instruction data using an InstructionType * @internal */ function encodeData(type, fields) { const allocLength = type.layout.span >= 0 ? type.layout.span : getAlloc(type, fields); const data = buffer.Buffer.alloc(allocLength); const layoutFields = Object.assign({ instruction: type.index }, fields); type.layout.encode(layoutFields, data); return data; } /** * Decode instruction data buffer using an InstructionType * @internal */ function decodeData$1(type, buffer) { let data; try { data = type.layout.decode(buffer); } catch (err) { throw new Error('invalid instruction; ' + err); } if (data.instruction !== type.index) { throw new Error(`invalid instruction; instruction index mismatch ${data.instruction} != ${type.index}`); } return data; } /** * https://github.com/solana-labs/solana/blob/90bedd7e067b5b8f3ddbb45da00a4e9cabb22c62/sdk/src/fee_calculator.rs#L7-L11 * * @internal */ const FeeCalculatorLayout = nu64('lamportsPerSignature'); /** * Calculator for transaction fees. * * @deprecated Deprecated since Solana v1.8.0. */ /** * See https://github.com/solana-labs/solana/blob/0ea2843ec9cdc517572b8e62c959f41b55cf4453/sdk/src/nonce_state.rs#L29-L32 * * @internal */ const NonceAccountLayout = struct([u32('version'), u32('state'), publicKey('authorizedPubkey'), publicKey('nonce'), struct([FeeCalculatorLayout], 'feeCalculator')]); const NONCE_ACCOUNT_LENGTH = NonceAccountLayout.span; /** * A durable nonce is a 32 byte value encoded as a base58 string. */ /** * NonceAccount class */ class NonceAccount { /** * @internal */ constructor(args) { this.authorizedPubkey = void 0; this.nonce = void 0; this.feeCalculator = void 0; this.authorizedPubkey = args.authorizedPubkey; this.nonce = args.nonce; this.feeCalculator = args.feeCalculator; } /** * Deserialize NonceAccount from the account data. * * @param buffer account data * @return NonceAccount */ static fromAccountData(buffer) { const nonceAccount = NonceAccountLayout.decode(toBuffer(buffer), 0); return new NonceAccount({ authorizedPubkey: new PublicKey(nonceAccount.authorizedPubkey), nonce: new PublicKey(nonceAccount.nonce).toString(), feeCalculator: nonceAccount.feeCalculator }); } } var browser$1 = {}; Object.defineProperty(browser$1, "__esModule", { value: true }); /** * Convert a little-endian buffer into a BigInt. * @param buf The little-endian buffer to convert * @returns A BigInt with the little-endian representation of buf. */ function toBigIntLE(buf) { { const reversed = Buffer.from(buf); reversed.reverse(); const hex = reversed.toString('hex'); if (hex.length === 0) { return BigInt(0); } return BigInt(`0x${hex}`); } } var toBigIntLE_1 = browser$1.toBigIntLE = toBigIntLE; /** * Convert a big-endian buffer into a BigInt * @param buf The big-endian buffer to convert. * @returns A BigInt with the big-endian representation of buf. */ function toBigIntBE(buf) { { const hex = buf.toString('hex'); if (hex.length === 0) { return BigInt(0); } return BigInt(`0x${hex}`); } } browser$1.toBigIntBE = toBigIntBE; /** * Convert a BigInt to a little-endian buffer. * @param num The BigInt to convert. * @param width The number of bytes that the resulting buffer should be. * @returns A little-endian buffer representation of num. */ function toBufferLE(num, width) { { const hex = num.toString(16); const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex'); buffer.reverse(); return buffer; } } var toBufferLE_1 = browser$1.toBufferLE = toBufferLE; /** * Convert a BigInt to a big-endian buffer. * @param num The BigInt to convert. * @param width The number of bytes that the resulting buffer should be. * @returns A big-endian buffer representation of num. */ function toBufferBE(num, width) { { const hex = num.toString(16); return Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex'); } } browser$1.toBufferBE = toBufferBE; const encodeDecode = layout => { const decode = layout.decode.bind(layout); const encode = layout.encode.bind(layout); return { decode, encode }; }; const bigInt = length => property => { const layout = blob(length, property); const { encode, decode } = encodeDecode(layout); const bigIntLayout = layout; bigIntLayout.decode = (buffer$1, offset) => { const src = decode(buffer$1, offset); return toBigIntLE_1(buffer.Buffer.from(src)); }; bigIntLayout.encode = (bigInt, buffer, offset) => { const src = toBufferLE_1(bigInt, length); return encode(src, buffer, offset); }; return bigIntLayout; }; const u64 = bigInt(8); /** * Create account system transaction params */ /** * Transfer system transaction params */ /** * Assign system transaction params */ /** * Create account with seed system transaction params */ /** * Create nonce account system transaction params */ /** * Create nonce account with seed system transaction params */ /** * Initialize nonce account system instruction params */ /** * Advance nonce account system instruction params */ /** * Withdraw nonce account system transaction params */ /** * Authorize nonce account system transaction params */ /** * Allocate account system transaction params */ /** * Allocate account with seed system transaction params */ /** * Assign account with seed system transaction params */ /** * Transfer with seed system transaction params */ /** Decoded transfer system transaction instruction */ /** Decoded transferWithSeed system transaction instruction */ /** * System Instruction class */ class SystemInstruction { /** * @internal */ constructor() {} /** * Decode a system instruction and retrieve the instruction type. */ static decodeInstructionType(instruction) { this.checkProgramId(instruction.programId); const instructionTypeLayout = u32('instruction'); const typeIndex = instructionTypeLayout.decode(instruction.data); let type; for (const [ixType, layout] of Object.entries(SYSTEM_INSTRUCTION_LAYOUTS)) { if (layout.index == typeIndex) { type = ixType; break; } } if (!type) { throw new Error('Instruction type incorrect; not a SystemInstruction'); } return type; } /** * Decode a create account system instruction and retrieve the instruction params. */ static decodeCreateAccount(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { lamports, space, programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.Create, instruction.data); return { fromPubkey: instruction.keys[0].pubkey, newAccountPubkey: instruction.keys[1].pubkey, lamports, space, programId: new PublicKey(programId) }; } /** * Decode a transfer system instruction and retrieve the instruction params. */ static decodeTransfer(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { lamports } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.Transfer, instruction.data); return { fromPubkey: instruction.keys[0].pubkey, toPubkey: instruction.keys[1].pubkey, lamports }; } /** * Decode a transfer with seed system instruction and retrieve the instruction params. */ static decodeTransferWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { lamports, seed, programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.TransferWithSeed, instruction.data); return { fromPubkey: instruction.keys[0].pubkey, basePubkey: instruction.keys[1].pubkey, toPubkey: instruction.keys[2].pubkey, lamports, seed, programId: new PublicKey(programId) }; } /** * Decode an allocate system instruction and retrieve the instruction params. */ static decodeAllocate(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 1); const { space } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.Allocate, instruction.data); return { accountPubkey: instruction.keys[0].pubkey, space }; } /** * Decode an allocate with seed system instruction and retrieve the instruction params. */ static decodeAllocateWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 1); const { base, seed, space, programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AllocateWithSeed, instruction.data); return { accountPubkey: instruction.keys[0].pubkey, basePubkey: new PublicKey(base), seed, space, programId: new PublicKey(programId) }; } /** * Decode an assign system instruction and retrieve the instruction params. */ static decodeAssign(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 1); const { programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.Assign, instruction.data); return { accountPubkey: instruction.keys[0].pubkey, programId: new PublicKey(programId) }; } /** * Decode an assign with seed system instruction and retrieve the instruction params. */ static decodeAssignWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 1); const { base, seed, programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AssignWithSeed, instruction.data); return { accountPubkey: instruction.keys[0].pubkey, basePubkey: new PublicKey(base), seed, programId: new PublicKey(programId) }; } /** * Decode a create account with seed system instruction and retrieve the instruction params. */ static decodeCreateWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { base, seed, lamports, space, programId } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.CreateWithSeed, instruction.data); return { fromPubkey: instruction.keys[0].pubkey, newAccountPubkey: instruction.keys[1].pubkey, basePubkey: new PublicKey(base), seed, lamports, space, programId: new PublicKey(programId) }; } /** * Decode a nonce initialize system instruction and retrieve the instruction params. */ static decodeNonceInitialize(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { authorized } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.InitializeNonceAccount, instruction.data); return { noncePubkey: instruction.keys[0].pubkey, authorizedPubkey: new PublicKey(authorized) }; } /** * Decode a nonce advance system instruction and retrieve the instruction params. */ static decodeNonceAdvance(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AdvanceNonceAccount, instruction.data); return { noncePubkey: instruction.keys[0].pubkey, authorizedPubkey: instruction.keys[2].pubkey }; } /** * Decode a nonce withdraw system instruction and retrieve the instruction params. */ static decodeNonceWithdraw(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 5); const { lamports } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.WithdrawNonceAccount, instruction.data); return { noncePubkey: instruction.keys[0].pubkey, toPubkey: instruction.keys[1].pubkey, authorizedPubkey: instruction.keys[4].pubkey, lamports }; } /** * Decode a nonce authorize system instruction and retrieve the instruction params. */ static decodeNonceAuthorize(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { authorized } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AuthorizeNonceAccount, instruction.data); return { noncePubkey: instruction.keys[0].pubkey, authorizedPubkey: instruction.keys[1].pubkey, newAuthorizedPubkey: new PublicKey(authorized) }; } /** * @internal */ static checkProgramId(programId) { if (!programId.equals(SystemProgram.programId)) { throw new Error('invalid instruction; programId is not SystemProgram'); } } /** * @internal */ static checkKeyLength(keys, expectedLength) { if (keys.length < expectedLength) { throw new Error(`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`); } } } /** * An enumeration of valid SystemInstructionType's */ /** * An enumeration of valid system InstructionType's * @internal */ const SYSTEM_INSTRUCTION_LAYOUTS = Object.freeze({ Create: { index: 0, layout: struct([u32('instruction'), ns64('lamports'), ns64('space'), publicKey('programId')]) }, Assign: { index: 1, layout: struct([u32('instruction'), publicKey('programId')]) }, Transfer: { index: 2, layout: struct([u32('instruction'), u64('lamports')]) }, CreateWithSeed: { index: 3, layout: struct([u32('instruction'), publicKey('base'), rustString('seed'), ns64('lamports'), ns64('space'), publicKey('programId')]) }, AdvanceNonceAccount: { index: 4, layout: struct([u32('instruction')]) }, WithdrawNonceAccount: { index: 5, layout: struct([u32('instruction'), ns64('lamports')]) }, InitializeNonceAccount: { index: 6, layout: struct([u32('instruction'), publicKey('authorized')]) }, AuthorizeNonceAccount: { index: 7, layout: struct([u32('instruction'), publicKey('authorized')]) }, Allocate: { index: 8, layout: struct([u32('instruction'), ns64('space')]) }, AllocateWithSeed: { index: 9, layout: struct([u32('instruction'), publicKey('base'), rustString('seed'), ns64('space'), publicKey('programId')]) }, AssignWithSeed: { index: 10, layout: struct([u32('instruction'), publicKey('base'), rustString('seed'), publicKey('programId')]) }, TransferWithSeed: { index: 11, layout: struct([u32('instruction'), u64('lamports'), rustString('seed'), publicKey('programId')]) }, UpgradeNonceAccount: { index: 12, layout: struct([u32('instruction')]) } }); /** * Factory class for transactions to interact with the System program */ class SystemProgram { /** * @internal */ constructor() {} /** * Public key that identifies the System program */ /** * Generate a transaction instruction that creates a new account */ static createAccount(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.Create; const data = encodeData(type, { lamports: params.lamports, space: params.space, programId: toBuffer(params.programId.toBuffer()) }); return new TransactionInstruction({ keys: [{ pubkey: params.fromPubkey, isSigner: true, isWritable: true }, { pubkey: params.newAccountPubkey, isSigner: true, isWritable: true }], programId: this.programId, data }); } /** * Generate a transaction instruction that transfers lamports from one account to another */ static transfer(params) { let data; let keys; if ('basePubkey' in params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.TransferWithSeed; data = encodeData(type, { lamports: BigInt(params.lamports), seed: params.seed, programId: toBuffer(params.programId.toBuffer()) }); keys = [{ pubkey: params.fromPubkey, isSigner: false, isWritable: true }, { pubkey: params.basePubkey, isSigner: true, isWritable: false }, { pubkey: params.toPubkey, isSigner: false, isWritable: true }]; } else { const type = SYSTEM_INSTRUCTION_LAYOUTS.Transfer; data = encodeData(type, { lamports: BigInt(params.lamports) }); keys = [{ pubkey: params.fromPubkey, isSigner: true, isWritable: true }, { pubkey: params.toPubkey, isSigner: false, isWritable: true }]; } return new TransactionInstruction({ keys, programId: this.programId, data }); } /** * Generate a transaction instruction that assigns an account to a program */ static assign(params) { let data; let keys; if ('basePubkey' in params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.AssignWithSeed; data = encodeData(type, { base: toBuffer(params.basePubkey.toBuffer()), seed: params.seed, programId: toBuffer(params.programId.toBuffer()) }); keys = [{ pubkey: params.accountPubkey, isSigner: false, isWritable: true }, { pubkey: params.basePubkey, isSigner: true, isWritable: false }]; } else { const type = SYSTEM_INSTRUCTION_LAYOUTS.Assign; data = encodeData(type, { programId: toBuffer(params.programId.toBuffer()) }); keys = [{ pubkey: params.accountPubkey, isSigner: true, isWritable: true }]; } return new TransactionInstruction({ keys, programId: this.programId, data }); } /** * Generate a transaction instruction that creates a new account at * an address generated with `from`, a seed, and programId */ static createAccountWithSeed(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.CreateWithSeed; const data = encodeData(type, { base: toBuffer(params.basePubkey.toBuffer()), seed: params.seed, lamports: params.lamports, space: params.space, programId: toBuffer(params.programId.toBuffer()) }); let keys = [{ pubkey: params.fromPubkey, isSigner: true, isWritable: true }, { pubkey: params.newAccountPubkey, isSigner: false, isWritable: true }]; if (params.basePubkey != params.fromPubkey) { keys.push({ pubkey: params.basePubkey, isSigner: true, isWritable: false }); } return new TransactionInstruction({ keys, programId: this.programId, data }); } /** * Generate a transaction that creates a new Nonce account */ static createNonceAccount(params) { const transaction = new Transaction(); if ('basePubkey' in params && 'seed' in params) { transaction.add(SystemProgram.createAccountWithSeed({ fromPubkey: params.fromPubkey, newAccountPubkey: params.noncePubkey, basePubkey: params.basePubkey, seed: params.seed, lamports: params.lamports, space: NONCE_ACCOUNT_LENGTH, programId: this.programId })); } else { transaction.add(SystemProgram.createAccount({ fromPubkey: params.fromPubkey, newAccountPubkey: params.noncePubkey, lamports: params.lamports, space: NONCE_ACCOUNT_LENGTH, programId: this.programId })); } const initParams = { noncePubkey: params.noncePubkey, authorizedPubkey: params.authorizedPubkey }; transaction.add(this.nonceInitialize(initParams)); return transaction; } /** * Generate an instruction to initialize a Nonce account */ static nonceInitialize(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.InitializeNonceAccount; const data = encodeData(type, { authorized: toBuffer(params.authorizedPubkey.toBuffer()) }); const instructionData = { keys: [{ pubkey: params.noncePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_RECENT_BLOCKHASHES_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }], programId: this.programId, data }; return new TransactionInstruction(instructionData); } /** * Generate an instruction to advance the nonce in a Nonce account */ static nonceAdvance(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.AdvanceNonceAccount; const data = encodeData(type); const instructionData = { keys: [{ pubkey: params.noncePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_RECENT_BLOCKHASHES_PUBKEY, isSigner: false, isWritable: false }, { pubkey: params.authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }; return new TransactionInstruction(instructionData); } /** * Generate a transaction instruction that withdraws lamports from a Nonce account */ static nonceWithdraw(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.WithdrawNonceAccount; const data = encodeData(type, { lamports: params.lamports }); return new TransactionInstruction({ keys: [{ pubkey: params.noncePubkey, isSigner: false, isWritable: true }, { pubkey: params.toPubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_RECENT_BLOCKHASHES_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, { pubkey: params.authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } /** * Generate a transaction instruction that authorizes a new PublicKey as the authority * on a Nonce account. */ static nonceAuthorize(params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.AuthorizeNonceAccount; const data = encodeData(type, { authorized: toBuffer(params.newAuthorizedPubkey.toBuffer()) }); return new TransactionInstruction({ keys: [{ pubkey: params.noncePubkey, isSigner: false, isWritable: true }, { pubkey: params.authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } /** * Generate a transaction instruction that allocates space in an account without funding */ static allocate(params) { let data; let keys; if ('basePubkey' in params) { const type = SYSTEM_INSTRUCTION_LAYOUTS.AllocateWithSeed; data = encodeData(type, { base: toBuffer(params.basePubkey.toBuffer()), seed: params.seed, space: params.space, programId: toBuffer(params.programId.toBuffer()) }); keys = [{ pubkey: params.accountPubkey, isSigner: false, isWritable: true }, { pubkey: params.basePubkey, isSigner: true, isWritable: false }]; } else { const type = SYSTEM_INSTRUCTION_LAYOUTS.Allocate; data = encodeData(type, { space: params.space }); keys = [{ pubkey: params.accountPubkey, isSigner: true, isWritable: true }]; } return new TransactionInstruction({ keys, programId: this.programId, data }); } } SystemProgram.programId = new PublicKey('11111111111111111111111111111111'); // Keep program chunks under PACKET_DATA_SIZE, leaving enough room for the // rest of the Transaction fields // // TODO: replace 300 with a proper constant for the size of the other // Transaction fields const CHUNK_SIZE = PACKET_DATA_SIZE - 300; /** * Program loader interface */ class Loader { /** * @internal */ constructor() {} /** * Amount of program data placed in each load Transaction */ /** * Minimum number of signatures required to load a program not including * retries * * Can be used to calculate transaction fees */ static getMinNumSignatures(dataLength) { return 2 * ( // Every transaction requires two signatures (payer + program) Math.ceil(dataLength / Loader.chunkSize) + 1 + // Add one for Create transaction 1) // Add one for Finalize transaction ; } /** * Loads a generic program * * @param connection The connection to use * @param payer System account that pays to load the program * @param program Account to load the program into * @param programId Public key that identifies the loader * @param data Program octets * @return true if program was loaded successfully, false if program was already loaded */ static async load(connection, payer, program, programId, data) { { const balanceNeeded = await connection.getMinimumBalanceForRentExemption(data.length); // Fetch program account info to check if it has already been created const programInfo = await connection.getAccountInfo(program.publicKey, 'confirmed'); let transaction = null; if (programInfo !== null) { if (programInfo.executable) { console.error('Program load failed, account is already executable'); return false; } if (programInfo.data.length !== data.length) { transaction = transaction || new Transaction(); transaction.add(SystemProgram.allocate({ accountPubkey: program.publicKey, space: data.length })); } if (!programInfo.owner.equals(programId)) { transaction = transaction || new Transaction(); transaction.add(SystemProgram.assign({ accountPubkey: program.publicKey, programId })); } if (programInfo.lamports < balanceNeeded) { transaction = transaction || new Transaction(); transaction.add(SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey: program.publicKey, lamports: balanceNeeded - programInfo.lamports })); } } else { transaction = new Transaction().add(SystemProgram.createAccount({ fromPubkey: payer.publicKey, newAccountPubkey: program.publicKey, lamports: balanceNeeded > 0 ? balanceNeeded : 1, space: data.length, programId })); } // If the account is already created correctly, skip this step // and proceed directly to loading instructions if (transaction !== null) { await sendAndConfirmTransaction(connection, transaction, [payer, program], { commitment: 'confirmed' }); } } const dataLayout = struct([u32('instruction'), u32('offset'), u32('bytesLength'), u32('bytesLengthPadding'), seq(u8('byte'), offset(u32(), -8), 'bytes')]); const chunkSize = Loader.chunkSize; let offset$1 = 0; let array = data; let transactions = []; while (array.length > 0) { const bytes = array.slice(0, chunkSize); const data = buffer.Buffer.alloc(chunkSize + 16); dataLayout.encode({ instruction: 0, // Load instruction offset: offset$1, bytes: bytes, bytesLength: 0, bytesLengthPadding: 0 }, data); const transaction = new Transaction().add({ keys: [{ pubkey: program.publicKey, isSigner: true, isWritable: true }], programId, data }); transactions.push(sendAndConfirmTransaction(connection, transaction, [payer, program], { commitment: 'confirmed' })); // Delay between sends in an attempt to reduce rate limit errors if (connection._rpcEndpoint.includes('solana.com')) { const REQUESTS_PER_SECOND = 4; await sleep(1000 / REQUESTS_PER_SECOND); } offset$1 += chunkSize; array = array.slice(chunkSize); } await Promise.all(transactions); // Finalize the account loaded with program data for execution { const dataLayout = struct([u32('instruction')]); const data = buffer.Buffer.alloc(dataLayout.span); dataLayout.encode({ instruction: 1 // Finalize instruction }, data); const transaction = new Transaction().add({ keys: [{ pubkey: program.publicKey, isSigner: true, isWritable: true }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }], programId, data }); const deployCommitment = 'processed'; const finalizeSignature = await connection.sendTransaction(transaction, [payer, program], { preflightCommitment: deployCommitment }); const { context, value } = await connection.confirmTransaction({ signature: finalizeSignature, lastValidBlockHeight: transaction.lastValidBlockHeight, blockhash: transaction.recentBlockhash }, deployCommitment); if (value.err) { throw new Error(`Transaction ${finalizeSignature} failed (${JSON.stringify(value)})`); } // We prevent programs from being usable until the slot after their deployment. // See https://github.com/solana-labs/solana/pull/29654 while (true // eslint-disable-line no-constant-condition ) { try { const currentSlot = await connection.getSlot({ commitment: deployCommitment }); if (currentSlot > context.slot) { break; } } catch { /* empty */ } await new Promise(resolve => setTimeout(resolve, Math.round(MS_PER_SLOT / 2))); } } // success return true; } } Loader.chunkSize = CHUNK_SIZE; /** * @deprecated Deprecated since Solana v1.17.20. */ const BPF_LOADER_PROGRAM_ID = new PublicKey('BPFLoader2111111111111111111111111111111111'); /** * Factory class for transactions to interact with a program loader * * @deprecated Deprecated since Solana v1.17.20. */ class BpfLoader { /** * Minimum number of signatures required to load a program not including * retries * * Can be used to calculate transaction fees */ static getMinNumSignatures(dataLength) { return Loader.getMinNumSignatures(dataLength); } /** * Load a SBF program * * @param connection The connection to use * @param payer Account that will pay program loading fees * @param program Account to load the program into * @param elf The entire ELF containing the SBF program * @param loaderProgramId The program id of the BPF loader to use * @return true if program was loaded successfully, false if program was already loaded */ static load(connection, payer, program, elf, loaderProgramId) { return Loader.load(connection, payer, program, loaderProgramId, elf); } } var objToString = Object.prototype.toString; var objKeys = Object.keys || function(obj) { var keys = []; for (var name in obj) { keys.push(name); } return keys; }; function stringify$1(val, isArrayProp) { var i, max, str, keys, key, propVal, toStr; if (val === true) { return "true"; } if (val === false) { return "false"; } switch (typeof val) { case "object": if (val === null) { return null; } else if (val.toJSON && typeof val.toJSON === "function") { return stringify$1(val.toJSON(), isArrayProp); } else { toStr = objToString.call(val); if (toStr === "[object Array]") { str = '['; max = val.length - 1; for(i = 0; i < max; i++) { str += stringify$1(val[i], true) + ','; } if (max > -1) { str += stringify$1(val[i], true); } return str + ']'; } else if (toStr === "[object Object]") { // only object is left keys = objKeys(val).sort(); max = keys.length; str = ""; i = 0; while (i < max) { key = keys[i]; propVal = stringify$1(val[key], false); if (propVal !== undefined) { if (str) { str += ','; } str += JSON.stringify(key) + ':' + propVal; } i++; } return '{' + str + '}'; } else { return JSON.stringify(val); } } case "function": case "undefined": return isArrayProp ? null : undefined; case "string": return JSON.stringify(val); default: return isFinite(val) ? val : null; } } var fastStableStringify = function(val) { var returnVal = stringify$1(val, false); if (returnVal !== undefined) { return ''+ returnVal; } }; var fastStableStringify$1 = /*@__PURE__*/getDefaultExportFromCjs(fastStableStringify); /** * A `StructFailure` represents a single specific failure in validation. */ /** * `StructError` objects are thrown (or returned) when validation fails. * * Validation logic is design to exit early for maximum performance. The error * represents the first error encountered during validation. For more detail, * the `error.failures` property is a generator function that can be run to * continue validation and receive all the failures in the data. */ class StructError extends TypeError { constructor(failure, failures) { let cached; const { message, ...rest } = failure; const { path } = failure; const msg = path.length === 0 ? message : "At path: " + path.join('.') + " -- " + message; super(msg); Object.assign(this, rest); this.name = this.constructor.name; this.failures = () => { var _cached; return (_cached = cached) != null ? _cached : cached = [failure, ...failures()]; }; } } /** * Check if a value is an iterator. */ function isIterable(x) { return isObject(x) && typeof x[Symbol.iterator] === 'function'; } /** * Check if a value is a plain object. */ function isObject(x) { return typeof x === 'object' && x != null; } /** * Return a value as a printable string. */ function print(value) { return typeof value === 'string' ? JSON.stringify(value) : "" + value; } /** * Shifts (removes and returns) the first value from the `input` iterator. * Like `Array.prototype.shift()` but for an `Iterator`. */ function shiftIterator(input) { const { done, value } = input.next(); return done ? undefined : value; } /** * Convert a single validation result to a failure. */ function toFailure(result, context, struct, value) { if (result === true) { return; } else if (result === false) { result = {}; } else if (typeof result === 'string') { result = { message: result }; } const { path, branch } = context; const { type } = struct; const { refinement, message = "Expected a value of type `" + type + "`" + (refinement ? " with refinement `" + refinement + "`" : '') + ", but received: `" + print(value) + "`" } = result; return { value, type, refinement, key: path[path.length - 1], path, branch, ...result, message }; } /** * Convert a validation result to an iterable of failures. */ function* toFailures(result, context, struct, value) { if (!isIterable(result)) { result = [result]; } for (const r of result) { const failure = toFailure(r, context, struct, value); if (failure) { yield failure; } } } /** * Check a value against a struct, traversing deeply into nested values, and * returning an iterator of failures or success. */ function* run(value, struct, options = {}) { const { path = [], branch = [value], coerce = false, mask = false } = options; const ctx = { path, branch }; if (coerce) { value = struct.coercer(value, ctx); if (mask && struct.type !== 'type' && isObject(struct.schema) && isObject(value) && !Array.isArray(value)) { for (const key in value) { if (struct.schema[key] === undefined) { delete value[key]; } } } } let valid = true; for (const failure of struct.validator(value, ctx)) { valid = false; yield [failure, undefined]; } for (let [k, v, s] of struct.entries(value, ctx)) { const ts = run(v, s, { path: k === undefined ? path : [...path, k], branch: k === undefined ? branch : [...branch, v], coerce, mask }); for (const t of ts) { if (t[0]) { valid = false; yield [t[0], undefined]; } else if (coerce) { v = t[1]; if (k === undefined) { value = v; } else if (value instanceof Map) { value.set(k, v); } else if (value instanceof Set) { value.add(v); } else if (isObject(value)) { value[k] = v; } } } } if (valid) { for (const failure of struct.refiner(value, ctx)) { valid = false; yield [failure, undefined]; } } if (valid) { yield [undefined, value]; } } /** * `Struct` objects encapsulate the validation logic for a specific type of * values. Once constructed, you use the `assert`, `is` or `validate` helpers to * validate unknown input data against the struct. */ class Struct { constructor(props) { const { type, schema, validator, refiner, coercer = value => value, entries = function* () {} } = props; this.type = type; this.schema = schema; this.entries = entries; this.coercer = coercer; if (validator) { this.validator = (value, context) => { const result = validator(value, context); return toFailures(result, context, this, value); }; } else { this.validator = () => []; } if (refiner) { this.refiner = (value, context) => { const result = refiner(value, context); return toFailures(result, context, this, value); }; } else { this.refiner = () => []; } } /** * Assert that a value passes the struct's validation, throwing if it doesn't. */ assert(value) { return assert(value, this); } /** * Create a value with the struct's coercion logic, then validate it. */ create(value) { return create(value, this); } /** * Check if a value passes the struct's validation. */ is(value) { return is(value, this); } /** * Mask a value, coercing and validating it, but returning only the subset of * properties defined by the struct's schema. */ mask(value) { return mask(value, this); } /** * Validate a value with the struct's validation logic, returning a tuple * representing the result. * * You may optionally pass `true` for the `withCoercion` argument to coerce * the value before attempting to validate it. If you do, the result will * contain the coerced result when successful. */ validate(value, options = {}) { return validate$1(value, this, options); } } /** * Assert that a value passes a struct, throwing if it doesn't. */ function assert(value, struct) { const result = validate$1(value, struct); if (result[0]) { throw result[0]; } } /** * Create a value with the coercion logic of struct and validate it. */ function create(value, struct) { const result = validate$1(value, struct, { coerce: true }); if (result[0]) { throw result[0]; } else { return result[1]; } } /** * Mask a value, returning only the subset of properties defined by a struct. */ function mask(value, struct) { const result = validate$1(value, struct, { coerce: true, mask: true }); if (result[0]) { throw result[0]; } else { return result[1]; } } /** * Check if a value passes a struct. */ function is(value, struct) { const result = validate$1(value, struct); return !result[0]; } /** * Validate a value against a struct, returning an error if invalid, or the * value (with potential coercion) if valid. */ function validate$1(value, struct, options = {}) { const tuples = run(value, struct, options); const tuple = shiftIterator(tuples); if (tuple[0]) { const error = new StructError(tuple[0], function* () { for (const t of tuples) { if (t[0]) { yield t[0]; } } }); return [error, undefined]; } else { const v = tuple[1]; return [undefined, v]; } } /** * Define a new struct type with a custom validation function. */ function define(name, validator) { return new Struct({ type: name, schema: null, validator }); } /** * Ensure that any value passes validation. */ function any() { return define('any', () => true); } function array(Element) { return new Struct({ type: 'array', schema: Element, *entries(value) { if (Element && Array.isArray(value)) { for (const [i, v] of value.entries()) { yield [i, v, Element]; } } }, coercer(value) { return Array.isArray(value) ? value.slice() : value; }, validator(value) { return Array.isArray(value) || "Expected an array value, but received: " + print(value); } }); } /** * Ensure that a value is a boolean. */ function boolean() { return define('boolean', value => { return typeof value === 'boolean'; }); } /** * Ensure that a value is an instance of a specific class. */ function instance(Class) { return define('instance', value => { return value instanceof Class || "Expected a `" + Class.name + "` instance, but received: " + print(value); }); } function literal(constant) { const description = print(constant); const t = typeof constant; return new Struct({ type: 'literal', schema: t === 'string' || t === 'number' || t === 'boolean' ? constant : null, validator(value) { return value === constant || "Expected the literal `" + description + "`, but received: " + print(value); } }); } /** * Ensure that no value ever passes validation. */ function never() { return define('never', () => false); } /** * Augment an existing struct to allow `null` values. */ function nullable(struct) { return new Struct({ ...struct, validator: (value, ctx) => value === null || struct.validator(value, ctx), refiner: (value, ctx) => value === null || struct.refiner(value, ctx) }); } /** * Ensure that a value is a number. */ function number() { return define('number', value => { return typeof value === 'number' && !isNaN(value) || "Expected a number, but received: " + print(value); }); } /** * Augment a struct to allow `undefined` values. */ function optional(struct) { return new Struct({ ...struct, validator: (value, ctx) => value === undefined || struct.validator(value, ctx), refiner: (value, ctx) => value === undefined || struct.refiner(value, ctx) }); } /** * Ensure that a value is an object with keys and values of specific types, but * without ensuring any specific shape of properties. * * Like TypeScript's `Record` utility. */ function record(Key, Value) { return new Struct({ type: 'record', schema: null, *entries(value) { if (isObject(value)) { for (const k in value) { const v = value[k]; yield [k, k, Key]; yield [k, v, Value]; } } }, validator(value) { return isObject(value) || "Expected an object, but received: " + print(value); } }); } /** * Ensure that a value is a string. */ function string() { return define('string', value => { return typeof value === 'string' || "Expected a string, but received: " + print(value); }); } function tuple(Elements) { const Never = never(); return new Struct({ type: 'tuple', schema: null, *entries(value) { if (Array.isArray(value)) { const length = Math.max(Elements.length, value.length); for (let i = 0; i < length; i++) { yield [i, value[i], Elements[i] || Never]; } } }, validator(value) { return Array.isArray(value) || "Expected an array, but received: " + print(value); } }); } /** * Ensure that a value has a set of known properties of specific types. * * Note: Unrecognized properties are allowed and untouched. This is similar to * how TypeScript's structural typing works. */ function type(schema) { const keys = Object.keys(schema); return new Struct({ type: 'type', schema, *entries(value) { if (isObject(value)) { for (const k of keys) { yield [k, value[k], schema[k]]; } } }, validator(value) { return isObject(value) || "Expected an object, but received: " + print(value); } }); } function union(Structs) { const description = Structs.map(s => s.type).join(' | '); return new Struct({ type: 'union', schema: null, validator(value, ctx) { const failures = []; for (const S of Structs) { const [...tuples] = run(value, S, ctx); const [first] = tuples; if (!first[0]) { return []; } else { for (const [failure] of tuples) { if (failure) { failures.push(failure); } } } } return ["Expected the value to satisfy a union of `" + description + "`, but received: " + print(value), ...failures]; } }); } /** * Ensure that any value passes validation, without widening its type to `any`. */ function unknown() { return define('unknown', () => true); } /** * Augment a `Struct` to add an additional coercion step to its input. * * This allows you to transform input data before validating it, to increase the * likelihood that it passes validation—for example for default values, parsing * different formats, etc. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ function coerce(struct, condition, coercer) { return new Struct({ ...struct, coercer: (value, ctx) => { return is(value, condition) ? struct.coercer(coercer(value, ctx), ctx) : struct.coercer(value, ctx); } }); } // Unique ID creation requires a high quality random # generator. In the browser we therefore // require the crypto API and do not support built-in fallback to lower quality random number // generators (like Math.random()). var getRandomValues; var rnds8 = new Uint8Array(16); function rng() { // lazy load so that environments that need to polyfill have a chance to do so if (!getRandomValues) { // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, // find the complete implementation of crypto (msCrypto) on IE11. getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto); if (!getRandomValues) { throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); } } return getRandomValues(rnds8); } var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; function validate(uuid) { return typeof uuid === 'string' && REGEX.test(uuid); } /** * Convert array of 16 byte values to UUID string format of the form: * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ var byteToHex = []; for (var i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).substr(1)); } function stringify(arr) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; // Note: Be careful editing this code! It's been tuned for performance // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one // of the following: // - One or more input array values don't map to a hex octet (leading to // "undefined" in the uuid) // - Invalid input values for the RFC `version` or `variant` fields if (!validate(uuid)) { throw TypeError('Stringified UUID is invalid'); } return uuid; } // // Inspired by https://github.com/LiosK/UUID.js // and http://docs.python.org/library/uuid.html var _nodeId; var _clockseq; // Previous uuid creation time var _lastMSecs = 0; var _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details function v1(options, buf, offset) { var i = buf && offset || 0; var b = buf || new Array(16); options = options || {}; var node = options.node || _nodeId; var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not // specified. We do this lazily to minimize issues related to insufficient // system entropy. See #189 if (node == null || clockseq == null) { var seedBytes = options.random || (options.rng || rng)(); if (node == null) { // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; } if (clockseq == null) { // Per 4.2.2, randomize (14 bit) clockseq clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; } } // UUID timestamps are 100 nano-second units since the Gregorian epoch, // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. var msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock // cycle to simulate higher resolution clock var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression if (dt < 0 && options.clockseq === undefined) { clockseq = clockseq + 1 & 0x3fff; } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new // time interval if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { nsecs = 0; } // Per 4.2.1.2 Throw error if too many uuids are requested if (nsecs >= 10000) { throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); } _lastMSecs = msecs; _lastNSecs = nsecs; _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch msecs += 12219292800000; // `time_low` var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; b[i++] = tl >>> 24 & 0xff; b[i++] = tl >>> 16 & 0xff; b[i++] = tl >>> 8 & 0xff; b[i++] = tl & 0xff; // `time_mid` var tmh = msecs / 0x100000000 * 10000 & 0xfffffff; b[i++] = tmh >>> 8 & 0xff; b[i++] = tmh & 0xff; // `time_high_and_version` b[i++] = tmh >>> 24 & 0xf | 0x10; // include version b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` b[i++] = clockseq & 0xff; // `node` for (var n = 0; n < 6; ++n) { b[i + n] = node[n]; } return buf || stringify(b); } function parse(uuid) { if (!validate(uuid)) { throw TypeError('Invalid UUID'); } var v; var arr = new Uint8Array(16); // Parse ########-....-....-....-............ arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; arr[1] = v >>> 16 & 0xff; arr[2] = v >>> 8 & 0xff; arr[3] = v & 0xff; // Parse ........-####-....-....-............ arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; arr[5] = v & 0xff; // Parse ........-....-####-....-............ arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; arr[7] = v & 0xff; // Parse ........-....-....-####-............ arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; arr[9] = v & 0xff; // Parse ........-....-....-....-############ // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; arr[11] = v / 0x100000000 & 0xff; arr[12] = v >>> 24 & 0xff; arr[13] = v >>> 16 & 0xff; arr[14] = v >>> 8 & 0xff; arr[15] = v & 0xff; return arr; } function stringToBytes(str) { str = unescape(encodeURIComponent(str)); // UTF8 escape var bytes = []; for (var i = 0; i < str.length; ++i) { bytes.push(str.charCodeAt(i)); } return bytes; } var DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; var URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; function v35 (name, version, hashfunc) { function generateUUID(value, namespace, buf, offset) { if (typeof value === 'string') { value = stringToBytes(value); } if (typeof namespace === 'string') { namespace = parse(namespace); } if (namespace.length !== 16) { throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); } // Compute hash of namespace and value, Per 4.3 // Future: Use spread syntax when supported on all platforms, e.g. `bytes = // hashfunc([...namespace, ... value])` var bytes = new Uint8Array(16 + value.length); bytes.set(namespace); bytes.set(value, namespace.length); bytes = hashfunc(bytes); bytes[6] = bytes[6] & 0x0f | version; bytes[8] = bytes[8] & 0x3f | 0x80; if (buf) { offset = offset || 0; for (var i = 0; i < 16; ++i) { buf[offset + i] = bytes[i]; } return buf; } return stringify(bytes); } // Function#name is not settable on some platforms (#270) try { generateUUID.name = name; // eslint-disable-next-line no-empty } catch (err) {} // For CommonJS default export support generateUUID.DNS = DNS; generateUUID.URL = URL; return generateUUID; } /* * Browser-compatible JavaScript MD5 * * Modification of JavaScript MD5 * https://github.com/blueimp/JavaScript-MD5 * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * https://opensource.org/licenses/MIT * * Based on * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ function md5(bytes) { if (typeof bytes === 'string') { var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape bytes = new Uint8Array(msg.length); for (var i = 0; i < msg.length; ++i) { bytes[i] = msg.charCodeAt(i); } } return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8)); } /* * Convert an array of little-endian words to an array of bytes */ function md5ToHexEncodedArray(input) { var output = []; var length32 = input.length * 32; var hexTab = '0123456789abcdef'; for (var i = 0; i < length32; i += 8) { var x = input[i >> 5] >>> i % 32 & 0xff; var hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16); output.push(hex); } return output; } /** * Calculate output length with padding and bit length */ function getOutputLength(inputLength8) { return (inputLength8 + 64 >>> 9 << 4) + 14 + 1; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function wordsToMd5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << len % 32; x[getOutputLength(len) - 1] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = md5ff(a, b, c, d, x[i], 7, -680876936); d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); c = md5ff(c, d, a, b, x[i + 10], 17, -42063); b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); b = md5gg(b, c, d, a, x[i], 20, -373897302); a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); a = md5hh(a, b, c, d, x[i + 5], 4, -378558); d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); d = md5hh(d, a, b, c, x[i], 11, -358537222); c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); a = md5ii(a, b, c, d, x[i], 6, -198630844); d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); a = safeAdd(a, olda); b = safeAdd(b, oldb); c = safeAdd(c, oldc); d = safeAdd(d, oldd); } return [a, b, c, d]; } /* * Convert an array bytes to an array of little-endian words * Characters >255 have their high-byte silently ignored. */ function bytesToWords(input) { if (input.length === 0) { return []; } var length8 = input.length * 8; var output = new Uint32Array(getOutputLength(length8)); for (var i = 0; i < length8; i += 8) { output[i >> 5] |= (input[i / 8] & 0xff) << i % 32; } return output; } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safeAdd(x, y) { var lsw = (x & 0xffff) + (y & 0xffff); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return msw << 16 | lsw & 0xffff; } /* * Bitwise rotate a 32-bit number to the left. */ function bitRotateLeft(num, cnt) { return num << cnt | num >>> 32 - cnt; } /* * These functions implement the four basic operations the algorithm uses. */ function md5cmn(q, a, b, x, s, t) { return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); } function md5ff(a, b, c, d, x, s, t) { return md5cmn(b & c | ~b & d, a, b, x, s, t); } function md5gg(a, b, c, d, x, s, t) { return md5cmn(b & d | c & ~d, a, b, x, s, t); } function md5hh(a, b, c, d, x, s, t) { return md5cmn(b ^ c ^ d, a, b, x, s, t); } function md5ii(a, b, c, d, x, s, t) { return md5cmn(c ^ (b | ~d), a, b, x, s, t); } var v3 = v35('v3', 0x30, md5); var v3$1 = v3; function v4(options, buf, offset) { options = options || {}; var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = rnds[6] & 0x0f | 0x40; rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided if (buf) { offset = offset || 0; for (var i = 0; i < 16; ++i) { buf[offset + i] = rnds[i]; } return buf; } return stringify(rnds); } // Adapted from Chris Veness' SHA1 code at // http://www.movable-type.co.uk/scripts/sha1.html function f(s, x, y, z) { switch (s) { case 0: return x & y ^ ~x & z; case 1: return x ^ y ^ z; case 2: return x & y ^ x & z ^ y & z; case 3: return x ^ y ^ z; } } function ROTL(x, n) { return x << n | x >>> 32 - n; } function sha1(bytes) { var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; var H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; if (typeof bytes === 'string') { var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape bytes = []; for (var i = 0; i < msg.length; ++i) { bytes.push(msg.charCodeAt(i)); } } else if (!Array.isArray(bytes)) { // Convert Array-like to Array bytes = Array.prototype.slice.call(bytes); } bytes.push(0x80); var l = bytes.length / 4 + 2; var N = Math.ceil(l / 16); var M = new Array(N); for (var _i = 0; _i < N; ++_i) { var arr = new Uint32Array(16); for (var j = 0; j < 16; ++j) { arr[j] = bytes[_i * 64 + j * 4] << 24 | bytes[_i * 64 + j * 4 + 1] << 16 | bytes[_i * 64 + j * 4 + 2] << 8 | bytes[_i * 64 + j * 4 + 3]; } M[_i] = arr; } M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32); M[N - 1][14] = Math.floor(M[N - 1][14]); M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff; for (var _i2 = 0; _i2 < N; ++_i2) { var W = new Uint32Array(80); for (var t = 0; t < 16; ++t) { W[t] = M[_i2][t]; } for (var _t = 16; _t < 80; ++_t) { W[_t] = ROTL(W[_t - 3] ^ W[_t - 8] ^ W[_t - 14] ^ W[_t - 16], 1); } var a = H[0]; var b = H[1]; var c = H[2]; var d = H[3]; var e = H[4]; for (var _t2 = 0; _t2 < 80; ++_t2) { var s = Math.floor(_t2 / 20); var T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[_t2] >>> 0; e = d; d = c; c = ROTL(b, 30) >>> 0; b = a; a = T; } H[0] = H[0] + a >>> 0; H[1] = H[1] + b >>> 0; H[2] = H[2] + c >>> 0; H[3] = H[3] + d >>> 0; H[4] = H[4] + e >>> 0; } return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff]; } var v5 = v35('v5', 0x50, sha1); var v5$1 = v5; var nil = '00000000-0000-0000-0000-000000000000'; function version(uuid) { if (!validate(uuid)) { throw TypeError('Invalid UUID'); } return parseInt(uuid.substr(14, 1), 16); } var esmBrowser = /*#__PURE__*/Object.freeze({ __proto__: null, NIL: nil, parse: parse, stringify: stringify, v1: v1, v3: v3$1, v4: v4, v5: v5$1, validate: validate, version: version }); var require$$0 = /*@__PURE__*/getAugmentedNamespace(esmBrowser); const uuid$1 = require$$0.v4; /** * Generates a JSON-RPC 1.0 or 2.0 request * @param {String} method Name of method to call * @param {Array|Object} params Array of parameters passed to the method as specified, or an object of parameter names and corresponding value * @param {String|Number|null} [id] Request ID can be a string, number, null for explicit notification or left out for automatic generation * @param {Object} [options] * @param {Number} [options.version=2] JSON-RPC version to use (1 or 2) * @param {Boolean} [options.notificationIdNull=false] When true, version 2 requests will set id to null instead of omitting it * @param {Function} [options.generator] Passed the request, and the options object and is expected to return a request ID * @throws {TypeError} If any of the parameters are invalid * @return {Object} A JSON-RPC 1.0 or 2.0 request * @memberOf Utils */ const generateRequest$1 = function(method, params, id, options) { if(typeof method !== 'string') { throw new TypeError(method + ' must be a string'); } options = options || {}; // check valid version provided const version = typeof options.version === 'number' ? options.version : 2; if (version !== 1 && version !== 2) { throw new TypeError(version + ' must be 1 or 2'); } const request = { method: method }; if(version === 2) { request.jsonrpc = '2.0'; } if(params) { // params given, but invalid? if(typeof params !== 'object' && !Array.isArray(params)) { throw new TypeError(params + ' must be an object, array or omitted'); } request.params = params; } // if id was left out, generate one (null means explicit notification) if(typeof(id) === 'undefined') { const generator = typeof options.generator === 'function' ? options.generator : function() { return uuid$1(); }; request.id = generator(request, options); } else if (version === 2 && id === null) { // we have a version 2 notification if (options.notificationIdNull) { request.id = null; // id will not be set at all unless option provided } } else { request.id = id; } return request; }; var generateRequest_1 = generateRequest$1; const uuid = require$$0.v4; const generateRequest = generateRequest_1; /** * Constructor for a Jayson Browser Client that does not depend any node.js core libraries * @class ClientBrowser * @param {Function} callServer Method that calls the server, receives the stringified request and a regular node-style callback * @param {Object} [options] * @param {Function} [options.reviver] Reviver function for JSON * @param {Function} [options.replacer] Replacer function for JSON * @param {Number} [options.version=2] JSON-RPC version to use (1|2) * @param {Function} [options.generator] Function to use for generating request IDs * @param {Boolean} [options.notificationIdNull=false] When true, version 2 requests will set id to null instead of omitting it * @return {ClientBrowser} */ const ClientBrowser = function(callServer, options) { if(!(this instanceof ClientBrowser)) { return new ClientBrowser(callServer, options); } if (!options) { options = {}; } this.options = { reviver: typeof options.reviver !== 'undefined' ? options.reviver : null, replacer: typeof options.replacer !== 'undefined' ? options.replacer : null, generator: typeof options.generator !== 'undefined' ? options.generator : function() { return uuid(); }, version: typeof options.version !== 'undefined' ? options.version : 2, notificationIdNull: typeof options.notificationIdNull === 'boolean' ? options.notificationIdNull : false, }; this.callServer = callServer; }; var browser = ClientBrowser; /** * Creates a request and dispatches it if given a callback. * @param {String|Array} method A batch request if passed an Array, or a method name if passed a String * @param {Array|Object} [params] Parameters for the method * @param {String|Number} [id] Optional id. If undefined an id will be generated. If null it creates a notification request * @param {Function} [callback] Request callback. If specified, executes the request rather than only returning it. * @throws {TypeError} Invalid parameters * @return {Object} JSON-RPC 1.0 or 2.0 compatible request */ ClientBrowser.prototype.request = function(method, params, id, callback) { const self = this; let request = null; // is this a batch request? const isBatch = Array.isArray(method) && typeof params === 'function'; if (this.options.version === 1 && isBatch) { throw new TypeError('JSON-RPC 1.0 does not support batching'); } // is this a raw request? const isRaw = !isBatch && method && typeof method === 'object' && typeof params === 'function'; if(isBatch || isRaw) { callback = params; request = method; } else { if(typeof id === 'function') { callback = id; // specifically undefined because "null" is a notification request id = undefined; } const hasCallback = typeof callback === 'function'; try { request = generateRequest(method, params, id, { generator: this.options.generator, version: this.options.version, notificationIdNull: this.options.notificationIdNull, }); } catch(err) { if(hasCallback) { return callback(err); } throw err; } // no callback means we should just return a raw request if(!hasCallback) { return request; } } let message; try { message = JSON.stringify(request, this.options.replacer); } catch(err) { return callback(err); } this.callServer(message, function(err, response) { self._parseResponse(err, response, callback); }); // always return the raw request return request; }; /** * Parses a response from a server * @param {Object} err Error to pass on that is unrelated to the actual response * @param {String} responseText JSON-RPC 1.0 or 2.0 response * @param {Function} callback Callback that will receive different arguments depending on the amount of parameters * @private */ ClientBrowser.prototype._parseResponse = function(err, responseText, callback) { if(err) { callback(err); return; } if(!responseText) { // empty response text, assume that is correct because it could be a // notification which jayson does not give any body for return callback(); } let response; try { response = JSON.parse(responseText, this.options.reviver); } catch(err) { return callback(err); } if(callback.length === 3) { // if callback length is 3, we split callback arguments on error and response // is batch response? if(Array.isArray(response)) { // neccesary to split strictly on validity according to spec here const isError = function(res) { return typeof res.error !== 'undefined'; }; const isNotError = function (res) { return !isError(res); }; return callback(null, response.filter(isError), response.filter(isNotError)); } else { // split regardless of validity return callback(null, response.error, response.result); } } callback(null, response); }; var RpcClient = /*@__PURE__*/getDefaultExportFromCjs(browser); const MINIMUM_SLOT_PER_EPOCH = 32; // Returns the number of trailing zeros in the binary representation of self. function trailingZeros(n) { let trailingZeros = 0; while (n > 1) { n /= 2; trailingZeros++; } return trailingZeros; } // Returns the smallest power of two greater than or equal to n function nextPowerOfTwo(n) { if (n === 0) return 1; n--; n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16; n |= n >> 32; return n + 1; } /** * Epoch schedule * (see https://docs.solana.com/terminology#epoch) * Can be retrieved with the {@link Connection.getEpochSchedule} method */ class EpochSchedule { constructor(slotsPerEpoch, leaderScheduleSlotOffset, warmup, firstNormalEpoch, firstNormalSlot) { /** The maximum number of slots in each epoch */ this.slotsPerEpoch = void 0; /** The number of slots before beginning of an epoch to calculate a leader schedule for that epoch */ this.leaderScheduleSlotOffset = void 0; /** Indicates whether epochs start short and grow */ this.warmup = void 0; /** The first epoch with `slotsPerEpoch` slots */ this.firstNormalEpoch = void 0; /** The first slot of `firstNormalEpoch` */ this.firstNormalSlot = void 0; this.slotsPerEpoch = slotsPerEpoch; this.leaderScheduleSlotOffset = leaderScheduleSlotOffset; this.warmup = warmup; this.firstNormalEpoch = firstNormalEpoch; this.firstNormalSlot = firstNormalSlot; } getEpoch(slot) { return this.getEpochAndSlotIndex(slot)[0]; } getEpochAndSlotIndex(slot) { if (slot < this.firstNormalSlot) { const epoch = trailingZeros(nextPowerOfTwo(slot + MINIMUM_SLOT_PER_EPOCH + 1)) - trailingZeros(MINIMUM_SLOT_PER_EPOCH) - 1; const epochLen = this.getSlotsInEpoch(epoch); const slotIndex = slot - (epochLen - MINIMUM_SLOT_PER_EPOCH); return [epoch, slotIndex]; } else { const normalSlotIndex = slot - this.firstNormalSlot; const normalEpochIndex = Math.floor(normalSlotIndex / this.slotsPerEpoch); const epoch = this.firstNormalEpoch + normalEpochIndex; const slotIndex = normalSlotIndex % this.slotsPerEpoch; return [epoch, slotIndex]; } } getFirstSlotInEpoch(epoch) { if (epoch <= this.firstNormalEpoch) { return (Math.pow(2, epoch) - 1) * MINIMUM_SLOT_PER_EPOCH; } else { return (epoch - this.firstNormalEpoch) * this.slotsPerEpoch + this.firstNormalSlot; } } getLastSlotInEpoch(epoch) { return this.getFirstSlotInEpoch(epoch) + this.getSlotsInEpoch(epoch) - 1; } getSlotsInEpoch(epoch) { if (epoch < this.firstNormalEpoch) { return Math.pow(2, epoch + trailingZeros(MINIMUM_SLOT_PER_EPOCH)); } else { return this.slotsPerEpoch; } } } class SendTransactionError extends Error { constructor(message, logs) { super(message); this.logs = void 0; this.logs = logs; } } // Keep in sync with client/src/rpc_custom_errors.rs // Typescript `enums` thwart tree-shaking. See https://bargsten.org/jsts/enums/ const SolanaJSONRPCErrorCode = { JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: -32001, JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE: -32002, JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE: -32003, JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: -32004, JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY: -32005, JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: -32006, JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: -32007, JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: -32008, JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: -32009, JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX: -32010, JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE: -32011, JSON_RPC_SCAN_ERROR: -32012, JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_LEN_MISMATCH: -32013, JSON_RPC_SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET: -32014, JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION: -32015, JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED: -32016 }; class SolanaJSONRPCError extends Error { constructor({ code, message, data }, customMessage) { super(customMessage != null ? `${customMessage}: ${message}` : message); this.code = void 0; this.data = void 0; this.code = code; this.data = data; this.name = 'SolanaJSONRPCError'; } } var fetchImpl = globalThis.fetch; var client = {}; var interopRequireDefault = {exports: {}}; (function (module) { function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } module.exports = _interopRequireDefault, module.exports.__esModule = true, module.exports["default"] = module.exports; } (interopRequireDefault)); var interopRequireDefaultExports = interopRequireDefault.exports; var regeneratorRuntime$1 = {exports: {}}; var _typeof = {exports: {}}; var hasRequired_typeof; function require_typeof () { if (hasRequired_typeof) return _typeof.exports; hasRequired_typeof = 1; (function (module) { function _typeof(o) { "@babel/helpers - typeof"; return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(o); } module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports; } (_typeof)); return _typeof.exports; } var hasRequiredRegeneratorRuntime; function requireRegeneratorRuntime () { if (hasRequiredRegeneratorRuntime) return regeneratorRuntime$1.exports; hasRequiredRegeneratorRuntime = 1; (function (module) { var _typeof = require_typeof()["default"]; function _regeneratorRuntime() { module.exports = _regeneratorRuntime = function _regeneratorRuntime() { return e; }, module.exports.__esModule = true, module.exports["default"] = module.exports; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; } module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports; } (regeneratorRuntime$1)); return regeneratorRuntime$1.exports; } var regenerator; var hasRequiredRegenerator; function requireRegenerator () { if (hasRequiredRegenerator) return regenerator; hasRequiredRegenerator = 1; // TODO(Babel 8): Remove this file. var runtime = requireRegeneratorRuntime()(); regenerator = runtime; // Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736= try { regeneratorRuntime = runtime; } catch (accidentalStrictMode) { if (typeof globalThis === "object") { globalThis.regeneratorRuntime = runtime; } else { Function("r", "regeneratorRuntime = r")(runtime); } } return regenerator; } var asyncToGenerator = {exports: {}}; var hasRequiredAsyncToGenerator; function requireAsyncToGenerator () { if (hasRequiredAsyncToGenerator) return asyncToGenerator.exports; hasRequiredAsyncToGenerator = 1; (function (module) { function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } module.exports = _asyncToGenerator, module.exports.__esModule = true, module.exports["default"] = module.exports; } (asyncToGenerator)); return asyncToGenerator.exports; } var classCallCheck = {exports: {}}; var hasRequiredClassCallCheck; function requireClassCallCheck () { if (hasRequiredClassCallCheck) return classCallCheck.exports; hasRequiredClassCallCheck = 1; (function (module) { function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } module.exports = _classCallCheck, module.exports.__esModule = true, module.exports["default"] = module.exports; } (classCallCheck)); return classCallCheck.exports; } var createClass = {exports: {}}; var toPropertyKey = {exports: {}}; var toPrimitive = {exports: {}}; var hasRequiredToPrimitive; function requireToPrimitive () { if (hasRequiredToPrimitive) return toPrimitive.exports; hasRequiredToPrimitive = 1; (function (module) { var _typeof = require_typeof()["default"]; function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } module.exports = _toPrimitive, module.exports.__esModule = true, module.exports["default"] = module.exports; } (toPrimitive)); return toPrimitive.exports; } var hasRequiredToPropertyKey; function requireToPropertyKey () { if (hasRequiredToPropertyKey) return toPropertyKey.exports; hasRequiredToPropertyKey = 1; (function (module) { var _typeof = require_typeof()["default"]; var toPrimitive = requireToPrimitive(); function _toPropertyKey(arg) { var key = toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } module.exports = _toPropertyKey, module.exports.__esModule = true, module.exports["default"] = module.exports; } (toPropertyKey)); return toPropertyKey.exports; } var hasRequiredCreateClass; function requireCreateClass () { if (hasRequiredCreateClass) return createClass.exports; hasRequiredCreateClass = 1; (function (module) { var toPropertyKey = requireToPropertyKey(); function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } module.exports = _createClass, module.exports.__esModule = true, module.exports["default"] = module.exports; } (createClass)); return createClass.exports; } var inherits = {exports: {}}; var setPrototypeOf = {exports: {}}; var hasRequiredSetPrototypeOf; function requireSetPrototypeOf () { if (hasRequiredSetPrototypeOf) return setPrototypeOf.exports; hasRequiredSetPrototypeOf = 1; (function (module) { function _setPrototypeOf(o, p) { module.exports = _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }, module.exports.__esModule = true, module.exports["default"] = module.exports; return _setPrototypeOf(o, p); } module.exports = _setPrototypeOf, module.exports.__esModule = true, module.exports["default"] = module.exports; } (setPrototypeOf)); return setPrototypeOf.exports; } var hasRequiredInherits; function requireInherits () { if (hasRequiredInherits) return inherits.exports; hasRequiredInherits = 1; (function (module) { var setPrototypeOf = requireSetPrototypeOf(); function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) setPrototypeOf(subClass, superClass); } module.exports = _inherits, module.exports.__esModule = true, module.exports["default"] = module.exports; } (inherits)); return inherits.exports; } var possibleConstructorReturn = {exports: {}}; var assertThisInitialized = {exports: {}}; var hasRequiredAssertThisInitialized; function requireAssertThisInitialized () { if (hasRequiredAssertThisInitialized) return assertThisInitialized.exports; hasRequiredAssertThisInitialized = 1; (function (module) { function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } module.exports = _assertThisInitialized, module.exports.__esModule = true, module.exports["default"] = module.exports; } (assertThisInitialized)); return assertThisInitialized.exports; } var hasRequiredPossibleConstructorReturn; function requirePossibleConstructorReturn () { if (hasRequiredPossibleConstructorReturn) return possibleConstructorReturn.exports; hasRequiredPossibleConstructorReturn = 1; (function (module) { var _typeof = require_typeof()["default"]; var assertThisInitialized = requireAssertThisInitialized(); function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return assertThisInitialized(self); } module.exports = _possibleConstructorReturn, module.exports.__esModule = true, module.exports["default"] = module.exports; } (possibleConstructorReturn)); return possibleConstructorReturn.exports; } var getPrototypeOf = {exports: {}}; var hasRequiredGetPrototypeOf; function requireGetPrototypeOf () { if (hasRequiredGetPrototypeOf) return getPrototypeOf.exports; hasRequiredGetPrototypeOf = 1; (function (module) { function _getPrototypeOf(o) { module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }, module.exports.__esModule = true, module.exports["default"] = module.exports; return _getPrototypeOf(o); } module.exports = _getPrototypeOf, module.exports.__esModule = true, module.exports["default"] = module.exports; } (getPrototypeOf)); return getPrototypeOf.exports; } var eventemitter3 = {exports: {}}; var hasRequiredEventemitter3; function requireEventemitter3 () { if (hasRequiredEventemitter3) return eventemitter3.exports; hasRequiredEventemitter3 = 1; (function (module) { var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // { module.exports = EventEmitter; } } (eventemitter3)); return eventemitter3.exports; } /** * "Client" wraps "ws" or a browser-implemented "WebSocket" library * according to the environment providing JSON RPC 2.0 support on top. * @module Client */ (function (exports) { var _interopRequireDefault = interopRequireDefaultExports; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _regenerator = _interopRequireDefault(requireRegenerator()); var _asyncToGenerator2 = _interopRequireDefault(requireAsyncToGenerator()); var _typeof2 = _interopRequireDefault(require_typeof()); var _classCallCheck2 = _interopRequireDefault(requireClassCallCheck()); var _createClass2 = _interopRequireDefault(requireCreateClass()); var _inherits2 = _interopRequireDefault(requireInherits()); var _possibleConstructorReturn2 = _interopRequireDefault(requirePossibleConstructorReturn()); var _getPrototypeOf2 = _interopRequireDefault(requireGetPrototypeOf()); var _eventemitter = requireEventemitter3(); function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var __rest = function (s, e) { var t = {}; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; } if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; // @ts-ignore var CommonClient = /*#__PURE__*/function (_EventEmitter) { (0, _inherits2["default"])(CommonClient, _EventEmitter); var _super = _createSuper(CommonClient); /** * Instantiate a Client class. * @constructor * @param {webSocketFactory} webSocketFactory - factory method for WebSocket * @param {String} address - url to a websocket server * @param {Object} options - ws options object with reconnect parameters * @param {Function} generate_request_id - custom generation request Id * @return {CommonClient} */ function CommonClient(webSocketFactory) { var _this; var address = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "ws://localhost:8080"; var _a = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var generate_request_id = arguments.length > 3 ? arguments[3] : undefined; (0, _classCallCheck2["default"])(this, CommonClient); var _a$autoconnect = _a.autoconnect, autoconnect = _a$autoconnect === void 0 ? true : _a$autoconnect, _a$reconnect = _a.reconnect, reconnect = _a$reconnect === void 0 ? true : _a$reconnect, _a$reconnect_interval = _a.reconnect_interval, reconnect_interval = _a$reconnect_interval === void 0 ? 1000 : _a$reconnect_interval, _a$max_reconnects = _a.max_reconnects, max_reconnects = _a$max_reconnects === void 0 ? 5 : _a$max_reconnects, rest_options = __rest(_a, ["autoconnect", "reconnect", "reconnect_interval", "max_reconnects"]); _this = _super.call(this); _this.webSocketFactory = webSocketFactory; _this.queue = {}; _this.rpc_id = 0; _this.address = address; _this.autoconnect = autoconnect; _this.ready = false; _this.reconnect = reconnect; _this.reconnect_timer_id = undefined; _this.reconnect_interval = reconnect_interval; _this.max_reconnects = max_reconnects; _this.rest_options = rest_options; _this.current_reconnects = 0; _this.generate_request_id = generate_request_id || function () { return ++_this.rpc_id; }; if (_this.autoconnect) _this._connect(_this.address, Object.assign({ autoconnect: _this.autoconnect, reconnect: _this.reconnect, reconnect_interval: _this.reconnect_interval, max_reconnects: _this.max_reconnects }, _this.rest_options)); return _this; } /** * Connects to a defined server if not connected already. * @method * @return {Undefined} */ (0, _createClass2["default"])(CommonClient, [{ key: "connect", value: function connect() { if (this.socket) return; this._connect(this.address, Object.assign({ autoconnect: this.autoconnect, reconnect: this.reconnect, reconnect_interval: this.reconnect_interval, max_reconnects: this.max_reconnects }, this.rest_options)); } /** * Calls a registered RPC method on server. * @method * @param {String} method - RPC method name * @param {Object|Array} params - optional method parameters * @param {Number} timeout - RPC reply timeout value * @param {Object} ws_opts - options passed to ws * @return {Promise} */ }, { key: "call", value: function call(method, params, timeout, ws_opts) { var _this2 = this; if (!ws_opts && "object" === (0, _typeof2["default"])(timeout)) { ws_opts = timeout; timeout = null; } return new Promise(function (resolve, reject) { if (!_this2.ready) return reject(new Error("socket not ready")); var rpc_id = _this2.generate_request_id(method, params); var message = { jsonrpc: "2.0", method: method, params: params || null, id: rpc_id }; _this2.socket.send(JSON.stringify(message), ws_opts, function (error) { if (error) return reject(error); _this2.queue[rpc_id] = { promise: [resolve, reject] }; if (timeout) { _this2.queue[rpc_id].timeout = setTimeout(function () { delete _this2.queue[rpc_id]; reject(new Error("reply timeout")); }, timeout); } }); }); } /** * Logins with the other side of the connection. * @method * @param {Object} params - Login credentials object * @return {Promise} */ }, { key: "login", value: function () { var _login = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(params) { var resp; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return this.call("rpc.login", params); case 2: resp = _context.sent; if (resp) { _context.next = 5; break; } throw new Error("authentication failed"); case 5: return _context.abrupt("return", resp); case 6: case "end": return _context.stop(); } } }, _callee, this); })); function login(_x) { return _login.apply(this, arguments); } return login; }() /** * Fetches a list of client's methods registered on server. * @method * @return {Array} */ }, { key: "listMethods", value: function () { var _listMethods = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() { return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return this.call("__listMethods"); case 2: return _context2.abrupt("return", _context2.sent); case 3: case "end": return _context2.stop(); } } }, _callee2, this); })); function listMethods() { return _listMethods.apply(this, arguments); } return listMethods; }() /** * Sends a JSON-RPC 2.0 notification to server. * @method * @param {String} method - RPC method name * @param {Object} params - optional method parameters * @return {Promise} */ }, { key: "notify", value: function notify(method, params) { var _this3 = this; return new Promise(function (resolve, reject) { if (!_this3.ready) return reject(new Error("socket not ready")); var message = { jsonrpc: "2.0", method: method, params: params || null }; _this3.socket.send(JSON.stringify(message), function (error) { if (error) return reject(error); resolve(); }); }); } /** * Subscribes for a defined event. * @method * @param {String|Array} event - event name * @return {Undefined} * @throws {Error} */ }, { key: "subscribe", value: function () { var _subscribe = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(event) { var result; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: if (typeof event === "string") event = [event]; _context3.next = 3; return this.call("rpc.on", event); case 3: result = _context3.sent; if (!(typeof event === "string" && result[event] !== "ok")) { _context3.next = 6; break; } throw new Error("Failed subscribing to an event '" + event + "' with: " + result[event]); case 6: return _context3.abrupt("return", result); case 7: case "end": return _context3.stop(); } } }, _callee3, this); })); function subscribe(_x2) { return _subscribe.apply(this, arguments); } return subscribe; }() /** * Unsubscribes from a defined event. * @method * @param {String|Array} event - event name * @return {Undefined} * @throws {Error} */ }, { key: "unsubscribe", value: function () { var _unsubscribe = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(event) { var result; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: if (typeof event === "string") event = [event]; _context4.next = 3; return this.call("rpc.off", event); case 3: result = _context4.sent; if (!(typeof event === "string" && result[event] !== "ok")) { _context4.next = 6; break; } throw new Error("Failed unsubscribing from an event with: " + result); case 6: return _context4.abrupt("return", result); case 7: case "end": return _context4.stop(); } } }, _callee4, this); })); function unsubscribe(_x3) { return _unsubscribe.apply(this, arguments); } return unsubscribe; }() /** * Closes a WebSocket connection gracefully. * @method * @param {Number} code - socket close code * @param {String} data - optional data to be sent before closing * @return {Undefined} */ }, { key: "close", value: function close(code, data) { this.socket.close(code || 1000, data); } /** * Connection/Message handler. * @method * @private * @param {String} address - WebSocket API address * @param {Object} options - ws options object * @return {Undefined} */ }, { key: "_connect", value: function _connect(address, options) { var _this4 = this; clearTimeout(this.reconnect_timer_id); this.socket = this.webSocketFactory(address, options); this.socket.addEventListener("open", function () { _this4.ready = true; _this4.emit("open"); _this4.current_reconnects = 0; }); this.socket.addEventListener("message", function (_ref) { var message = _ref.data; if (message instanceof ArrayBuffer) message = Buffer.from(message).toString(); try { message = JSON.parse(message); } catch (error) { return; } // check if any listeners are attached and forward event if (message.notification && _this4.listeners(message.notification).length) { if (!Object.keys(message.params).length) return _this4.emit(message.notification); var args = [message.notification]; if (message.params.constructor === Object) args.push(message.params);else // using for-loop instead of unshift/spread because performance is better for (var i = 0; i < message.params.length; i++) { args.push(message.params[i]); } // run as microtask so that pending queue messages are resolved first // eslint-disable-next-line prefer-spread return Promise.resolve().then(function () { _this4.emit.apply(_this4, args); }); } if (!_this4.queue[message.id]) { // general JSON RPC 2.0 events if (message.method && message.params) { // run as microtask so that pending queue messages are resolved first return Promise.resolve().then(function () { _this4.emit(message.method, message.params); }); } return; } // reject early since server's response is invalid if ("error" in message === "result" in message) _this4.queue[message.id].promise[1](new Error("Server response malformed. Response must include either \"result\"" + " or \"error\", but not both.")); if (_this4.queue[message.id].timeout) clearTimeout(_this4.queue[message.id].timeout); if (message.error) _this4.queue[message.id].promise[1](message.error);else _this4.queue[message.id].promise[0](message.result); delete _this4.queue[message.id]; }); this.socket.addEventListener("error", function (error) { return _this4.emit("error", error); }); this.socket.addEventListener("close", function (_ref2) { var code = _ref2.code, reason = _ref2.reason; if (_this4.ready) // Delay close event until internal state is updated setTimeout(function () { return _this4.emit("close", code, reason); }, 0); _this4.ready = false; _this4.socket = undefined; if (code === 1000) return; _this4.current_reconnects++; if (_this4.reconnect && (_this4.max_reconnects > _this4.current_reconnects || _this4.max_reconnects === 0)) _this4.reconnect_timer_id = setTimeout(function () { return _this4._connect(address, options); }, _this4.reconnect_interval); }); } }]); return CommonClient; }(_eventemitter.EventEmitter); exports["default"] = CommonClient; } (client)); var RpcWebSocketCommonClient = /*@__PURE__*/getDefaultExportFromCjs(client); var websocket_browser = {}; /** * WebSocket implements a browser-side WebSocket specification. * @module Client */ (function (exports) { var _interopRequireDefault = interopRequireDefaultExports; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = _default; var _classCallCheck2 = _interopRequireDefault(requireClassCallCheck()); var _createClass2 = _interopRequireDefault(requireCreateClass()); var _inherits2 = _interopRequireDefault(requireInherits()); var _possibleConstructorReturn2 = _interopRequireDefault(requirePossibleConstructorReturn()); var _getPrototypeOf2 = _interopRequireDefault(requireGetPrototypeOf()); var _eventemitter = requireEventemitter3(); function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var WebSocketBrowserImpl = /*#__PURE__*/function (_EventEmitter) { (0, _inherits2["default"])(WebSocketBrowserImpl, _EventEmitter); var _super = _createSuper(WebSocketBrowserImpl); /** Instantiate a WebSocket class * @constructor * @param {String} address - url to a websocket server * @param {(Object)} options - websocket options * @param {(String|Array)} protocols - a list of protocols * @return {WebSocketBrowserImpl} - returns a WebSocket instance */ function WebSocketBrowserImpl(address, options, protocols) { var _this; (0, _classCallCheck2["default"])(this, WebSocketBrowserImpl); _this = _super.call(this); _this.socket = new window.WebSocket(address, protocols); _this.socket.onopen = function () { return _this.emit("open"); }; _this.socket.onmessage = function (event) { return _this.emit("message", event.data); }; _this.socket.onerror = function (error) { return _this.emit("error", error); }; _this.socket.onclose = function (event) { _this.emit("close", event.code, event.reason); }; return _this; } /** * Sends data through a websocket connection * @method * @param {(String|Object)} data - data to be sent via websocket * @param {Object} optionsOrCallback - ws options * @param {Function} callback - a callback called once the data is sent * @return {Undefined} */ (0, _createClass2["default"])(WebSocketBrowserImpl, [{ key: "send", value: function send(data, optionsOrCallback, callback) { var cb = callback || optionsOrCallback; try { this.socket.send(data); cb(); } catch (error) { cb(error); } } /** * Closes an underlying socket * @method * @param {Number} code - status code explaining why the connection is being closed * @param {String} reason - a description why the connection is closing * @return {Undefined} * @throws {Error} */ }, { key: "close", value: function close(code, reason) { this.socket.close(code, reason); } }, { key: "addEventListener", value: function addEventListener(type, listener, options) { this.socket.addEventListener(type, listener, options); } }]); return WebSocketBrowserImpl; }(_eventemitter.EventEmitter); /** * factory method for common WebSocket instance * @method * @param {String} address - url to a websocket server * @param {(Object)} options - websocket options * @return {Undefined} */ function _default(address, options) { return new WebSocketBrowserImpl(address, options); } } (websocket_browser)); var createRpc = /*@__PURE__*/getDefaultExportFromCjs(websocket_browser); class RpcWebSocketClient extends RpcWebSocketCommonClient { constructor(address, options, generate_request_id) { const webSocketFactory = url => { const rpc = createRpc(url, { autoconnect: true, max_reconnects: 5, reconnect: true, reconnect_interval: 1000, ...options }); if ('socket' in rpc) { this.underlyingSocket = rpc.socket; } else { this.underlyingSocket = rpc; } return rpc; }; super(webSocketFactory, address, options, generate_request_id); this.underlyingSocket = void 0; } call(...args) { const readyState = this.underlyingSocket?.readyState; if (readyState === 1 /* WebSocket.OPEN */) { return super.call(...args); } return Promise.reject(new Error('Tried to call a JSON-RPC method `' + args[0] + '` but the socket was not `CONNECTING` or `OPEN` (`readyState` was ' + readyState + ')')); } notify(...args) { const readyState = this.underlyingSocket?.readyState; if (readyState === 1 /* WebSocket.OPEN */) { return super.notify(...args); } return Promise.reject(new Error('Tried to send a JSON-RPC notification `' + args[0] + '` but the socket was not `CONNECTING` or `OPEN` (`readyState` was ' + readyState + ')')); } } /** * @internal */ /** * Decode account data buffer using an AccountType * @internal */ function decodeData(type, data) { let decoded; try { decoded = type.layout.decode(data); } catch (err) { throw new Error('invalid instruction; ' + err); } if (decoded.typeIndex !== type.index) { throw new Error(`invalid account data; account type mismatch ${decoded.typeIndex} != ${type.index}`); } return decoded; } /// The serialized size of lookup table metadata const LOOKUP_TABLE_META_SIZE = 56; class AddressLookupTableAccount { constructor(args) { this.key = void 0; this.state = void 0; this.key = args.key; this.state = args.state; } isActive() { const U64_MAX = BigInt('0xffffffffffffffff'); return this.state.deactivationSlot === U64_MAX; } static deserialize(accountData) { const meta = decodeData(LookupTableMetaLayout, accountData); const serializedAddressesLen = accountData.length - LOOKUP_TABLE_META_SIZE; assert$1(serializedAddressesLen >= 0, 'lookup table is invalid'); assert$1(serializedAddressesLen % 32 === 0, 'lookup table is invalid'); const numSerializedAddresses = serializedAddressesLen / 32; const { addresses } = struct([seq(publicKey(), numSerializedAddresses, 'addresses')]).decode(accountData.slice(LOOKUP_TABLE_META_SIZE)); return { deactivationSlot: meta.deactivationSlot, lastExtendedSlot: meta.lastExtendedSlot, lastExtendedSlotStartIndex: meta.lastExtendedStartIndex, authority: meta.authority.length !== 0 ? new PublicKey(meta.authority[0]) : undefined, addresses: addresses.map(address => new PublicKey(address)) }; } } const LookupTableMetaLayout = { index: 1, layout: struct([u32('typeIndex'), u64('deactivationSlot'), nu64('lastExtendedSlot'), u8('lastExtendedStartIndex'), u8(), // option seq(publicKey(), offset(u8(), -1), 'authority')]) }; const URL_RE = /^[^:]+:\/\/([^:[]+|\[[^\]]+\])(:\d+)?(.*)/i; function makeWebsocketUrl(endpoint) { const matches = endpoint.match(URL_RE); if (matches == null) { throw TypeError(`Failed to validate endpoint URL \`${endpoint}\``); } const [_, // eslint-disable-line @typescript-eslint/no-unused-vars hostish, portWithColon, rest] = matches; const protocol = endpoint.startsWith('https:') ? 'wss:' : 'ws:'; const startPort = portWithColon == null ? null : parseInt(portWithColon.slice(1), 10); const websocketPort = // Only shift the port by +1 as a convention for ws(s) only if given endpoint // is explicitly specifying the endpoint port (HTTP-based RPC), assuming // we're directly trying to connect to solana-validator's ws listening port. // When the endpoint omits the port, we're connecting to the protocol // default ports: http(80) or https(443) and it's assumed we're behind a reverse // proxy which manages WebSocket upgrade and backend port redirection. startPort == null ? '' : `:${startPort + 1}`; return `${protocol}//${hostish}${websocketPort}${rest}`; } const PublicKeyFromString = coerce(instance(PublicKey), string(), value => new PublicKey(value)); const RawAccountDataResult = tuple([string(), literal('base64')]); const BufferFromRawAccountData = coerce(instance(buffer.Buffer), RawAccountDataResult, value => buffer.Buffer.from(value[0], 'base64')); /** * Attempt to use a recent blockhash for up to 30 seconds * @internal */ const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000; /** * HACK. * Copied from rpc-websockets/dist/lib/client. * Otherwise, `yarn build` fails with: * https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d */ /** @internal */ /** @internal */ /** @internal */ /** @internal */ /** @internal */ /** * @internal * Every subscription contains the args used to open the subscription with * the server, and a list of callers interested in notifications. */ /** * @internal * A subscription may be in various states of connectedness. Only when it is * fully connected will it have a server subscription id associated with it. * This id can be returned to the server to unsubscribe the client entirely. */ /** * A type that encapsulates a subscription's RPC method * names and notification (callback) signature. */ /** * @internal * Utility type that keeps tagged unions intact while omitting properties. */ /** * @internal * This type represents a single subscribable 'topic.' It's made up of: * * - The args used to open the subscription with the server, * - The state of the subscription, in terms of its connectedness, and * - The set of callbacks to call when the server publishes notifications * * This record gets indexed by `SubscriptionConfigHash` and is used to * set up subscriptions, fan out notifications, and track subscription state. */ /** * @internal */ /** * Extra contextual information for RPC responses */ /** * Options for sending transactions */ /** * Options for confirming transactions */ /** * Options for getConfirmedSignaturesForAddress2 */ /** * Options for getSignaturesForAddress */ /** * RPC Response with extra contextual information */ /** * A strategy for confirming transactions that uses the last valid * block height for a given blockhash to check for transaction expiration. */ /** * A strategy for confirming durable nonce transactions. */ /** * Properties shared by all transaction confirmation strategies */ /** * This type represents all transaction confirmation strategies */ /* @internal */ function assertEndpointUrl(putativeUrl) { if (/^https?:/.test(putativeUrl) === false) { throw new TypeError('Endpoint URL must start with `http:` or `https:`.'); } return putativeUrl; } /** @internal */ function extractCommitmentFromConfig(commitmentOrConfig) { let commitment; let config; if (typeof commitmentOrConfig === 'string') { commitment = commitmentOrConfig; } else if (commitmentOrConfig) { const { commitment: specifiedCommitment, ...specifiedConfig } = commitmentOrConfig; commitment = specifiedCommitment; config = specifiedConfig; } return { commitment, config }; } /** * @internal */ function createRpcResult(result) { return union([type({ jsonrpc: literal('2.0'), id: string(), result }), type({ jsonrpc: literal('2.0'), id: string(), error: type({ code: unknown(), message: string(), data: optional(any()) }) })]); } const UnknownRpcResult = createRpcResult(unknown()); /** * @internal */ function jsonRpcResult(schema) { return coerce(createRpcResult(schema), UnknownRpcResult, value => { if ('error' in value) { return value; } else { return { ...value, result: create(value.result, schema) }; } }); } /** * @internal */ function jsonRpcResultAndContext(value) { return jsonRpcResult(type({ context: type({ slot: number() }), value })); } /** * @internal */ function notificationResultAndContext(value) { return type({ context: type({ slot: number() }), value }); } /** * @internal */ function versionedMessageFromResponse(version, response) { if (version === 0) { return new MessageV0({ header: response.header, staticAccountKeys: response.accountKeys.map(accountKey => new PublicKey(accountKey)), recentBlockhash: response.recentBlockhash, compiledInstructions: response.instructions.map(ix => ({ programIdIndex: ix.programIdIndex, accountKeyIndexes: ix.accounts, data: bs58$1.decode(ix.data) })), addressTableLookups: response.addressTableLookups }); } else { return new Message(response); } } /** * The level of commitment desired when querying state *
	 *   'processed': Query the most recent block which has reached 1 confirmation by the connected node
	 *   'confirmed': Query the most recent block which has reached 1 confirmation by the cluster
	 *   'finalized': Query the most recent block which has been finalized by the cluster
	 * 
*/ // Deprecated as of v1.5.5 /** * A subset of Commitment levels, which are at least optimistically confirmed *
	 *   'confirmed': Query the most recent block which has reached 1 confirmation by the cluster
	 *   'finalized': Query the most recent block which has been finalized by the cluster
	 * 
*/ /** * Filter for largest accounts query *
	 *   'circulating':    Return the largest accounts that are part of the circulating supply
	 *   'nonCirculating': Return the largest accounts that are not part of the circulating supply
	 * 
*/ /** * Configuration object for changing `getAccountInfo` query behavior */ /** * Configuration object for changing `getBalance` query behavior */ /** * Configuration object for changing `getBlock` query behavior */ /** * Configuration object for changing `getBlock` query behavior */ /** * Configuration object for changing `getStakeMinimumDelegation` query behavior */ /** * Configuration object for changing `getBlockHeight` query behavior */ /** * Configuration object for changing `getEpochInfo` query behavior */ /** * Configuration object for changing `getInflationReward` query behavior */ /** * Configuration object for changing `getLatestBlockhash` query behavior */ /** * Configuration object for changing `isBlockhashValid` query behavior */ /** * Configuration object for changing `getSlot` query behavior */ /** * Configuration object for changing `getSlotLeader` query behavior */ /** * Configuration object for changing `getTransaction` query behavior */ /** * Configuration object for changing `getTransaction` query behavior */ /** * Configuration object for changing `getLargestAccounts` query behavior */ /** * Configuration object for changing `getSupply` request behavior */ /** * Configuration object for changing query behavior */ /** * Information describing a cluster node */ /** * Information describing a vote account */ /** * A collection of cluster vote accounts */ /** * Network Inflation * (see https://docs.solana.com/implemented-proposals/ed_overview) */ const GetInflationGovernorResult = type({ foundation: number(), foundationTerm: number(), initial: number(), taper: number(), terminal: number() }); /** * The inflation reward for an epoch */ /** * Expected JSON RPC response for the "getInflationReward" message */ const GetInflationRewardResult = jsonRpcResult(array(nullable(type({ epoch: number(), effectiveSlot: number(), amount: number(), postBalance: number(), commission: optional(nullable(number())) })))); /** * Configuration object for changing `getRecentPrioritizationFees` query behavior */ /** * Expected JSON RPC response for the "getRecentPrioritizationFees" message */ const GetRecentPrioritizationFeesResult = array(type({ slot: number(), prioritizationFee: number() })); /** * Expected JSON RPC response for the "getInflationRate" message */ const GetInflationRateResult = type({ total: number(), validator: number(), foundation: number(), epoch: number() }); /** * Information about the current epoch */ const GetEpochInfoResult = type({ epoch: number(), slotIndex: number(), slotsInEpoch: number(), absoluteSlot: number(), blockHeight: optional(number()), transactionCount: optional(number()) }); const GetEpochScheduleResult = type({ slotsPerEpoch: number(), leaderScheduleSlotOffset: number(), warmup: boolean(), firstNormalEpoch: number(), firstNormalSlot: number() }); /** * Leader schedule * (see https://docs.solana.com/terminology#leader-schedule) */ const GetLeaderScheduleResult = record(string(), array(number())); /** * Transaction error or null */ const TransactionErrorResult = nullable(union([type({}), string()])); /** * Signature status for a transaction */ const SignatureStatusResult = type({ err: TransactionErrorResult }); /** * Transaction signature received notification */ const SignatureReceivedResult = literal('receivedSignature'); /** * Version info for a node */ const VersionResult = type({ 'solana-core': string(), 'feature-set': optional(number()) }); const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(type({ err: nullable(union([type({}), string()])), logs: nullable(array(string())), accounts: optional(nullable(array(nullable(type({ executable: boolean(), owner: string(), lamports: number(), data: array(string()), rentEpoch: optional(number()) }))))), unitsConsumed: optional(number()), returnData: optional(nullable(type({ programId: string(), data: tuple([string(), literal('base64')]) }))) })); /** * Metadata for a parsed confirmed transaction on the ledger * * @deprecated Deprecated since Solana v1.8.0. Please use {@link ParsedTransactionMeta} instead. */ /** * Collection of addresses loaded by a transaction using address table lookups */ /** * Metadata for a parsed transaction on the ledger */ /** * Metadata for a confirmed transaction on the ledger */ /** * A processed transaction from the RPC API */ /** * A processed transaction from the RPC API */ /** * A processed transaction message from the RPC API */ /** * A confirmed transaction on the ledger * * @deprecated Deprecated since Solana v1.8.0. */ /** * A partially decoded transaction instruction */ /** * A parsed transaction message account */ /** * A parsed transaction instruction */ /** * A parsed address table lookup */ /** * A parsed transaction message */ /** * A parsed transaction */ /** * A parsed and confirmed transaction on the ledger * * @deprecated Deprecated since Solana v1.8.0. Please use {@link ParsedTransactionWithMeta} instead. */ /** * A parsed transaction on the ledger with meta */ /** * A processed block fetched from the RPC API */ /** * A processed block fetched from the RPC API where the `transactionDetails` mode is `accounts` */ /** * A processed block fetched from the RPC API where the `transactionDetails` mode is `none` */ /** * A block with parsed transactions */ /** * A block with parsed transactions where the `transactionDetails` mode is `accounts` */ /** * A block with parsed transactions where the `transactionDetails` mode is `none` */ /** * A processed block fetched from the RPC API */ /** * A processed block fetched from the RPC API where the `transactionDetails` mode is `accounts` */ /** * A processed block fetched from the RPC API where the `transactionDetails` mode is `none` */ /** * A confirmed block on the ledger * * @deprecated Deprecated since Solana v1.8.0. */ /** * A Block on the ledger with signatures only */ /** * recent block production information */ /** * Expected JSON RPC response for the "getBlockProduction" message */ const BlockProductionResponseStruct = jsonRpcResultAndContext(type({ byIdentity: record(string(), array(number())), range: type({ firstSlot: number(), lastSlot: number() }) })); /** * A performance sample */ function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disableRetryOnRateLimit, httpAgent) { const fetch = customFetch ? customFetch : fetchImpl; let agent; { if (httpAgent != null) { 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.'); } } let fetchWithMiddleware; if (fetchMiddleware) { fetchWithMiddleware = async (info, init) => { const modifiedFetchArgs = await new Promise((resolve, reject) => { try { fetchMiddleware(info, init, (modifiedInfo, modifiedInit) => resolve([modifiedInfo, modifiedInit])); } catch (error) { reject(error); } }); return await fetch(...modifiedFetchArgs); }; } const clientBrowser = new RpcClient(async (request, callback) => { const options = { method: 'POST', body: request, agent, headers: Object.assign({ 'Content-Type': 'application/json' }, httpHeaders || {}, COMMON_HTTP_HEADERS) }; try { let too_many_requests_retries = 5; let res; let waitTime = 500; for (;;) { if (fetchWithMiddleware) { res = await fetchWithMiddleware(url, options); } else { res = await fetch(url, options); } if (res.status !== 429 /* Too many requests */) { break; } if (disableRetryOnRateLimit === true) { break; } too_many_requests_retries -= 1; if (too_many_requests_retries === 0) { break; } console.error(`Server responded with ${res.status} ${res.statusText}. Retrying after ${waitTime}ms delay...`); await sleep(waitTime); waitTime *= 2; } const text = await res.text(); if (res.ok) { callback(null, text); } else { callback(new Error(`${res.status} ${res.statusText}: ${text}`)); } } catch (err) { if (err instanceof Error) callback(err); } }, {}); return clientBrowser; } function createRpcRequest(client) { return (method, args) => { return new Promise((resolve, reject) => { client.request(method, args, (err, response) => { if (err) { reject(err); return; } resolve(response); }); }); }; } function createRpcBatchRequest(client) { return requests => { return new Promise((resolve, reject) => { // Do nothing if requests is empty if (requests.length === 0) resolve([]); const batch = requests.map(params => { return client.request(params.methodName, params.args); }); client.request(batch, (err, response) => { if (err) { reject(err); return; } resolve(response); }); }); }; } /** * Expected JSON RPC response for the "getInflationGovernor" message */ const GetInflationGovernorRpcResult = jsonRpcResult(GetInflationGovernorResult); /** * Expected JSON RPC response for the "getInflationRate" message */ const GetInflationRateRpcResult = jsonRpcResult(GetInflationRateResult); /** * Expected JSON RPC response for the "getRecentPrioritizationFees" message */ const GetRecentPrioritizationFeesRpcResult = jsonRpcResult(GetRecentPrioritizationFeesResult); /** * Expected JSON RPC response for the "getEpochInfo" message */ const GetEpochInfoRpcResult = jsonRpcResult(GetEpochInfoResult); /** * Expected JSON RPC response for the "getEpochSchedule" message */ const GetEpochScheduleRpcResult = jsonRpcResult(GetEpochScheduleResult); /** * Expected JSON RPC response for the "getLeaderSchedule" message */ const GetLeaderScheduleRpcResult = jsonRpcResult(GetLeaderScheduleResult); /** * Expected JSON RPC response for the "minimumLedgerSlot" and "getFirstAvailableBlock" messages */ const SlotRpcResult = jsonRpcResult(number()); /** * Supply */ /** * Expected JSON RPC response for the "getSupply" message */ const GetSupplyRpcResult = jsonRpcResultAndContext(type({ total: number(), circulating: number(), nonCirculating: number(), nonCirculatingAccounts: array(PublicKeyFromString) })); /** * Token amount object which returns a token amount in different formats * for various client use cases. */ /** * Expected JSON RPC structure for token amounts */ const TokenAmountResult = type({ amount: string(), uiAmount: nullable(number()), decimals: number(), uiAmountString: optional(string()) }); /** * Token address and balance. */ /** * Expected JSON RPC response for the "getTokenLargestAccounts" message */ const GetTokenLargestAccountsResult = jsonRpcResultAndContext(array(type({ address: PublicKeyFromString, amount: string(), uiAmount: nullable(number()), decimals: number(), uiAmountString: optional(string()) }))); /** * Expected JSON RPC response for the "getTokenAccountsByOwner" message */ const GetTokenAccountsByOwner = jsonRpcResultAndContext(array(type({ pubkey: PublicKeyFromString, account: type({ executable: boolean(), owner: PublicKeyFromString, lamports: number(), data: BufferFromRawAccountData, rentEpoch: number() }) }))); const ParsedAccountDataResult = type({ program: string(), parsed: unknown(), space: number() }); /** * Expected JSON RPC response for the "getTokenAccountsByOwner" message with parsed data */ const GetParsedTokenAccountsByOwner = jsonRpcResultAndContext(array(type({ pubkey: PublicKeyFromString, account: type({ executable: boolean(), owner: PublicKeyFromString, lamports: number(), data: ParsedAccountDataResult, rentEpoch: number() }) }))); /** * Pair of an account address and its balance */ /** * Expected JSON RPC response for the "getLargestAccounts" message */ const GetLargestAccountsRpcResult = jsonRpcResultAndContext(array(type({ lamports: number(), address: PublicKeyFromString }))); /** * @internal */ const AccountInfoResult = type({ executable: boolean(), owner: PublicKeyFromString, lamports: number(), data: BufferFromRawAccountData, rentEpoch: number() }); /** * @internal */ const KeyedAccountInfoResult = type({ pubkey: PublicKeyFromString, account: AccountInfoResult }); const ParsedOrRawAccountData = coerce(union([instance(buffer.Buffer), ParsedAccountDataResult]), union([RawAccountDataResult, ParsedAccountDataResult]), value => { if (Array.isArray(value)) { return create(value, BufferFromRawAccountData); } else { return value; } }); /** * @internal */ const ParsedAccountInfoResult = type({ executable: boolean(), owner: PublicKeyFromString, lamports: number(), data: ParsedOrRawAccountData, rentEpoch: number() }); const KeyedParsedAccountInfoResult = type({ pubkey: PublicKeyFromString, account: ParsedAccountInfoResult }); /** * @internal */ const StakeActivationResult = type({ state: union([literal('active'), literal('inactive'), literal('activating'), literal('deactivating')]), active: number(), inactive: number() }); /** * Expected JSON RPC response for the "getConfirmedSignaturesForAddress2" message */ const GetConfirmedSignaturesForAddress2RpcResult = jsonRpcResult(array(type({ signature: string(), slot: number(), err: TransactionErrorResult, memo: nullable(string()), blockTime: optional(nullable(number())) }))); /** * Expected JSON RPC response for the "getSignaturesForAddress" message */ const GetSignaturesForAddressRpcResult = jsonRpcResult(array(type({ signature: string(), slot: number(), err: TransactionErrorResult, memo: nullable(string()), blockTime: optional(nullable(number())) }))); /*** * Expected JSON RPC response for the "accountNotification" message */ const AccountNotificationResult = type({ subscription: number(), result: notificationResultAndContext(AccountInfoResult) }); /** * @internal */ const ProgramAccountInfoResult = type({ pubkey: PublicKeyFromString, account: AccountInfoResult }); /*** * Expected JSON RPC response for the "programNotification" message */ const ProgramAccountNotificationResult = type({ subscription: number(), result: notificationResultAndContext(ProgramAccountInfoResult) }); /** * @internal */ const SlotInfoResult = type({ parent: number(), slot: number(), root: number() }); /** * Expected JSON RPC response for the "slotNotification" message */ const SlotNotificationResult = type({ subscription: number(), result: SlotInfoResult }); /** * Slot updates which can be used for tracking the live progress of a cluster. * - `"firstShredReceived"`: connected node received the first shred of a block. * Indicates that a new block that is being produced. * - `"completed"`: connected node has received all shreds of a block. Indicates * a block was recently produced. * - `"optimisticConfirmation"`: block was optimistically confirmed by the * cluster. It is not guaranteed that an optimistic confirmation notification * will be sent for every finalized blocks. * - `"root"`: the connected node rooted this block. * - `"createdBank"`: the connected node has started validating this block. * - `"frozen"`: the connected node has validated this block. * - `"dead"`: the connected node failed to validate this block. */ /** * @internal */ const SlotUpdateResult = union([type({ type: union([literal('firstShredReceived'), literal('completed'), literal('optimisticConfirmation'), literal('root')]), slot: number(), timestamp: number() }), type({ type: literal('createdBank'), parent: number(), slot: number(), timestamp: number() }), type({ type: literal('frozen'), slot: number(), timestamp: number(), stats: type({ numTransactionEntries: number(), numSuccessfulTransactions: number(), numFailedTransactions: number(), maxTransactionsPerEntry: number() }) }), type({ type: literal('dead'), slot: number(), timestamp: number(), err: string() })]); /** * Expected JSON RPC response for the "slotsUpdatesNotification" message */ const SlotUpdateNotificationResult = type({ subscription: number(), result: SlotUpdateResult }); /** * Expected JSON RPC response for the "signatureNotification" message */ const SignatureNotificationResult = type({ subscription: number(), result: notificationResultAndContext(union([SignatureStatusResult, SignatureReceivedResult])) }); /** * Expected JSON RPC response for the "rootNotification" message */ const RootNotificationResult = type({ subscription: number(), result: number() }); const ContactInfoResult = type({ pubkey: string(), gossip: nullable(string()), tpu: nullable(string()), rpc: nullable(string()), version: nullable(string()) }); const VoteAccountInfoResult = type({ votePubkey: string(), nodePubkey: string(), activatedStake: number(), epochVoteAccount: boolean(), epochCredits: array(tuple([number(), number(), number()])), commission: number(), lastVote: number(), rootSlot: nullable(number()) }); /** * Expected JSON RPC response for the "getVoteAccounts" message */ const GetVoteAccounts = jsonRpcResult(type({ current: array(VoteAccountInfoResult), delinquent: array(VoteAccountInfoResult) })); const ConfirmationStatus = union([literal('processed'), literal('confirmed'), literal('finalized')]); const SignatureStatusResponse = type({ slot: number(), confirmations: nullable(number()), err: TransactionErrorResult, confirmationStatus: optional(ConfirmationStatus) }); /** * Expected JSON RPC response for the "getSignatureStatuses" message */ const GetSignatureStatusesRpcResult = jsonRpcResultAndContext(array(nullable(SignatureStatusResponse))); /** * Expected JSON RPC response for the "getMinimumBalanceForRentExemption" message */ const GetMinimumBalanceForRentExemptionRpcResult = jsonRpcResult(number()); const AddressTableLookupStruct = type({ accountKey: PublicKeyFromString, writableIndexes: array(number()), readonlyIndexes: array(number()) }); const ConfirmedTransactionResult = type({ signatures: array(string()), message: type({ accountKeys: array(string()), header: type({ numRequiredSignatures: number(), numReadonlySignedAccounts: number(), numReadonlyUnsignedAccounts: number() }), instructions: array(type({ accounts: array(number()), data: string(), programIdIndex: number() })), recentBlockhash: string(), addressTableLookups: optional(array(AddressTableLookupStruct)) }) }); const AnnotatedAccountKey = type({ pubkey: PublicKeyFromString, signer: boolean(), writable: boolean(), source: optional(union([literal('transaction'), literal('lookupTable')])) }); const ConfirmedTransactionAccountsModeResult = type({ accountKeys: array(AnnotatedAccountKey), signatures: array(string()) }); const ParsedInstructionResult = type({ parsed: unknown(), program: string(), programId: PublicKeyFromString }); const RawInstructionResult = type({ accounts: array(PublicKeyFromString), data: string(), programId: PublicKeyFromString }); const InstructionResult = union([RawInstructionResult, ParsedInstructionResult]); const UnknownInstructionResult = union([type({ parsed: unknown(), program: string(), programId: string() }), type({ accounts: array(string()), data: string(), programId: string() })]); const ParsedOrRawInstruction = coerce(InstructionResult, UnknownInstructionResult, value => { if ('accounts' in value) { return create(value, RawInstructionResult); } else { return create(value, ParsedInstructionResult); } }); /** * @internal */ const ParsedConfirmedTransactionResult = type({ signatures: array(string()), message: type({ accountKeys: array(AnnotatedAccountKey), instructions: array(ParsedOrRawInstruction), recentBlockhash: string(), addressTableLookups: optional(nullable(array(AddressTableLookupStruct))) }) }); const TokenBalanceResult = type({ accountIndex: number(), mint: string(), owner: optional(string()), uiTokenAmount: TokenAmountResult }); const LoadedAddressesResult = type({ writable: array(PublicKeyFromString), readonly: array(PublicKeyFromString) }); /** * @internal */ const ConfirmedTransactionMetaResult = type({ err: TransactionErrorResult, fee: number(), innerInstructions: optional(nullable(array(type({ index: number(), instructions: array(type({ accounts: array(number()), data: string(), programIdIndex: number() })) })))), preBalances: array(number()), postBalances: array(number()), logMessages: optional(nullable(array(string()))), preTokenBalances: optional(nullable(array(TokenBalanceResult))), postTokenBalances: optional(nullable(array(TokenBalanceResult))), loadedAddresses: optional(LoadedAddressesResult), computeUnitsConsumed: optional(number()) }); /** * @internal */ const ParsedConfirmedTransactionMetaResult = type({ err: TransactionErrorResult, fee: number(), innerInstructions: optional(nullable(array(type({ index: number(), instructions: array(ParsedOrRawInstruction) })))), preBalances: array(number()), postBalances: array(number()), logMessages: optional(nullable(array(string()))), preTokenBalances: optional(nullable(array(TokenBalanceResult))), postTokenBalances: optional(nullable(array(TokenBalanceResult))), loadedAddresses: optional(LoadedAddressesResult), computeUnitsConsumed: optional(number()) }); const TransactionVersionStruct = union([literal(0), literal('legacy')]); /** @internal */ const RewardsResult = type({ pubkey: string(), lamports: number(), postBalance: nullable(number()), rewardType: nullable(string()), commission: optional(nullable(number())) }); /** * Expected JSON RPC response for the "getBlock" message */ const GetBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), transactions: array(type({ transaction: ConfirmedTransactionResult, meta: nullable(ConfirmedTransactionMetaResult), version: optional(TransactionVersionStruct) })), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected JSON RPC response for the "getBlock" message when `transactionDetails` is `none` */ const GetNoneModeBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected JSON RPC response for the "getBlock" message when `transactionDetails` is `accounts` */ const GetAccountsModeBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), transactions: array(type({ transaction: ConfirmedTransactionAccountsModeResult, meta: nullable(ConfirmedTransactionMetaResult), version: optional(TransactionVersionStruct) })), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected parsed JSON RPC response for the "getBlock" message */ const GetParsedBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), transactions: array(type({ transaction: ParsedConfirmedTransactionResult, meta: nullable(ParsedConfirmedTransactionMetaResult), version: optional(TransactionVersionStruct) })), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected parsed JSON RPC response for the "getBlock" message when `transactionDetails` is `accounts` */ const GetParsedAccountsModeBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), transactions: array(type({ transaction: ConfirmedTransactionAccountsModeResult, meta: nullable(ParsedConfirmedTransactionMetaResult), version: optional(TransactionVersionStruct) })), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected parsed JSON RPC response for the "getBlock" message when `transactionDetails` is `none` */ const GetParsedNoneModeBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), rewards: optional(array(RewardsResult)), blockTime: nullable(number()), blockHeight: nullable(number()) }))); /** * Expected JSON RPC response for the "getConfirmedBlock" message * * @deprecated Deprecated since Solana v1.8.0. Please use {@link GetBlockRpcResult} instead. */ const GetConfirmedBlockRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), transactions: array(type({ transaction: ConfirmedTransactionResult, meta: nullable(ConfirmedTransactionMetaResult) })), rewards: optional(array(RewardsResult)), blockTime: nullable(number()) }))); /** * Expected JSON RPC response for the "getBlock" message */ const GetBlockSignaturesRpcResult = jsonRpcResult(nullable(type({ blockhash: string(), previousBlockhash: string(), parentSlot: number(), signatures: array(string()), blockTime: nullable(number()) }))); /** * Expected JSON RPC response for the "getTransaction" message */ const GetTransactionRpcResult = jsonRpcResult(nullable(type({ slot: number(), meta: nullable(ConfirmedTransactionMetaResult), blockTime: optional(nullable(number())), transaction: ConfirmedTransactionResult, version: optional(TransactionVersionStruct) }))); /** * Expected parsed JSON RPC response for the "getTransaction" message */ const GetParsedTransactionRpcResult = jsonRpcResult(nullable(type({ slot: number(), transaction: ParsedConfirmedTransactionResult, meta: nullable(ParsedConfirmedTransactionMetaResult), blockTime: optional(nullable(number())), version: optional(TransactionVersionStruct) }))); /** * Expected JSON RPC response for the "getRecentBlockhash" message * * @deprecated Deprecated since Solana v1.8.0. Please use {@link GetLatestBlockhashRpcResult} instead. */ const GetRecentBlockhashAndContextRpcResult = jsonRpcResultAndContext(type({ blockhash: string(), feeCalculator: type({ lamportsPerSignature: number() }) })); /** * Expected JSON RPC response for the "getLatestBlockhash" message */ const GetLatestBlockhashRpcResult = jsonRpcResultAndContext(type({ blockhash: string(), lastValidBlockHeight: number() })); /** * Expected JSON RPC response for the "isBlockhashValid" message */ const IsBlockhashValidRpcResult = jsonRpcResultAndContext(boolean()); const PerfSampleResult = type({ slot: number(), numTransactions: number(), numSlots: number(), samplePeriodSecs: number() }); /* * Expected JSON RPC response for "getRecentPerformanceSamples" message */ const GetRecentPerformanceSamplesRpcResult = jsonRpcResult(array(PerfSampleResult)); /** * Expected JSON RPC response for the "getFeeCalculatorForBlockhash" message */ const GetFeeCalculatorRpcResult = jsonRpcResultAndContext(nullable(type({ feeCalculator: type({ lamportsPerSignature: number() }) }))); /** * Expected JSON RPC response for the "requestAirdrop" message */ const RequestAirdropRpcResult = jsonRpcResult(string()); /** * Expected JSON RPC response for the "sendTransaction" message */ const SendTransactionRpcResult = jsonRpcResult(string()); /** * Information about the latest slot being processed by a node */ /** * Parsed account data */ /** * Stake Activation data */ /** * Data slice argument for getProgramAccounts */ /** * Memory comparison filter for getProgramAccounts */ /** * Data size comparison filter for getProgramAccounts */ /** * A filter object for getProgramAccounts */ /** * Configuration object for getProgramAccounts requests */ /** * Configuration object for getParsedProgramAccounts */ /** * Configuration object for getMultipleAccounts */ /** * Configuration object for `getStakeActivation` */ /** * Configuration object for `getStakeActivation` */ /** * Configuration object for `getStakeActivation` */ /** * Configuration object for `getNonce` */ /** * Configuration object for `getNonceAndContext` */ /** * Information describing an account */ /** * Account information identified by pubkey */ /** * Callback function for account change notifications */ /** * Callback function for program account change notifications */ /** * Callback function for slot change notifications */ /** * Callback function for slot update notifications */ /** * Callback function for signature status notifications */ /** * Signature status notification with transaction result */ /** * Signature received notification */ /** * Callback function for signature notifications */ /** * Signature subscription options */ /** * Callback function for root change notifications */ /** * @internal */ const LogsResult = type({ err: TransactionErrorResult, logs: array(string()), signature: string() }); /** * Logs result. */ /** * Expected JSON RPC response for the "logsNotification" message. */ const LogsNotificationResult = type({ result: notificationResultAndContext(LogsResult), subscription: number() }); /** * Filter for log subscriptions. */ /** * Callback function for log notifications. */ /** * Signature result */ /** * Transaction error */ /** * Transaction confirmation status *
	 *   'processed': Transaction landed in a block which has reached 1 confirmation by the connected node
	 *   'confirmed': Transaction landed in a block which has reached 1 confirmation by the cluster
	 *   'finalized': Transaction landed in a block which has been finalized by the cluster
	 * 
*/ /** * Signature status */ /** * A confirmed signature with its status */ /** * An object defining headers to be passed to the RPC server */ /** * The type of the JavaScript `fetch()` API */ /** * A callback used to augment the outgoing HTTP request */ /** * Configuration for instantiating a Connection */ /** @internal */ const COMMON_HTTP_HEADERS = { 'solana-client': `js/${"0.0.0-development" }` }; /** * A connection to a fullnode JSON RPC endpoint */ class Connection { /** * Establish a JSON RPC connection * * @param endpoint URL to the fullnode JSON RPC endpoint * @param commitmentOrConfig optional default commitment level or optional ConnectionConfig configuration object */ constructor(endpoint, _commitmentOrConfig) { /** @internal */ this._commitment = void 0; /** @internal */ this._confirmTransactionInitialTimeout = void 0; /** @internal */ this._rpcEndpoint = void 0; /** @internal */ this._rpcWsEndpoint = void 0; /** @internal */ this._rpcClient = void 0; /** @internal */ this._rpcRequest = void 0; /** @internal */ this._rpcBatchRequest = void 0; /** @internal */ this._rpcWebSocket = void 0; /** @internal */ this._rpcWebSocketConnected = false; /** @internal */ this._rpcWebSocketHeartbeat = null; /** @internal */ this._rpcWebSocketIdleTimeout = null; /** @internal * A number that we increment every time an active connection closes. * Used to determine whether the same socket connection that was open * when an async operation started is the same one that's active when * its continuation fires. * */ this._rpcWebSocketGeneration = 0; /** @internal */ this._disableBlockhashCaching = false; /** @internal */ this._pollingBlockhash = false; /** @internal */ this._blockhashInfo = { latestBlockhash: null, lastFetch: 0, transactionSignatures: [], simulatedSignatures: [] }; /** @internal */ this._nextClientSubscriptionId = 0; /** @internal */ this._subscriptionDisposeFunctionsByClientSubscriptionId = {}; /** @internal */ this._subscriptionHashByClientSubscriptionId = {}; /** @internal */ this._subscriptionStateChangeCallbacksByHash = {}; /** @internal */ this._subscriptionCallbacksByServerSubscriptionId = {}; /** @internal */ this._subscriptionsByHash = {}; /** * Special case. * After a signature is processed, RPCs automatically dispose of the * subscription on the server side. We need to track which of these * subscriptions have been disposed in such a way, so that we know * whether the client is dealing with a not-yet-processed signature * (in which case we must tear down the server subscription) or an * already-processed signature (in which case the client can simply * clear out the subscription locally without telling the server). * * NOTE: There is a proposal to eliminate this special case, here: * https://github.com/solana-labs/solana/issues/18892 */ /** @internal */ this._subscriptionsAutoDisposedByRpc = new Set(); /* * Returns the current block height of the node */ this.getBlockHeight = (() => { const requestPromises = {}; return async commitmentOrConfig => { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const requestHash = fastStableStringify$1(args); requestPromises[requestHash] = requestPromises[requestHash] ?? (async () => { try { const unsafeRes = await this._rpcRequest('getBlockHeight', args); const res = create(unsafeRes, jsonRpcResult(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get block height information'); } return res.result; } finally { delete requestPromises[requestHash]; } })(); return await requestPromises[requestHash]; }; })(); let wsEndpoint; let httpHeaders; let fetch; let fetchMiddleware; let disableRetryOnRateLimit; let httpAgent; if (_commitmentOrConfig && typeof _commitmentOrConfig === 'string') { this._commitment = _commitmentOrConfig; } else if (_commitmentOrConfig) { this._commitment = _commitmentOrConfig.commitment; this._confirmTransactionInitialTimeout = _commitmentOrConfig.confirmTransactionInitialTimeout; wsEndpoint = _commitmentOrConfig.wsEndpoint; httpHeaders = _commitmentOrConfig.httpHeaders; fetch = _commitmentOrConfig.fetch; fetchMiddleware = _commitmentOrConfig.fetchMiddleware; disableRetryOnRateLimit = _commitmentOrConfig.disableRetryOnRateLimit; httpAgent = _commitmentOrConfig.httpAgent; } this._rpcEndpoint = assertEndpointUrl(endpoint); this._rpcWsEndpoint = wsEndpoint || makeWebsocketUrl(endpoint); this._rpcClient = createRpcClient(endpoint, httpHeaders, fetch, fetchMiddleware, disableRetryOnRateLimit, httpAgent); this._rpcRequest = createRpcRequest(this._rpcClient); this._rpcBatchRequest = createRpcBatchRequest(this._rpcClient); this._rpcWebSocket = new RpcWebSocketClient(this._rpcWsEndpoint, { autoconnect: false, max_reconnects: Infinity }); this._rpcWebSocket.on('open', this._wsOnOpen.bind(this)); this._rpcWebSocket.on('error', this._wsOnError.bind(this)); this._rpcWebSocket.on('close', this._wsOnClose.bind(this)); this._rpcWebSocket.on('accountNotification', this._wsOnAccountNotification.bind(this)); this._rpcWebSocket.on('programNotification', this._wsOnProgramAccountNotification.bind(this)); this._rpcWebSocket.on('slotNotification', this._wsOnSlotNotification.bind(this)); this._rpcWebSocket.on('slotsUpdatesNotification', this._wsOnSlotUpdatesNotification.bind(this)); this._rpcWebSocket.on('signatureNotification', this._wsOnSignatureNotification.bind(this)); this._rpcWebSocket.on('rootNotification', this._wsOnRootNotification.bind(this)); this._rpcWebSocket.on('logsNotification', this._wsOnLogsNotification.bind(this)); } /** * The default commitment used for requests */ get commitment() { return this._commitment; } /** * The RPC endpoint */ get rpcEndpoint() { return this._rpcEndpoint; } /** * Fetch the balance for the specified public key, return with context */ async getBalanceAndContext(publicKey, commitmentOrConfig) { /** @internal */ const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([publicKey.toBase58()], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getBalance', args); const res = create(unsafeRes, jsonRpcResultAndContext(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get balance for ${publicKey.toBase58()}`); } return res.result; } /** * Fetch the balance for the specified public key */ async getBalance(publicKey, commitmentOrConfig) { return await this.getBalanceAndContext(publicKey, commitmentOrConfig).then(x => x.value).catch(e => { throw new Error('failed to get balance of account ' + publicKey.toBase58() + ': ' + e); }); } /** * Fetch the estimated production time of a block */ async getBlockTime(slot) { const unsafeRes = await this._rpcRequest('getBlockTime', [slot]); const res = create(unsafeRes, jsonRpcResult(nullable(number()))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get block time for slot ${slot}`); } return res.result; } /** * Fetch the lowest slot that the node has information about in its ledger. * This value may increase over time if the node is configured to purge older ledger data */ async getMinimumLedgerSlot() { const unsafeRes = await this._rpcRequest('minimumLedgerSlot', []); const res = create(unsafeRes, jsonRpcResult(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get minimum ledger slot'); } return res.result; } /** * Fetch the slot of the lowest confirmed block that has not been purged from the ledger */ async getFirstAvailableBlock() { const unsafeRes = await this._rpcRequest('getFirstAvailableBlock', []); const res = create(unsafeRes, SlotRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get first available block'); } return res.result; } /** * Fetch information about the current supply */ async getSupply(config) { let configArg = {}; if (typeof config === 'string') { configArg = { commitment: config }; } else if (config) { configArg = { ...config, commitment: config && config.commitment || this.commitment }; } else { configArg = { commitment: this.commitment }; } const unsafeRes = await this._rpcRequest('getSupply', [configArg]); const res = create(unsafeRes, GetSupplyRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get supply'); } return res.result; } /** * Fetch the current supply of a token mint */ async getTokenSupply(tokenMintAddress, commitment) { const args = this._buildArgs([tokenMintAddress.toBase58()], commitment); const unsafeRes = await this._rpcRequest('getTokenSupply', args); const res = create(unsafeRes, jsonRpcResultAndContext(TokenAmountResult)); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get token supply'); } return res.result; } /** * Fetch the current balance of a token account */ async getTokenAccountBalance(tokenAddress, commitment) { const args = this._buildArgs([tokenAddress.toBase58()], commitment); const unsafeRes = await this._rpcRequest('getTokenAccountBalance', args); const res = create(unsafeRes, jsonRpcResultAndContext(TokenAmountResult)); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get token account balance'); } return res.result; } /** * Fetch all the token accounts owned by the specified account * * @return {Promise} */ async getTokenAccountsByOwner(ownerAddress, filter, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); let _args = [ownerAddress.toBase58()]; if ('mint' in filter) { _args.push({ mint: filter.mint.toBase58() }); } else { _args.push({ programId: filter.programId.toBase58() }); } const args = this._buildArgs(_args, commitment, 'base64', config); const unsafeRes = await this._rpcRequest('getTokenAccountsByOwner', args); const res = create(unsafeRes, GetTokenAccountsByOwner); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get token accounts owned by account ${ownerAddress.toBase58()}`); } return res.result; } /** * Fetch parsed token accounts owned by the specified account * * @return {Promise}>>>} */ async getParsedTokenAccountsByOwner(ownerAddress, filter, commitment) { let _args = [ownerAddress.toBase58()]; if ('mint' in filter) { _args.push({ mint: filter.mint.toBase58() }); } else { _args.push({ programId: filter.programId.toBase58() }); } const args = this._buildArgs(_args, commitment, 'jsonParsed'); const unsafeRes = await this._rpcRequest('getTokenAccountsByOwner', args); const res = create(unsafeRes, GetParsedTokenAccountsByOwner); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get token accounts owned by account ${ownerAddress.toBase58()}`); } return res.result; } /** * Fetch the 20 largest accounts with their current balances */ async getLargestAccounts(config) { const arg = { ...config, commitment: config && config.commitment || this.commitment }; const args = arg.filter || arg.commitment ? [arg] : []; const unsafeRes = await this._rpcRequest('getLargestAccounts', args); const res = create(unsafeRes, GetLargestAccountsRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get largest accounts'); } return res.result; } /** * Fetch the 20 largest token accounts with their current balances * for a given mint. */ async getTokenLargestAccounts(mintAddress, commitment) { const args = this._buildArgs([mintAddress.toBase58()], commitment); const unsafeRes = await this._rpcRequest('getTokenLargestAccounts', args); const res = create(unsafeRes, GetTokenLargestAccountsResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get token largest accounts'); } return res.result; } /** * Fetch all the account info for the specified public key, return with context */ async getAccountInfoAndContext(publicKey, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([publicKey.toBase58()], commitment, 'base64', config); const unsafeRes = await this._rpcRequest('getAccountInfo', args); const res = create(unsafeRes, jsonRpcResultAndContext(nullable(AccountInfoResult))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get info about account ${publicKey.toBase58()}`); } return res.result; } /** * Fetch parsed account info for the specified public key */ async getParsedAccountInfo(publicKey, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([publicKey.toBase58()], commitment, 'jsonParsed', config); const unsafeRes = await this._rpcRequest('getAccountInfo', args); const res = create(unsafeRes, jsonRpcResultAndContext(nullable(ParsedAccountInfoResult))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get info about account ${publicKey.toBase58()}`); } return res.result; } /** * Fetch all the account info for the specified public key */ async getAccountInfo(publicKey, commitmentOrConfig) { try { const res = await this.getAccountInfoAndContext(publicKey, commitmentOrConfig); return res.value; } catch (e) { throw new Error('failed to get info about account ' + publicKey.toBase58() + ': ' + e); } } /** * Fetch all the account info for multiple accounts specified by an array of public keys, return with context */ async getMultipleParsedAccounts(publicKeys, rawConfig) { const { commitment, config } = extractCommitmentFromConfig(rawConfig); const keys = publicKeys.map(key => key.toBase58()); const args = this._buildArgs([keys], commitment, 'jsonParsed', config); const unsafeRes = await this._rpcRequest('getMultipleAccounts', args); const res = create(unsafeRes, jsonRpcResultAndContext(array(nullable(ParsedAccountInfoResult)))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get info for accounts ${keys}`); } return res.result; } /** * Fetch all the account info for multiple accounts specified by an array of public keys, return with context */ async getMultipleAccountsInfoAndContext(publicKeys, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const keys = publicKeys.map(key => key.toBase58()); const args = this._buildArgs([keys], commitment, 'base64', config); const unsafeRes = await this._rpcRequest('getMultipleAccounts', args); const res = create(unsafeRes, jsonRpcResultAndContext(array(nullable(AccountInfoResult)))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get info for accounts ${keys}`); } return res.result; } /** * Fetch all the account info for multiple accounts specified by an array of public keys */ async getMultipleAccountsInfo(publicKeys, commitmentOrConfig) { const res = await this.getMultipleAccountsInfoAndContext(publicKeys, commitmentOrConfig); return res.value; } /** * Returns epoch activation information for a stake account that has been delegated */ async getStakeActivation(publicKey, commitmentOrConfig, epoch) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([publicKey.toBase58()], commitment, undefined /* encoding */, { ...config, epoch: epoch != null ? epoch : config?.epoch }); const unsafeRes = await this._rpcRequest('getStakeActivation', args); const res = create(unsafeRes, jsonRpcResult(StakeActivationResult)); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get Stake Activation ${publicKey.toBase58()}`); } return res.result; } /** * Fetch all the accounts owned by the specified program id * * @return {Promise}>>} */ // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members async getProgramAccounts(programId, configOrCommitment) { const { commitment, config } = extractCommitmentFromConfig(configOrCommitment); const { encoding, ...configWithoutEncoding } = config || {}; const args = this._buildArgs([programId.toBase58()], commitment, encoding || 'base64', configWithoutEncoding); const unsafeRes = await this._rpcRequest('getProgramAccounts', args); const baseSchema = array(KeyedAccountInfoResult); const res = configWithoutEncoding.withContext === true ? create(unsafeRes, jsonRpcResultAndContext(baseSchema)) : create(unsafeRes, jsonRpcResult(baseSchema)); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get accounts owned by program ${programId.toBase58()}`); } return res.result; } /** * Fetch and parse all the accounts owned by the specified program id * * @return {Promise}>>} */ async getParsedProgramAccounts(programId, configOrCommitment) { const { commitment, config } = extractCommitmentFromConfig(configOrCommitment); const args = this._buildArgs([programId.toBase58()], commitment, 'jsonParsed', config); const unsafeRes = await this._rpcRequest('getProgramAccounts', args); const res = create(unsafeRes, jsonRpcResult(array(KeyedParsedAccountInfoResult))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get accounts owned by program ${programId.toBase58()}`); } return res.result; } /** @deprecated Instead, call `confirmTransaction` and pass in {@link TransactionConfirmationStrategy} */ // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members async confirmTransaction(strategy, commitment) { let rawSignature; if (typeof strategy == 'string') { rawSignature = strategy; } else { const config = strategy; if (config.abortSignal?.aborted) { return Promise.reject(config.abortSignal.reason); } rawSignature = config.signature; } let decodedSignature; try { decodedSignature = bs58$1.decode(rawSignature); } catch (err) { throw new Error('signature must be base58 encoded: ' + rawSignature); } assert$1(decodedSignature.length === 64, 'signature has invalid length'); if (typeof strategy === 'string') { return await this.confirmTransactionUsingLegacyTimeoutStrategy({ commitment: commitment || this.commitment, signature: rawSignature }); } else if ('lastValidBlockHeight' in strategy) { return await this.confirmTransactionUsingBlockHeightExceedanceStrategy({ commitment: commitment || this.commitment, strategy }); } else { return await this.confirmTransactionUsingDurableNonceStrategy({ commitment: commitment || this.commitment, strategy }); } } getCancellationPromise(signal) { return new Promise((_, reject) => { if (signal == null) { return; } if (signal.aborted) { reject(signal.reason); } else { signal.addEventListener('abort', () => { reject(signal.reason); }); } }); } getTransactionConfirmationPromise({ commitment, signature }) { let signatureSubscriptionId; let disposeSignatureSubscriptionStateChangeObserver; let done = false; const confirmationPromise = new Promise((resolve, reject) => { try { signatureSubscriptionId = this.onSignature(signature, (result, context) => { signatureSubscriptionId = undefined; const response = { context, value: result }; resolve({ __type: TransactionStatus.PROCESSED, response }); }, commitment); const subscriptionSetupPromise = new Promise(resolveSubscriptionSetup => { if (signatureSubscriptionId == null) { resolveSubscriptionSetup(); } else { disposeSignatureSubscriptionStateChangeObserver = this._onSubscriptionStateChange(signatureSubscriptionId, nextState => { if (nextState === 'subscribed') { resolveSubscriptionSetup(); } }); } }); (async () => { await subscriptionSetupPromise; if (done) return; const response = await this.getSignatureStatus(signature); if (done) return; if (response == null) { return; } const { context, value } = response; if (value == null) { return; } if (value?.err) { reject(value.err); } else { switch (commitment) { case 'confirmed': case 'single': case 'singleGossip': { if (value.confirmationStatus === 'processed') { return; } break; } case 'finalized': case 'max': case 'root': { if (value.confirmationStatus === 'processed' || value.confirmationStatus === 'confirmed') { return; } break; } // exhaust enums to ensure full coverage case 'processed': case 'recent': } done = true; resolve({ __type: TransactionStatus.PROCESSED, response: { context, value } }); } })(); } catch (err) { reject(err); } }); const abortConfirmation = () => { if (disposeSignatureSubscriptionStateChangeObserver) { disposeSignatureSubscriptionStateChangeObserver(); disposeSignatureSubscriptionStateChangeObserver = undefined; } if (signatureSubscriptionId != null) { this.removeSignatureListener(signatureSubscriptionId); signatureSubscriptionId = undefined; } }; return { abortConfirmation, confirmationPromise }; } async confirmTransactionUsingBlockHeightExceedanceStrategy({ commitment, strategy: { abortSignal, lastValidBlockHeight, signature } }) { let done = false; const expiryPromise = new Promise(resolve => { const checkBlockHeight = async () => { try { const blockHeight = await this.getBlockHeight(commitment); return blockHeight; } catch (_e) { return -1; } }; (async () => { let currentBlockHeight = await checkBlockHeight(); if (done) return; while (currentBlockHeight <= lastValidBlockHeight) { await sleep(1000); if (done) return; currentBlockHeight = await checkBlockHeight(); if (done) return; } resolve({ __type: TransactionStatus.BLOCKHEIGHT_EXCEEDED }); })(); }); const { abortConfirmation, confirmationPromise } = this.getTransactionConfirmationPromise({ commitment, signature }); const cancellationPromise = this.getCancellationPromise(abortSignal); let result; try { const outcome = await Promise.race([cancellationPromise, confirmationPromise, expiryPromise]); if (outcome.__type === TransactionStatus.PROCESSED) { result = outcome.response; } else { throw new TransactionExpiredBlockheightExceededError(signature); } } finally { done = true; abortConfirmation(); } return result; } async confirmTransactionUsingDurableNonceStrategy({ commitment, strategy: { abortSignal, minContextSlot, nonceAccountPubkey, nonceValue, signature } }) { let done = false; const expiryPromise = new Promise(resolve => { let currentNonceValue = nonceValue; let lastCheckedSlot = null; const getCurrentNonceValue = async () => { try { const { context, value: nonceAccount } = await this.getNonceAndContext(nonceAccountPubkey, { commitment, minContextSlot }); lastCheckedSlot = context.slot; return nonceAccount?.nonce; } catch (e) { // If for whatever reason we can't reach/read the nonce // account, just keep using the last-known value. return currentNonceValue; } }; (async () => { currentNonceValue = await getCurrentNonceValue(); if (done) return; while (true // eslint-disable-line no-constant-condition ) { if (nonceValue !== currentNonceValue) { resolve({ __type: TransactionStatus.NONCE_INVALID, slotInWhichNonceDidAdvance: lastCheckedSlot }); return; } await sleep(2000); if (done) return; currentNonceValue = await getCurrentNonceValue(); if (done) return; } })(); }); const { abortConfirmation, confirmationPromise } = this.getTransactionConfirmationPromise({ commitment, signature }); const cancellationPromise = this.getCancellationPromise(abortSignal); let result; try { const outcome = await Promise.race([cancellationPromise, confirmationPromise, expiryPromise]); if (outcome.__type === TransactionStatus.PROCESSED) { result = outcome.response; } else { // Double check that the transaction is indeed unconfirmed. let signatureStatus; while (true // eslint-disable-line no-constant-condition ) { const status = await this.getSignatureStatus(signature); if (status == null) { break; } if (status.context.slot < (outcome.slotInWhichNonceDidAdvance ?? minContextSlot)) { await sleep(400); continue; } signatureStatus = status; break; } if (signatureStatus?.value) { const commitmentForStatus = commitment || 'finalized'; const { confirmationStatus } = signatureStatus.value; switch (commitmentForStatus) { case 'processed': case 'recent': if (confirmationStatus !== 'processed' && confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') { throw new TransactionExpiredNonceInvalidError(signature); } break; case 'confirmed': case 'single': case 'singleGossip': if (confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') { throw new TransactionExpiredNonceInvalidError(signature); } break; case 'finalized': case 'max': case 'root': if (confirmationStatus !== 'finalized') { throw new TransactionExpiredNonceInvalidError(signature); } break; default: // Exhaustive switch. // eslint-disable-next-line @typescript-eslint/no-unused-vars (_ => {})(commitmentForStatus); } result = { context: signatureStatus.context, value: { err: signatureStatus.value.err } }; } else { throw new TransactionExpiredNonceInvalidError(signature); } } } finally { done = true; abortConfirmation(); } return result; } async confirmTransactionUsingLegacyTimeoutStrategy({ commitment, signature }) { let timeoutId; const expiryPromise = new Promise(resolve => { let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000; switch (commitment) { case 'processed': case 'recent': case 'single': case 'confirmed': case 'singleGossip': { timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000; break; } } timeoutId = setTimeout(() => resolve({ __type: TransactionStatus.TIMED_OUT, timeoutMs }), timeoutMs); }); const { abortConfirmation, confirmationPromise } = this.getTransactionConfirmationPromise({ commitment, signature }); let result; try { const outcome = await Promise.race([confirmationPromise, expiryPromise]); if (outcome.__type === TransactionStatus.PROCESSED) { result = outcome.response; } else { throw new TransactionExpiredTimeoutError(signature, outcome.timeoutMs / 1000); } } finally { clearTimeout(timeoutId); abortConfirmation(); } return result; } /** * Return the list of nodes that are currently participating in the cluster */ async getClusterNodes() { const unsafeRes = await this._rpcRequest('getClusterNodes', []); const res = create(unsafeRes, jsonRpcResult(array(ContactInfoResult))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get cluster nodes'); } return res.result; } /** * Return the list of nodes that are currently participating in the cluster */ async getVoteAccounts(commitment) { const args = this._buildArgs([], commitment); const unsafeRes = await this._rpcRequest('getVoteAccounts', args); const res = create(unsafeRes, GetVoteAccounts); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get vote accounts'); } return res.result; } /** * Fetch the current slot that the node is processing */ async getSlot(commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getSlot', args); const res = create(unsafeRes, jsonRpcResult(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get slot'); } return res.result; } /** * Fetch the current slot leader of the cluster */ async getSlotLeader(commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getSlotLeader', args); const res = create(unsafeRes, jsonRpcResult(string())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get slot leader'); } return res.result; } /** * Fetch `limit` number of slot leaders starting from `startSlot` * * @param startSlot fetch slot leaders starting from this slot * @param limit number of slot leaders to return */ async getSlotLeaders(startSlot, limit) { const args = [startSlot, limit]; const unsafeRes = await this._rpcRequest('getSlotLeaders', args); const res = create(unsafeRes, jsonRpcResult(array(PublicKeyFromString))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get slot leaders'); } return res.result; } /** * Fetch the current status of a signature */ async getSignatureStatus(signature, config) { const { context, value: values } = await this.getSignatureStatuses([signature], config); assert$1(values.length === 1); const value = values[0]; return { context, value }; } /** * Fetch the current statuses of a batch of signatures */ async getSignatureStatuses(signatures, config) { const params = [signatures]; if (config) { params.push(config); } const unsafeRes = await this._rpcRequest('getSignatureStatuses', params); const res = create(unsafeRes, GetSignatureStatusesRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get signature status'); } return res.result; } /** * Fetch the current transaction count of the cluster */ async getTransactionCount(commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getTransactionCount', args); const res = create(unsafeRes, jsonRpcResult(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transaction count'); } return res.result; } /** * Fetch the current total currency supply of the cluster in lamports * * @deprecated Deprecated since v1.2.8. Please use {@link getSupply} instead. */ async getTotalSupply(commitment) { const result = await this.getSupply({ commitment, excludeNonCirculatingAccountsList: true }); return result.value.total; } /** * Fetch the cluster InflationGovernor parameters */ async getInflationGovernor(commitment) { const args = this._buildArgs([], commitment); const unsafeRes = await this._rpcRequest('getInflationGovernor', args); const res = create(unsafeRes, GetInflationGovernorRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get inflation'); } return res.result; } /** * Fetch the inflation reward for a list of addresses for an epoch */ async getInflationReward(addresses, epoch, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([addresses.map(pubkey => pubkey.toBase58())], commitment, undefined /* encoding */, { ...config, epoch: epoch != null ? epoch : config?.epoch }); const unsafeRes = await this._rpcRequest('getInflationReward', args); const res = create(unsafeRes, GetInflationRewardResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get inflation reward'); } return res.result; } /** * Fetch the specific inflation values for the current epoch */ async getInflationRate() { const unsafeRes = await this._rpcRequest('getInflationRate', []); const res = create(unsafeRes, GetInflationRateRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get inflation rate'); } return res.result; } /** * Fetch the Epoch Info parameters */ async getEpochInfo(commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getEpochInfo', args); const res = create(unsafeRes, GetEpochInfoRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get epoch info'); } return res.result; } /** * Fetch the Epoch Schedule parameters */ async getEpochSchedule() { const unsafeRes = await this._rpcRequest('getEpochSchedule', []); const res = create(unsafeRes, GetEpochScheduleRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get epoch schedule'); } const epochSchedule = res.result; return new EpochSchedule(epochSchedule.slotsPerEpoch, epochSchedule.leaderScheduleSlotOffset, epochSchedule.warmup, epochSchedule.firstNormalEpoch, epochSchedule.firstNormalSlot); } /** * Fetch the leader schedule for the current epoch * @return {Promise>} */ async getLeaderSchedule() { const unsafeRes = await this._rpcRequest('getLeaderSchedule', []); const res = create(unsafeRes, GetLeaderScheduleRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get leader schedule'); } return res.result; } /** * Fetch the minimum balance needed to exempt an account of `dataLength` * size from rent */ async getMinimumBalanceForRentExemption(dataLength, commitment) { const args = this._buildArgs([dataLength], commitment); const unsafeRes = await this._rpcRequest('getMinimumBalanceForRentExemption', args); const res = create(unsafeRes, GetMinimumBalanceForRentExemptionRpcResult); if ('error' in res) { console.warn('Unable to fetch minimum balance for rent exemption'); return 0; } return res.result; } /** * Fetch a recent blockhash from the cluster, return with context * @return {Promise>} * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getLatestBlockhash} instead. */ async getRecentBlockhashAndContext(commitment) { const args = this._buildArgs([], commitment); const unsafeRes = await this._rpcRequest('getRecentBlockhash', args); const res = create(unsafeRes, GetRecentBlockhashAndContextRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get recent blockhash'); } return res.result; } /** * Fetch recent performance samples * @return {Promise>} */ async getRecentPerformanceSamples(limit) { const unsafeRes = await this._rpcRequest('getRecentPerformanceSamples', limit ? [limit] : []); const res = create(unsafeRes, GetRecentPerformanceSamplesRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get recent performance samples'); } return res.result; } /** * Fetch the fee calculator for a recent blockhash from the cluster, return with context * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getFeeForMessage} instead. */ async getFeeCalculatorForBlockhash(blockhash, commitment) { const args = this._buildArgs([blockhash], commitment); const unsafeRes = await this._rpcRequest('getFeeCalculatorForBlockhash', args); const res = create(unsafeRes, GetFeeCalculatorRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get fee calculator'); } const { context, value } = res.result; return { context, value: value !== null ? value.feeCalculator : null }; } /** * Fetch the fee for a message from the cluster, return with context */ async getFeeForMessage(message, commitment) { const wireMessage = toBuffer(message.serialize()).toString('base64'); const args = this._buildArgs([wireMessage], commitment); const unsafeRes = await this._rpcRequest('getFeeForMessage', args); const res = create(unsafeRes, jsonRpcResultAndContext(nullable(number()))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get fee for message'); } if (res.result === null) { throw new Error('invalid blockhash'); } return res.result; } /** * Fetch a list of prioritization fees from recent blocks. */ async getRecentPrioritizationFees(config) { const accounts = config?.lockedWritableAccounts?.map(key => key.toBase58()); const args = accounts?.length ? [accounts] : []; const unsafeRes = await this._rpcRequest('getRecentPrioritizationFees', args); const res = create(unsafeRes, GetRecentPrioritizationFeesRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get recent prioritization fees'); } return res.result; } /** * Fetch a recent blockhash from the cluster * @return {Promise<{blockhash: Blockhash, feeCalculator: FeeCalculator}>} * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getLatestBlockhash} instead. */ async getRecentBlockhash(commitment) { try { const res = await this.getRecentBlockhashAndContext(commitment); return res.value; } catch (e) { throw new Error('failed to get recent blockhash: ' + e); } } /** * Fetch the latest blockhash from the cluster * @return {Promise} */ async getLatestBlockhash(commitmentOrConfig) { try { const res = await this.getLatestBlockhashAndContext(commitmentOrConfig); return res.value; } catch (e) { throw new Error('failed to get recent blockhash: ' + e); } } /** * Fetch the latest blockhash from the cluster * @return {Promise} */ async getLatestBlockhashAndContext(commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgs([], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getLatestBlockhash', args); const res = create(unsafeRes, GetLatestBlockhashRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get latest blockhash'); } return res.result; } /** * Returns whether a blockhash is still valid or not */ async isBlockhashValid(blockhash, rawConfig) { const { commitment, config } = extractCommitmentFromConfig(rawConfig); const args = this._buildArgs([blockhash], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('isBlockhashValid', args); const res = create(unsafeRes, IsBlockhashValidRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to determine if the blockhash `' + blockhash + '`is valid'); } return res.result; } /** * Fetch the node version */ async getVersion() { const unsafeRes = await this._rpcRequest('getVersion', []); const res = create(unsafeRes, jsonRpcResult(VersionResult)); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get version'); } return res.result; } /** * Fetch the genesis hash */ async getGenesisHash() { const unsafeRes = await this._rpcRequest('getGenesisHash', []); const res = create(unsafeRes, jsonRpcResult(string())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get genesis hash'); } return res.result; } /** * Fetch a processed block from the cluster. * * @deprecated Instead, call `getBlock` using a `GetVersionedBlockConfig` by * setting the `maxSupportedTransactionVersion` property. */ /** * @deprecated Instead, call `getBlock` using a `GetVersionedBlockConfig` by * setting the `maxSupportedTransactionVersion` property. */ // eslint-disable-next-line no-dupe-class-members /** * @deprecated Instead, call `getBlock` using a `GetVersionedBlockConfig` by * setting the `maxSupportedTransactionVersion` property. */ // eslint-disable-next-line no-dupe-class-members /** * Fetch a processed block from the cluster. */ // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members /** * Fetch a processed block from the cluster. */ // eslint-disable-next-line no-dupe-class-members async getBlock(slot, rawConfig) { const { commitment, config } = extractCommitmentFromConfig(rawConfig); const args = this._buildArgsAtLeastConfirmed([slot], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getBlock', args); try { switch (config?.transactionDetails) { case 'accounts': { const res = create(unsafeRes, GetAccountsModeBlockRpcResult); if ('error' in res) { throw res.error; } return res.result; } case 'none': { const res = create(unsafeRes, GetNoneModeBlockRpcResult); if ('error' in res) { throw res.error; } return res.result; } default: { const res = create(unsafeRes, GetBlockRpcResult); if ('error' in res) { throw res.error; } const { result } = res; return result ? { ...result, transactions: result.transactions.map(({ transaction, meta, version }) => ({ meta, transaction: { ...transaction, message: versionedMessageFromResponse(version, transaction.message) }, version })) } : null; } } } catch (e) { throw new SolanaJSONRPCError(e, 'failed to get confirmed block'); } } /** * Fetch parsed transaction details for a confirmed or finalized block */ // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members // eslint-disable-next-line no-dupe-class-members async getParsedBlock(slot, rawConfig) { const { commitment, config } = extractCommitmentFromConfig(rawConfig); const args = this._buildArgsAtLeastConfirmed([slot], commitment, 'jsonParsed', config); const unsafeRes = await this._rpcRequest('getBlock', args); try { switch (config?.transactionDetails) { case 'accounts': { const res = create(unsafeRes, GetParsedAccountsModeBlockRpcResult); if ('error' in res) { throw res.error; } return res.result; } case 'none': { const res = create(unsafeRes, GetParsedNoneModeBlockRpcResult); if ('error' in res) { throw res.error; } return res.result; } default: { const res = create(unsafeRes, GetParsedBlockRpcResult); if ('error' in res) { throw res.error; } return res.result; } } } catch (e) { throw new SolanaJSONRPCError(e, 'failed to get block'); } } /* * Returns recent block production information from the current or previous epoch */ async getBlockProduction(configOrCommitment) { let extra; let commitment; if (typeof configOrCommitment === 'string') { commitment = configOrCommitment; } else if (configOrCommitment) { const { commitment: c, ...rest } = configOrCommitment; commitment = c; extra = rest; } const args = this._buildArgs([], commitment, 'base64', extra); const unsafeRes = await this._rpcRequest('getBlockProduction', args); const res = create(unsafeRes, BlockProductionResponseStruct); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get block production information'); } return res.result; } /** * Fetch a confirmed or finalized transaction from the cluster. * * @deprecated Instead, call `getTransaction` using a * `GetVersionedTransactionConfig` by setting the * `maxSupportedTransactionVersion` property. */ /** * Fetch a confirmed or finalized transaction from the cluster. */ // eslint-disable-next-line no-dupe-class-members /** * Fetch a confirmed or finalized transaction from the cluster. */ // eslint-disable-next-line no-dupe-class-members async getTransaction(signature, rawConfig) { const { commitment, config } = extractCommitmentFromConfig(rawConfig); const args = this._buildArgsAtLeastConfirmed([signature], commitment, undefined /* encoding */, config); const unsafeRes = await this._rpcRequest('getTransaction', args); const res = create(unsafeRes, GetTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transaction'); } const result = res.result; if (!result) return result; return { ...result, transaction: { ...result.transaction, message: versionedMessageFromResponse(result.version, result.transaction.message) } }; } /** * Fetch parsed transaction details for a confirmed or finalized transaction */ async getParsedTransaction(signature, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const args = this._buildArgsAtLeastConfirmed([signature], commitment, 'jsonParsed', config); const unsafeRes = await this._rpcRequest('getTransaction', args); const res = create(unsafeRes, GetParsedTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transaction'); } return res.result; } /** * Fetch parsed transaction details for a batch of confirmed transactions */ async getParsedTransactions(signatures, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const batch = signatures.map(signature => { const args = this._buildArgsAtLeastConfirmed([signature], commitment, 'jsonParsed', config); return { methodName: 'getTransaction', args }; }); const unsafeRes = await this._rpcBatchRequest(batch); const res = unsafeRes.map(unsafeRes => { const res = create(unsafeRes, GetParsedTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transactions'); } return res.result; }); return res; } /** * Fetch transaction details for a batch of confirmed transactions. * Similar to {@link getParsedTransactions} but returns a {@link TransactionResponse}. * * @deprecated Instead, call `getTransactions` using a * `GetVersionedTransactionConfig` by setting the * `maxSupportedTransactionVersion` property. */ /** * Fetch transaction details for a batch of confirmed transactions. * Similar to {@link getParsedTransactions} but returns a {@link * VersionedTransactionResponse}. */ // eslint-disable-next-line no-dupe-class-members /** * Fetch transaction details for a batch of confirmed transactions. * Similar to {@link getParsedTransactions} but returns a {@link * VersionedTransactionResponse}. */ // eslint-disable-next-line no-dupe-class-members async getTransactions(signatures, commitmentOrConfig) { const { commitment, config } = extractCommitmentFromConfig(commitmentOrConfig); const batch = signatures.map(signature => { const args = this._buildArgsAtLeastConfirmed([signature], commitment, undefined /* encoding */, config); return { methodName: 'getTransaction', args }; }); const unsafeRes = await this._rpcBatchRequest(batch); const res = unsafeRes.map(unsafeRes => { const res = create(unsafeRes, GetTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transactions'); } const result = res.result; if (!result) return result; return { ...result, transaction: { ...result.transaction, message: versionedMessageFromResponse(result.version, result.transaction.message) } }; }); return res; } /** * Fetch a list of Transactions and transaction statuses from the cluster * for a confirmed block. * * @deprecated Deprecated since v1.13.0. Please use {@link getBlock} instead. */ async getConfirmedBlock(slot, commitment) { const args = this._buildArgsAtLeastConfirmed([slot], commitment); const unsafeRes = await this._rpcRequest('getConfirmedBlock', args); const res = create(unsafeRes, GetConfirmedBlockRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get confirmed block'); } const result = res.result; if (!result) { throw new Error('Confirmed block ' + slot + ' not found'); } const block = { ...result, transactions: result.transactions.map(({ transaction, meta }) => { const message = new Message(transaction.message); return { meta, transaction: { ...transaction, message } }; }) }; return { ...block, transactions: block.transactions.map(({ transaction, meta }) => { return { meta, transaction: Transaction.populate(transaction.message, transaction.signatures) }; }) }; } /** * Fetch confirmed blocks between two slots */ async getBlocks(startSlot, endSlot, commitment) { const args = this._buildArgsAtLeastConfirmed(endSlot !== undefined ? [startSlot, endSlot] : [startSlot], commitment); const unsafeRes = await this._rpcRequest('getBlocks', args); const res = create(unsafeRes, jsonRpcResult(array(number()))); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get blocks'); } return res.result; } /** * Fetch a list of Signatures from the cluster for a block, excluding rewards */ async getBlockSignatures(slot, commitment) { const args = this._buildArgsAtLeastConfirmed([slot], commitment, undefined, { transactionDetails: 'signatures', rewards: false }); const unsafeRes = await this._rpcRequest('getBlock', args); const res = create(unsafeRes, GetBlockSignaturesRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get block'); } const result = res.result; if (!result) { throw new Error('Block ' + slot + ' not found'); } return result; } /** * Fetch a list of Signatures from the cluster for a confirmed block, excluding rewards * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getBlockSignatures} instead. */ async getConfirmedBlockSignatures(slot, commitment) { const args = this._buildArgsAtLeastConfirmed([slot], commitment, undefined, { transactionDetails: 'signatures', rewards: false }); const unsafeRes = await this._rpcRequest('getConfirmedBlock', args); const res = create(unsafeRes, GetBlockSignaturesRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get confirmed block'); } const result = res.result; if (!result) { throw new Error('Confirmed block ' + slot + ' not found'); } return result; } /** * Fetch a transaction details for a confirmed transaction * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getTransaction} instead. */ async getConfirmedTransaction(signature, commitment) { const args = this._buildArgsAtLeastConfirmed([signature], commitment); const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args); const res = create(unsafeRes, GetTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get transaction'); } const result = res.result; if (!result) return result; const message = new Message(result.transaction.message); const signatures = result.transaction.signatures; return { ...result, transaction: Transaction.populate(message, signatures) }; } /** * Fetch parsed transaction details for a confirmed transaction * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getParsedTransaction} instead. */ async getParsedConfirmedTransaction(signature, commitment) { const args = this._buildArgsAtLeastConfirmed([signature], commitment, 'jsonParsed'); const unsafeRes = await this._rpcRequest('getConfirmedTransaction', args); const res = create(unsafeRes, GetParsedTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get confirmed transaction'); } return res.result; } /** * Fetch parsed transaction details for a batch of confirmed transactions * * @deprecated Deprecated since Solana v1.8.0. Please use {@link getParsedTransactions} instead. */ async getParsedConfirmedTransactions(signatures, commitment) { const batch = signatures.map(signature => { const args = this._buildArgsAtLeastConfirmed([signature], commitment, 'jsonParsed'); return { methodName: 'getConfirmedTransaction', args }; }); const unsafeRes = await this._rpcBatchRequest(batch); const res = unsafeRes.map(unsafeRes => { const res = create(unsafeRes, GetParsedTransactionRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get confirmed transactions'); } return res.result; }); return res; } /** * Fetch a list of all the confirmed signatures for transactions involving an address * within a specified slot range. Max range allowed is 10,000 slots. * * @deprecated Deprecated since v1.3. Please use {@link getConfirmedSignaturesForAddress2} instead. * * @param address queried address * @param startSlot start slot, inclusive * @param endSlot end slot, inclusive */ async getConfirmedSignaturesForAddress(address, startSlot, endSlot) { let options = {}; let firstAvailableBlock = await this.getFirstAvailableBlock(); while (!('until' in options)) { startSlot--; if (startSlot <= 0 || startSlot < firstAvailableBlock) { break; } try { const block = await this.getConfirmedBlockSignatures(startSlot, 'finalized'); if (block.signatures.length > 0) { options.until = block.signatures[block.signatures.length - 1].toString(); } } catch (err) { if (err instanceof Error && err.message.includes('skipped')) { continue; } else { throw err; } } } let highestConfirmedRoot = await this.getSlot('finalized'); while (!('before' in options)) { endSlot++; if (endSlot > highestConfirmedRoot) { break; } try { const block = await this.getConfirmedBlockSignatures(endSlot); if (block.signatures.length > 0) { options.before = block.signatures[block.signatures.length - 1].toString(); } } catch (err) { if (err instanceof Error && err.message.includes('skipped')) { continue; } else { throw err; } } } const confirmedSignatureInfo = await this.getConfirmedSignaturesForAddress2(address, options); return confirmedSignatureInfo.map(info => info.signature); } /** * Returns confirmed signatures for transactions involving an * address backwards in time from the provided signature or most recent confirmed block * * * @param address queried address * @param options */ async getConfirmedSignaturesForAddress2(address, options, commitment) { const args = this._buildArgsAtLeastConfirmed([address.toBase58()], commitment, undefined, options); const unsafeRes = await this._rpcRequest('getConfirmedSignaturesForAddress2', args); const res = create(unsafeRes, GetConfirmedSignaturesForAddress2RpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get confirmed signatures for address'); } return res.result; } /** * Returns confirmed signatures for transactions involving an * address backwards in time from the provided signature or most recent confirmed block * * * @param address queried address * @param options */ async getSignaturesForAddress(address, options, commitment) { const args = this._buildArgsAtLeastConfirmed([address.toBase58()], commitment, undefined, options); const unsafeRes = await this._rpcRequest('getSignaturesForAddress', args); const res = create(unsafeRes, GetSignaturesForAddressRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, 'failed to get signatures for address'); } return res.result; } async getAddressLookupTable(accountKey, config) { const { context, value: accountInfo } = await this.getAccountInfoAndContext(accountKey, config); let value = null; if (accountInfo !== null) { value = new AddressLookupTableAccount({ key: accountKey, state: AddressLookupTableAccount.deserialize(accountInfo.data) }); } return { context, value }; } /** * Fetch the contents of a Nonce account from the cluster, return with context */ async getNonceAndContext(nonceAccount, commitmentOrConfig) { const { context, value: accountInfo } = await this.getAccountInfoAndContext(nonceAccount, commitmentOrConfig); let value = null; if (accountInfo !== null) { value = NonceAccount.fromAccountData(accountInfo.data); } return { context, value }; } /** * Fetch the contents of a Nonce account from the cluster */ async getNonce(nonceAccount, commitmentOrConfig) { return await this.getNonceAndContext(nonceAccount, commitmentOrConfig).then(x => x.value).catch(e => { throw new Error('failed to get nonce for account ' + nonceAccount.toBase58() + ': ' + e); }); } /** * Request an allocation of lamports to the specified address * * ```typescript * import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js"; * * (async () => { * const connection = new Connection("https://api.testnet.solana.com", "confirmed"); * const myAddress = new PublicKey("2nr1bHFT86W9tGnyvmYW4vcHKsQB3sVQfnddasz4kExM"); * const signature = await connection.requestAirdrop(myAddress, LAMPORTS_PER_SOL); * await connection.confirmTransaction(signature); * })(); * ``` */ async requestAirdrop(to, lamports) { const unsafeRes = await this._rpcRequest('requestAirdrop', [to.toBase58(), lamports]); const res = create(unsafeRes, RequestAirdropRpcResult); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `airdrop to ${to.toBase58()} failed`); } return res.result; } /** * @internal */ async _blockhashWithExpiryBlockHeight(disableCache) { if (!disableCache) { // Wait for polling to finish while (this._pollingBlockhash) { await sleep(100); } const timeSinceFetch = Date.now() - this._blockhashInfo.lastFetch; const expired = timeSinceFetch >= BLOCKHASH_CACHE_TIMEOUT_MS; if (this._blockhashInfo.latestBlockhash !== null && !expired) { return this._blockhashInfo.latestBlockhash; } } return await this._pollNewBlockhash(); } /** * @internal */ async _pollNewBlockhash() { this._pollingBlockhash = true; try { const startTime = Date.now(); const cachedLatestBlockhash = this._blockhashInfo.latestBlockhash; const cachedBlockhash = cachedLatestBlockhash ? cachedLatestBlockhash.blockhash : null; for (let i = 0; i < 50; i++) { const latestBlockhash = await this.getLatestBlockhash('finalized'); if (cachedBlockhash !== latestBlockhash.blockhash) { this._blockhashInfo = { latestBlockhash, lastFetch: Date.now(), transactionSignatures: [], simulatedSignatures: [] }; return latestBlockhash; } // Sleep for approximately half a slot await sleep(MS_PER_SLOT / 2); } throw new Error(`Unable to obtain a new blockhash after ${Date.now() - startTime}ms`); } finally { this._pollingBlockhash = false; } } /** * get the stake minimum delegation */ async getStakeMinimumDelegation(config) { const { commitment, config: configArg } = extractCommitmentFromConfig(config); const args = this._buildArgs([], commitment, 'base64', configArg); const unsafeRes = await this._rpcRequest('getStakeMinimumDelegation', args); const res = create(unsafeRes, jsonRpcResultAndContext(number())); if ('error' in res) { throw new SolanaJSONRPCError(res.error, `failed to get stake minimum delegation`); } return res.result; } /** * Simulate a transaction * * @deprecated Instead, call {@link simulateTransaction} with {@link * VersionedTransaction} and {@link SimulateTransactionConfig} parameters */ /** * Simulate a transaction */ // eslint-disable-next-line no-dupe-class-members /** * Simulate a transaction */ // eslint-disable-next-line no-dupe-class-members async simulateTransaction(transactionOrMessage, configOrSigners, includeAccounts) { if ('message' in transactionOrMessage) { const versionedTx = transactionOrMessage; const wireTransaction = versionedTx.serialize(); const encodedTransaction = buffer.Buffer.from(wireTransaction).toString('base64'); if (Array.isArray(configOrSigners) || includeAccounts !== undefined) { throw new Error('Invalid arguments'); } const config = configOrSigners || {}; config.encoding = 'base64'; if (!('commitment' in config)) { config.commitment = this.commitment; } const args = [encodedTransaction, config]; const unsafeRes = await this._rpcRequest('simulateTransaction', args); const res = create(unsafeRes, SimulatedTransactionResponseStruct); if ('error' in res) { throw new Error('failed to simulate transaction: ' + res.error.message); } return res.result; } let transaction; if (transactionOrMessage instanceof Transaction) { let originalTx = transactionOrMessage; transaction = new Transaction(); transaction.feePayer = originalTx.feePayer; transaction.instructions = transactionOrMessage.instructions; transaction.nonceInfo = originalTx.nonceInfo; transaction.signatures = originalTx.signatures; } else { transaction = Transaction.populate(transactionOrMessage); // HACK: this function relies on mutating the populated transaction transaction._message = transaction._json = undefined; } if (configOrSigners !== undefined && !Array.isArray(configOrSigners)) { throw new Error('Invalid arguments'); } const signers = configOrSigners; if (transaction.nonceInfo && signers) { transaction.sign(...signers); } else { let disableCache = this._disableBlockhashCaching; for (;;) { const latestBlockhash = await this._blockhashWithExpiryBlockHeight(disableCache); transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight; transaction.recentBlockhash = latestBlockhash.blockhash; if (!signers) break; transaction.sign(...signers); if (!transaction.signature) { throw new Error('!signature'); // should never happen } const signature = transaction.signature.toString('base64'); if (!this._blockhashInfo.simulatedSignatures.includes(signature) && !this._blockhashInfo.transactionSignatures.includes(signature)) { // The signature of this transaction has not been seen before with the // current recentBlockhash, all done. Let's break this._blockhashInfo.simulatedSignatures.push(signature); break; } else { // This transaction would be treated as duplicate (its derived signature // matched to one of already recorded signatures). // So, we must fetch a new blockhash for a different signature by disabling // our cache not to wait for the cache expiration (BLOCKHASH_CACHE_TIMEOUT_MS). disableCache = true; } } } const message = transaction._compile(); const signData = message.serialize(); const wireTransaction = transaction._serialize(signData); const encodedTransaction = wireTransaction.toString('base64'); const config = { encoding: 'base64', commitment: this.commitment }; if (includeAccounts) { const addresses = (Array.isArray(includeAccounts) ? includeAccounts : message.nonProgramIds()).map(key => key.toBase58()); config['accounts'] = { encoding: 'base64', addresses }; } if (signers) { config.sigVerify = true; } const args = [encodedTransaction, config]; const unsafeRes = await this._rpcRequest('simulateTransaction', args); const res = create(unsafeRes, SimulatedTransactionResponseStruct); if ('error' in res) { let logs; if ('data' in res.error) { logs = res.error.data.logs; if (logs && Array.isArray(logs)) { const traceIndent = '\n '; const logTrace = traceIndent + logs.join(traceIndent); console.error(res.error.message, logTrace); } } throw new SendTransactionError('failed to simulate transaction: ' + res.error.message, logs); } return res.result; } /** * Sign and send a transaction * * @deprecated Instead, call {@link sendTransaction} with a {@link * VersionedTransaction} */ /** * Send a signed transaction */ // eslint-disable-next-line no-dupe-class-members /** * Sign and send a transaction */ // eslint-disable-next-line no-dupe-class-members async sendTransaction(transaction, signersOrOptions, options) { if ('version' in transaction) { if (signersOrOptions && Array.isArray(signersOrOptions)) { throw new Error('Invalid arguments'); } const wireTransaction = transaction.serialize(); return await this.sendRawTransaction(wireTransaction, signersOrOptions); } if (signersOrOptions === undefined || !Array.isArray(signersOrOptions)) { throw new Error('Invalid arguments'); } const signers = signersOrOptions; if (transaction.nonceInfo) { transaction.sign(...signers); } else { let disableCache = this._disableBlockhashCaching; for (;;) { const latestBlockhash = await this._blockhashWithExpiryBlockHeight(disableCache); transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight; transaction.recentBlockhash = latestBlockhash.blockhash; transaction.sign(...signers); if (!transaction.signature) { throw new Error('!signature'); // should never happen } const signature = transaction.signature.toString('base64'); if (!this._blockhashInfo.transactionSignatures.includes(signature)) { // The signature of this transaction has not been seen before with the // current recentBlockhash, all done. Let's break this._blockhashInfo.transactionSignatures.push(signature); break; } else { // This transaction would be treated as duplicate (its derived signature // matched to one of already recorded signatures). // So, we must fetch a new blockhash for a different signature by disabling // our cache not to wait for the cache expiration (BLOCKHASH_CACHE_TIMEOUT_MS). disableCache = true; } } } const wireTransaction = transaction.serialize(); return await this.sendRawTransaction(wireTransaction, options); } /** * Send a transaction that has already been signed and serialized into the * wire format */ async sendRawTransaction(rawTransaction, options) { const encodedTransaction = toBuffer(rawTransaction).toString('base64'); const result = await this.sendEncodedTransaction(encodedTransaction, options); return result; } /** * Send a transaction that has already been signed, serialized into the * wire format, and encoded as a base64 string */ async sendEncodedTransaction(encodedTransaction, options) { const config = { encoding: 'base64' }; const skipPreflight = options && options.skipPreflight; const preflightCommitment = skipPreflight === true ? 'processed' // FIXME Remove when https://github.com/anza-xyz/agave/pull/483 is deployed. : options && options.preflightCommitment || this.commitment; if (options && options.maxRetries != null) { config.maxRetries = options.maxRetries; } if (options && options.minContextSlot != null) { config.minContextSlot = options.minContextSlot; } if (skipPreflight) { config.skipPreflight = skipPreflight; } if (preflightCommitment) { config.preflightCommitment = preflightCommitment; } const args = [encodedTransaction, config]; const unsafeRes = await this._rpcRequest('sendTransaction', args); const res = create(unsafeRes, SendTransactionRpcResult); if ('error' in res) { let logs; if ('data' in res.error) { logs = res.error.data.logs; } throw new SendTransactionError('failed to send transaction: ' + res.error.message, logs); } return res.result; } /** * @internal */ _wsOnOpen() { this._rpcWebSocketConnected = true; this._rpcWebSocketHeartbeat = setInterval(() => { // Ping server every 5s to prevent idle timeouts (async () => { try { await this._rpcWebSocket.notify('ping'); // eslint-disable-next-line no-empty } catch {} })(); }, 5000); this._updateSubscriptions(); } /** * @internal */ _wsOnError(err) { this._rpcWebSocketConnected = false; console.error('ws error:', err.message); } /** * @internal */ _wsOnClose(code) { this._rpcWebSocketConnected = false; this._rpcWebSocketGeneration = (this._rpcWebSocketGeneration + 1) % Number.MAX_SAFE_INTEGER; if (this._rpcWebSocketIdleTimeout) { clearTimeout(this._rpcWebSocketIdleTimeout); this._rpcWebSocketIdleTimeout = null; } if (this._rpcWebSocketHeartbeat) { clearInterval(this._rpcWebSocketHeartbeat); this._rpcWebSocketHeartbeat = null; } if (code === 1000) { // explicit close, check if any subscriptions have been made since close this._updateSubscriptions(); return; } // implicit close, prepare subscriptions for auto-reconnect this._subscriptionCallbacksByServerSubscriptionId = {}; Object.entries(this._subscriptionsByHash).forEach(([hash, subscription]) => { this._setSubscription(hash, { ...subscription, state: 'pending' }); }); } /** * @internal */ _setSubscription(hash, nextSubscription) { const prevState = this._subscriptionsByHash[hash]?.state; this._subscriptionsByHash[hash] = nextSubscription; if (prevState !== nextSubscription.state) { const stateChangeCallbacks = this._subscriptionStateChangeCallbacksByHash[hash]; if (stateChangeCallbacks) { stateChangeCallbacks.forEach(cb => { try { cb(nextSubscription.state); // eslint-disable-next-line no-empty } catch {} }); } } } /** * @internal */ _onSubscriptionStateChange(clientSubscriptionId, callback) { const hash = this._subscriptionHashByClientSubscriptionId[clientSubscriptionId]; if (hash == null) { return () => {}; } const stateChangeCallbacks = this._subscriptionStateChangeCallbacksByHash[hash] ||= new Set(); stateChangeCallbacks.add(callback); return () => { stateChangeCallbacks.delete(callback); if (stateChangeCallbacks.size === 0) { delete this._subscriptionStateChangeCallbacksByHash[hash]; } }; } /** * @internal */ async _updateSubscriptions() { if (Object.keys(this._subscriptionsByHash).length === 0) { if (this._rpcWebSocketConnected) { this._rpcWebSocketConnected = false; this._rpcWebSocketIdleTimeout = setTimeout(() => { this._rpcWebSocketIdleTimeout = null; try { this._rpcWebSocket.close(); } catch (err) { // swallow error if socket has already been closed. if (err instanceof Error) { console.log(`Error when closing socket connection: ${err.message}`); } } }, 500); } return; } if (this._rpcWebSocketIdleTimeout !== null) { clearTimeout(this._rpcWebSocketIdleTimeout); this._rpcWebSocketIdleTimeout = null; this._rpcWebSocketConnected = true; } if (!this._rpcWebSocketConnected) { this._rpcWebSocket.connect(); return; } const activeWebSocketGeneration = this._rpcWebSocketGeneration; const isCurrentConnectionStillActive = () => { return activeWebSocketGeneration === this._rpcWebSocketGeneration; }; await Promise.all( // Don't be tempted to change this to `Object.entries`. We call // `_updateSubscriptions` recursively when processing the state, // so it's important that we look up the *current* version of // each subscription, every time we process a hash. Object.keys(this._subscriptionsByHash).map(async hash => { const subscription = this._subscriptionsByHash[hash]; if (subscription === undefined) { // This entry has since been deleted. Skip. return; } switch (subscription.state) { case 'pending': case 'unsubscribed': if (subscription.callbacks.size === 0) { /** * You can end up here when: * * - a subscription has recently unsubscribed * without having new callbacks added to it * while the unsubscribe was in flight, or * - when a pending subscription has its * listeners removed before a request was * sent to the server. * * Being that nobody is interested in this * subscription any longer, delete it. */ delete this._subscriptionsByHash[hash]; if (subscription.state === 'unsubscribed') { delete this._subscriptionCallbacksByServerSubscriptionId[subscription.serverSubscriptionId]; } await this._updateSubscriptions(); return; } await (async () => { const { args, method } = subscription; try { this._setSubscription(hash, { ...subscription, state: 'subscribing' }); const serverSubscriptionId = await this._rpcWebSocket.call(method, args); this._setSubscription(hash, { ...subscription, serverSubscriptionId, state: 'subscribed' }); this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId] = subscription.callbacks; await this._updateSubscriptions(); } catch (e) { if (e instanceof Error) { console.error(`${method} error for argument`, args, e.message); } if (!isCurrentConnectionStillActive()) { return; } // TODO: Maybe add an 'errored' state or a retry limit? this._setSubscription(hash, { ...subscription, state: 'pending' }); await this._updateSubscriptions(); } })(); break; case 'subscribed': if (subscription.callbacks.size === 0) { // By the time we successfully set up a subscription // with the server, the client stopped caring about it. // Tear it down now. await (async () => { const { serverSubscriptionId, unsubscribeMethod } = subscription; if (this._subscriptionsAutoDisposedByRpc.has(serverSubscriptionId)) { /** * Special case. * If we're dealing with a subscription that has been auto- * disposed by the RPC, then we can skip the RPC call to * tear down the subscription here. * * NOTE: There is a proposal to eliminate this special case, here: * https://github.com/solana-labs/solana/issues/18892 */ this._subscriptionsAutoDisposedByRpc.delete(serverSubscriptionId); } else { this._setSubscription(hash, { ...subscription, state: 'unsubscribing' }); this._setSubscription(hash, { ...subscription, state: 'unsubscribing' }); try { await this._rpcWebSocket.call(unsubscribeMethod, [serverSubscriptionId]); } catch (e) { if (e instanceof Error) { console.error(`${unsubscribeMethod} error:`, e.message); } if (!isCurrentConnectionStillActive()) { return; } // TODO: Maybe add an 'errored' state or a retry limit? this._setSubscription(hash, { ...subscription, state: 'subscribed' }); await this._updateSubscriptions(); return; } } this._setSubscription(hash, { ...subscription, state: 'unsubscribed' }); await this._updateSubscriptions(); })(); } break; } })); } /** * @internal */ _handleServerNotification(serverSubscriptionId, callbackArgs) { const callbacks = this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId]; if (callbacks === undefined) { return; } callbacks.forEach(cb => { try { cb( // I failed to find a way to convince TypeScript that `cb` is of type // `TCallback` which is certainly compatible with `Parameters`. // See https://github.com/microsoft/TypeScript/issues/47615 // @ts-ignore ...callbackArgs); } catch (e) { console.error(e); } }); } /** * @internal */ _wsOnAccountNotification(notification) { const { result, subscription } = create(notification, AccountNotificationResult); this._handleServerNotification(subscription, [result.value, result.context]); } /** * @internal */ _makeSubscription(subscriptionConfig, /** * When preparing `args` for a call to `_makeSubscription`, be sure * to carefully apply a default `commitment` property, if necessary. * * - If the user supplied a `commitment` use that. * - Otherwise, if the `Connection::commitment` is set, use that. * - Otherwise, set it to the RPC server default: `finalized`. * * This is extremely important to ensure that these two fundamentally * identical subscriptions produce the same identifying hash: * * - A subscription made without specifying a commitment. * - A subscription made where the commitment specified is the same * as the default applied to the subscription above. * * Example; these two subscriptions must produce the same hash: * * - An `accountSubscribe` subscription for `'PUBKEY'` * - An `accountSubscribe` subscription for `'PUBKEY'` with commitment * `'finalized'`. * * See the 'making a subscription with defaulted params omitted' test * in `connection-subscriptions.ts` for more. */ args) { const clientSubscriptionId = this._nextClientSubscriptionId++; const hash = fastStableStringify$1([subscriptionConfig.method, args]); const existingSubscription = this._subscriptionsByHash[hash]; if (existingSubscription === undefined) { this._subscriptionsByHash[hash] = { ...subscriptionConfig, args, callbacks: new Set([subscriptionConfig.callback]), state: 'pending' }; } else { existingSubscription.callbacks.add(subscriptionConfig.callback); } this._subscriptionHashByClientSubscriptionId[clientSubscriptionId] = hash; this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId] = async () => { delete this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId]; delete this._subscriptionHashByClientSubscriptionId[clientSubscriptionId]; const subscription = this._subscriptionsByHash[hash]; assert$1(subscription !== undefined, `Could not find a \`Subscription\` when tearing down client subscription #${clientSubscriptionId}`); subscription.callbacks.delete(subscriptionConfig.callback); await this._updateSubscriptions(); }; this._updateSubscriptions(); return clientSubscriptionId; } /** * Register a callback to be invoked whenever the specified account changes * * @param publicKey Public key of the account to monitor * @param callback Function to invoke whenever the account is changed * @param commitment Specify the commitment level account changes must reach before notification * @return subscription id */ onAccountChange(publicKey, callback, commitment) { const args = this._buildArgs([publicKey.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default. 'base64'); return this._makeSubscription({ callback, method: 'accountSubscribe', unsubscribeMethod: 'accountUnsubscribe' }, args); } /** * Deregister an account notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeAccountChangeListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'account change'); } /** * @internal */ _wsOnProgramAccountNotification(notification) { const { result, subscription } = create(notification, ProgramAccountNotificationResult); this._handleServerNotification(subscription, [{ accountId: result.value.pubkey, accountInfo: result.value.account }, result.context]); } /** * Register a callback to be invoked whenever accounts owned by the * specified program change * * @param programId Public key of the program to monitor * @param callback Function to invoke whenever the account is changed * @param commitment Specify the commitment level account changes must reach before notification * @param filters The program account filters to pass into the RPC method * @return subscription id */ onProgramAccountChange(programId, callback, commitment, filters) { const args = this._buildArgs([programId.toBase58()], commitment || this._commitment || 'finalized', // Apply connection/server default. 'base64' /* encoding */, filters ? { filters: filters } : undefined /* extra */); return this._makeSubscription({ callback, method: 'programSubscribe', unsubscribeMethod: 'programUnsubscribe' }, args); } /** * Deregister an account notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeProgramAccountChangeListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'program account change'); } /** * Registers a callback to be invoked whenever logs are emitted. */ onLogs(filter, callback, commitment) { const args = this._buildArgs([typeof filter === 'object' ? { mentions: [filter.toString()] } : filter], commitment || this._commitment || 'finalized' // Apply connection/server default. ); return this._makeSubscription({ callback, method: 'logsSubscribe', unsubscribeMethod: 'logsUnsubscribe' }, args); } /** * Deregister a logs callback. * * @param clientSubscriptionId client subscription id to deregister. */ async removeOnLogsListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'logs'); } /** * @internal */ _wsOnLogsNotification(notification) { const { result, subscription } = create(notification, LogsNotificationResult); this._handleServerNotification(subscription, [result.value, result.context]); } /** * @internal */ _wsOnSlotNotification(notification) { const { result, subscription } = create(notification, SlotNotificationResult); this._handleServerNotification(subscription, [result]); } /** * Register a callback to be invoked upon slot changes * * @param callback Function to invoke whenever the slot changes * @return subscription id */ onSlotChange(callback) { return this._makeSubscription({ callback, method: 'slotSubscribe', unsubscribeMethod: 'slotUnsubscribe' }, [] /* args */); } /** * Deregister a slot notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeSlotChangeListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot change'); } /** * @internal */ _wsOnSlotUpdatesNotification(notification) { const { result, subscription } = create(notification, SlotUpdateNotificationResult); this._handleServerNotification(subscription, [result]); } /** * Register a callback to be invoked upon slot updates. {@link SlotUpdate}'s * may be useful to track live progress of a cluster. * * @param callback Function to invoke whenever the slot updates * @return subscription id */ onSlotUpdate(callback) { return this._makeSubscription({ callback, method: 'slotsUpdatesSubscribe', unsubscribeMethod: 'slotsUpdatesUnsubscribe' }, [] /* args */); } /** * Deregister a slot update notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeSlotUpdateListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'slot update'); } /** * @internal */ async _unsubscribeClientSubscription(clientSubscriptionId, subscriptionName) { const dispose = this._subscriptionDisposeFunctionsByClientSubscriptionId[clientSubscriptionId]; if (dispose) { await dispose(); } else { console.warn('Ignored unsubscribe request because an active subscription with id ' + `\`${clientSubscriptionId}\` for '${subscriptionName}' events ` + 'could not be found.'); } } _buildArgs(args, override, encoding, extra) { const commitment = override || this._commitment; if (commitment || encoding || extra) { let options = {}; if (encoding) { options.encoding = encoding; } if (commitment) { options.commitment = commitment; } if (extra) { options = Object.assign(options, extra); } args.push(options); } return args; } /** * @internal */ _buildArgsAtLeastConfirmed(args, override, encoding, extra) { const commitment = override || this._commitment; if (commitment && !['confirmed', 'finalized'].includes(commitment)) { throw new Error('Using Connection with default commitment: `' + this._commitment + '`, but method requires at least `confirmed`'); } return this._buildArgs(args, override, encoding, extra); } /** * @internal */ _wsOnSignatureNotification(notification) { const { result, subscription } = create(notification, SignatureNotificationResult); if (result.value !== 'receivedSignature') { /** * Special case. * After a signature is processed, RPCs automatically dispose of the * subscription on the server side. We need to track which of these * subscriptions have been disposed in such a way, so that we know * whether the client is dealing with a not-yet-processed signature * (in which case we must tear down the server subscription) or an * already-processed signature (in which case the client can simply * clear out the subscription locally without telling the server). * * NOTE: There is a proposal to eliminate this special case, here: * https://github.com/solana-labs/solana/issues/18892 */ this._subscriptionsAutoDisposedByRpc.add(subscription); } this._handleServerNotification(subscription, result.value === 'receivedSignature' ? [{ type: 'received' }, result.context] : [{ type: 'status', result: result.value }, result.context]); } /** * Register a callback to be invoked upon signature updates * * @param signature Transaction signature string in base 58 * @param callback Function to invoke on signature notifications * @param commitment Specify the commitment level signature must reach before notification * @return subscription id */ onSignature(signature, callback, commitment) { const args = this._buildArgs([signature], commitment || this._commitment || 'finalized' // Apply connection/server default. ); const clientSubscriptionId = this._makeSubscription({ callback: (notification, context) => { if (notification.type === 'status') { callback(notification.result, context); // Signatures subscriptions are auto-removed by the RPC service // so no need to explicitly send an unsubscribe message. try { this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty } catch (_err) { // Already removed. } } }, method: 'signatureSubscribe', unsubscribeMethod: 'signatureUnsubscribe' }, args); return clientSubscriptionId; } /** * Register a callback to be invoked when a transaction is * received and/or processed. * * @param signature Transaction signature string in base 58 * @param callback Function to invoke on signature notifications * @param options Enable received notifications and set the commitment * level that signature must reach before notification * @return subscription id */ onSignatureWithOptions(signature, callback, options) { const { commitment, ...extra } = { ...options, commitment: options && options.commitment || this._commitment || 'finalized' // Apply connection/server default. }; const args = this._buildArgs([signature], commitment, undefined /* encoding */, extra); const clientSubscriptionId = this._makeSubscription({ callback: (notification, context) => { callback(notification, context); // Signatures subscriptions are auto-removed by the RPC service // so no need to explicitly send an unsubscribe message. try { this.removeSignatureListener(clientSubscriptionId); // eslint-disable-next-line no-empty } catch (_err) { // Already removed. } }, method: 'signatureSubscribe', unsubscribeMethod: 'signatureUnsubscribe' }, args); return clientSubscriptionId; } /** * Deregister a signature notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeSignatureListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'signature result'); } /** * @internal */ _wsOnRootNotification(notification) { const { result, subscription } = create(notification, RootNotificationResult); this._handleServerNotification(subscription, [result]); } /** * Register a callback to be invoked upon root changes * * @param callback Function to invoke whenever the root changes * @return subscription id */ onRootChange(callback) { return this._makeSubscription({ callback, method: 'rootSubscribe', unsubscribeMethod: 'rootUnsubscribe' }, [] /* args */); } /** * Deregister a root notification callback * * @param clientSubscriptionId client subscription id to deregister */ async removeRootChangeListener(clientSubscriptionId) { await this._unsubscribeClientSubscription(clientSubscriptionId, 'root change'); } } /** * Keypair signer interface */ /** * An account keypair used for signing transactions. */ class Keypair { /** * Create a new keypair instance. * Generate random keypair if no {@link Ed25519Keypair} is provided. * * @param {Ed25519Keypair} keypair ed25519 keypair */ constructor(keypair) { this._keypair = void 0; this._keypair = keypair ?? generateKeypair(); } /** * Generate a new random keypair * * @returns {Keypair} Keypair */ static generate() { return new Keypair(generateKeypair()); } /** * Create a keypair from a raw secret key byte array. * * This method should only be used to recreate a keypair from a previously * generated secret key. Generating keypairs from a random seed should be done * with the {@link Keypair.fromSeed} method. * * @throws error if the provided secret key is invalid and validation is not skipped. * * @param secretKey secret key byte array * @param options skip secret key validation * * @returns {Keypair} Keypair */ static fromSecretKey(secretKey, options) { if (secretKey.byteLength !== 64) { throw new Error('bad secret key size'); } const publicKey = secretKey.slice(32, 64); if (!options || !options.skipValidation) { const privateScalar = secretKey.slice(0, 32); const computedPublicKey = getPublicKey(privateScalar); for (let ii = 0; ii < 32; ii++) { if (publicKey[ii] !== computedPublicKey[ii]) { throw new Error('provided secretKey is invalid'); } } } return new Keypair({ publicKey, secretKey }); } /** * Generate a keypair from a 32 byte seed. * * @param seed seed byte array * * @returns {Keypair} Keypair */ static fromSeed(seed) { const publicKey = getPublicKey(seed); const secretKey = new Uint8Array(64); secretKey.set(seed); secretKey.set(publicKey, 32); return new Keypair({ publicKey, secretKey }); } /** * The public key for this keypair * * @returns {PublicKey} PublicKey */ get publicKey() { return new PublicKey(this._keypair.publicKey); } /** * The raw secret key for this keypair * @returns {Uint8Array} Secret key in an array of Uint8 bytes */ get secretKey() { return new Uint8Array(this._keypair.secretKey); } } /** * An enumeration of valid LookupTableInstructionType's */ /** * An enumeration of valid address lookup table InstructionType's * @internal */ const LOOKUP_TABLE_INSTRUCTION_LAYOUTS = Object.freeze({ CreateLookupTable: { index: 0, layout: struct([u32('instruction'), u64('recentSlot'), u8('bumpSeed')]) }, FreezeLookupTable: { index: 1, layout: struct([u32('instruction')]) }, ExtendLookupTable: { index: 2, layout: struct([u32('instruction'), u64(), seq(publicKey(), offset(u32(), -8), 'addresses')]) }, DeactivateLookupTable: { index: 3, layout: struct([u32('instruction')]) }, CloseLookupTable: { index: 4, layout: struct([u32('instruction')]) } }); class AddressLookupTableInstruction { /** * @internal */ constructor() {} static decodeInstructionType(instruction) { this.checkProgramId(instruction.programId); const instructionTypeLayout = u32('instruction'); const index = instructionTypeLayout.decode(instruction.data); let type; for (const [layoutType, layout] of Object.entries(LOOKUP_TABLE_INSTRUCTION_LAYOUTS)) { if (layout.index == index) { type = layoutType; break; } } if (!type) { throw new Error('Invalid Instruction. Should be a LookupTable Instruction'); } return type; } static decodeCreateLookupTable(instruction) { this.checkProgramId(instruction.programId); this.checkKeysLength(instruction.keys, 4); const { recentSlot } = decodeData$1(LOOKUP_TABLE_INSTRUCTION_LAYOUTS.CreateLookupTable, instruction.data); return { authority: instruction.keys[1].pubkey, payer: instruction.keys[2].pubkey, recentSlot: Number(recentSlot) }; } static decodeExtendLookupTable(instruction) { this.checkProgramId(instruction.programId); if (instruction.keys.length < 2) { throw new Error(`invalid instruction; found ${instruction.keys.length} keys, expected at least 2`); } const { addresses } = decodeData$1(LOOKUP_TABLE_INSTRUCTION_LAYOUTS.ExtendLookupTable, instruction.data); return { lookupTable: instruction.keys[0].pubkey, authority: instruction.keys[1].pubkey, payer: instruction.keys.length > 2 ? instruction.keys[2].pubkey : undefined, addresses: addresses.map(buffer => new PublicKey(buffer)) }; } static decodeCloseLookupTable(instruction) { this.checkProgramId(instruction.programId); this.checkKeysLength(instruction.keys, 3); return { lookupTable: instruction.keys[0].pubkey, authority: instruction.keys[1].pubkey, recipient: instruction.keys[2].pubkey }; } static decodeFreezeLookupTable(instruction) { this.checkProgramId(instruction.programId); this.checkKeysLength(instruction.keys, 2); return { lookupTable: instruction.keys[0].pubkey, authority: instruction.keys[1].pubkey }; } static decodeDeactivateLookupTable(instruction) { this.checkProgramId(instruction.programId); this.checkKeysLength(instruction.keys, 2); return { lookupTable: instruction.keys[0].pubkey, authority: instruction.keys[1].pubkey }; } /** * @internal */ static checkProgramId(programId) { if (!programId.equals(AddressLookupTableProgram.programId)) { throw new Error('invalid instruction; programId is not AddressLookupTable Program'); } } /** * @internal */ static checkKeysLength(keys, expectedLength) { if (keys.length < expectedLength) { throw new Error(`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`); } } } class AddressLookupTableProgram { /** * @internal */ constructor() {} static createLookupTable(params) { const [lookupTableAddress, bumpSeed] = PublicKey.findProgramAddressSync([params.authority.toBuffer(), toBufferLE_1(BigInt(params.recentSlot), 8)], this.programId); const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.CreateLookupTable; const data = encodeData(type, { recentSlot: BigInt(params.recentSlot), bumpSeed: bumpSeed }); const keys = [{ pubkey: lookupTableAddress, isSigner: false, isWritable: true }, { pubkey: params.authority, isSigner: true, isWritable: false }, { pubkey: params.payer, isSigner: true, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }]; return [new TransactionInstruction({ programId: this.programId, keys: keys, data: data }), lookupTableAddress]; } static freezeLookupTable(params) { const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.FreezeLookupTable; const data = encodeData(type); const keys = [{ pubkey: params.lookupTable, isSigner: false, isWritable: true }, { pubkey: params.authority, isSigner: true, isWritable: false }]; return new TransactionInstruction({ programId: this.programId, keys: keys, data: data }); } static extendLookupTable(params) { const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.ExtendLookupTable; const data = encodeData(type, { addresses: params.addresses.map(addr => addr.toBytes()) }); const keys = [{ pubkey: params.lookupTable, isSigner: false, isWritable: true }, { pubkey: params.authority, isSigner: true, isWritable: false }]; if (params.payer) { keys.push({ pubkey: params.payer, isSigner: true, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }); } return new TransactionInstruction({ programId: this.programId, keys: keys, data: data }); } static deactivateLookupTable(params) { const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.DeactivateLookupTable; const data = encodeData(type); const keys = [{ pubkey: params.lookupTable, isSigner: false, isWritable: true }, { pubkey: params.authority, isSigner: true, isWritable: false }]; return new TransactionInstruction({ programId: this.programId, keys: keys, data: data }); } static closeLookupTable(params) { const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.CloseLookupTable; const data = encodeData(type); const keys = [{ pubkey: params.lookupTable, isSigner: false, isWritable: true }, { pubkey: params.authority, isSigner: true, isWritable: false }, { pubkey: params.recipient, isSigner: false, isWritable: true }]; return new TransactionInstruction({ programId: this.programId, keys: keys, data: data }); } } AddressLookupTableProgram.programId = new PublicKey('AddressLookupTab1e1111111111111111111111111'); /** * Compute Budget Instruction class */ class ComputeBudgetInstruction { /** * @internal */ constructor() {} /** * Decode a compute budget instruction and retrieve the instruction type. */ static decodeInstructionType(instruction) { this.checkProgramId(instruction.programId); const instructionTypeLayout = u8('instruction'); const typeIndex = instructionTypeLayout.decode(instruction.data); let type; for (const [ixType, layout] of Object.entries(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS)) { if (layout.index == typeIndex) { type = ixType; break; } } if (!type) { throw new Error('Instruction type incorrect; not a ComputeBudgetInstruction'); } return type; } /** * Decode request units compute budget instruction and retrieve the instruction params. */ static decodeRequestUnits(instruction) { this.checkProgramId(instruction.programId); const { units, additionalFee } = decodeData$1(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits, instruction.data); return { units, additionalFee }; } /** * Decode request heap frame compute budget instruction and retrieve the instruction params. */ static decodeRequestHeapFrame(instruction) { this.checkProgramId(instruction.programId); const { bytes } = decodeData$1(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame, instruction.data); return { bytes }; } /** * Decode set compute unit limit compute budget instruction and retrieve the instruction params. */ static decodeSetComputeUnitLimit(instruction) { this.checkProgramId(instruction.programId); const { units } = decodeData$1(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitLimit, instruction.data); return { units }; } /** * Decode set compute unit price compute budget instruction and retrieve the instruction params. */ static decodeSetComputeUnitPrice(instruction) { this.checkProgramId(instruction.programId); const { microLamports } = decodeData$1(COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitPrice, instruction.data); return { microLamports }; } /** * @internal */ static checkProgramId(programId) { if (!programId.equals(ComputeBudgetProgram.programId)) { throw new Error('invalid instruction; programId is not ComputeBudgetProgram'); } } } /** * An enumeration of valid ComputeBudgetInstructionType's */ /** * Request units instruction params */ /** * Request heap frame instruction params */ /** * Set compute unit limit instruction params */ /** * Set compute unit price instruction params */ /** * An enumeration of valid ComputeBudget InstructionType's * @internal */ const COMPUTE_BUDGET_INSTRUCTION_LAYOUTS = Object.freeze({ RequestUnits: { index: 0, layout: struct([u8('instruction'), u32('units'), u32('additionalFee')]) }, RequestHeapFrame: { index: 1, layout: struct([u8('instruction'), u32('bytes')]) }, SetComputeUnitLimit: { index: 2, layout: struct([u8('instruction'), u32('units')]) }, SetComputeUnitPrice: { index: 3, layout: struct([u8('instruction'), u64('microLamports')]) } }); /** * Factory class for transaction instructions to interact with the Compute Budget program */ class ComputeBudgetProgram { /** * @internal */ constructor() {} /** * Public key that identifies the Compute Budget program */ /** * @deprecated Instead, call {@link setComputeUnitLimit} and/or {@link setComputeUnitPrice} */ static requestUnits(params) { const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestUnits; const data = encodeData(type, params); return new TransactionInstruction({ keys: [], programId: this.programId, data }); } static requestHeapFrame(params) { const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.RequestHeapFrame; const data = encodeData(type, params); return new TransactionInstruction({ keys: [], programId: this.programId, data }); } static setComputeUnitLimit(params) { const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitLimit; const data = encodeData(type, params); return new TransactionInstruction({ keys: [], programId: this.programId, data }); } static setComputeUnitPrice(params) { const type = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS.SetComputeUnitPrice; const data = encodeData(type, { microLamports: BigInt(params.microLamports) }); return new TransactionInstruction({ keys: [], programId: this.programId, data }); } } ComputeBudgetProgram.programId = new PublicKey('ComputeBudget111111111111111111111111111111'); const PRIVATE_KEY_BYTES$1 = 64; const PUBLIC_KEY_BYTES$1 = 32; const SIGNATURE_BYTES = 64; /** * Params for creating an ed25519 instruction using a public key */ /** * Params for creating an ed25519 instruction using a private key */ const ED25519_INSTRUCTION_LAYOUT = struct([u8('numSignatures'), u8('padding'), u16('signatureOffset'), u16('signatureInstructionIndex'), u16('publicKeyOffset'), u16('publicKeyInstructionIndex'), u16('messageDataOffset'), u16('messageDataSize'), u16('messageInstructionIndex')]); class Ed25519Program { /** * @internal */ constructor() {} /** * Public key that identifies the ed25519 program */ /** * Create an ed25519 instruction with a public key and signature. The * public key must be a buffer that is 32 bytes long, and the signature * must be a buffer of 64 bytes. */ static createInstructionWithPublicKey(params) { const { publicKey, message, signature, instructionIndex } = params; assert$1(publicKey.length === PUBLIC_KEY_BYTES$1, `Public Key must be ${PUBLIC_KEY_BYTES$1} bytes but received ${publicKey.length} bytes`); assert$1(signature.length === SIGNATURE_BYTES, `Signature must be ${SIGNATURE_BYTES} bytes but received ${signature.length} bytes`); const publicKeyOffset = ED25519_INSTRUCTION_LAYOUT.span; const signatureOffset = publicKeyOffset + publicKey.length; const messageDataOffset = signatureOffset + signature.length; const numSignatures = 1; const instructionData = buffer.Buffer.alloc(messageDataOffset + message.length); const index = instructionIndex == null ? 0xffff // An index of `u16::MAX` makes it default to the current instruction. : instructionIndex; ED25519_INSTRUCTION_LAYOUT.encode({ numSignatures, padding: 0, signatureOffset, signatureInstructionIndex: index, publicKeyOffset, publicKeyInstructionIndex: index, messageDataOffset, messageDataSize: message.length, messageInstructionIndex: index }, instructionData); instructionData.fill(publicKey, publicKeyOffset); instructionData.fill(signature, signatureOffset); instructionData.fill(message, messageDataOffset); return new TransactionInstruction({ keys: [], programId: Ed25519Program.programId, data: instructionData }); } /** * Create an ed25519 instruction with a private key. The private key * must be a buffer that is 64 bytes long. */ static createInstructionWithPrivateKey(params) { const { privateKey, message, instructionIndex } = params; assert$1(privateKey.length === PRIVATE_KEY_BYTES$1, `Private key must be ${PRIVATE_KEY_BYTES$1} bytes but received ${privateKey.length} bytes`); try { const keypair = Keypair.fromSecretKey(privateKey); const publicKey = keypair.publicKey.toBytes(); const signature = sign(message, keypair.secretKey); return this.createInstructionWithPublicKey({ publicKey, message, signature, instructionIndex }); } catch (error) { throw new Error(`Error creating instruction; ${error}`); } } } Ed25519Program.programId = new PublicKey('Ed25519SigVerify111111111111111111111111111'); const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); const _32n = /* @__PURE__ */ BigInt(32); // We are not using BigUint64Array, because they are extremely slow as per 2022 function fromBig(n, le = false) { if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) }; return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 }; } function split(lst, le = false) { let Ah = new Uint32Array(lst.length); let Al = new Uint32Array(lst.length); for (let i = 0; i < lst.length; i++) { const { h, l } = fromBig(lst[i], le); [Ah[i], Al[i]] = [h, l]; } return [Ah, Al]; } // Left rotate for Shift in [1, 32) const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); // Left rotate for Shift in (32, 64), NOTE: 32 is special case. const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); // SHA3 (keccak) is based on a new design: basically, the internal state is bigger than output size. // It's called a sponge function. // Various per round constants calculations const [SHA3_PI, SHA3_ROTL, _SHA3_IOTA] = [[], [], []]; const _0n$1 = /* @__PURE__ */ BigInt(0); const _1n$2 = /* @__PURE__ */ BigInt(1); const _2n$1 = /* @__PURE__ */ BigInt(2); const _7n = /* @__PURE__ */ BigInt(7); const _256n = /* @__PURE__ */ BigInt(256); const _0x71n = /* @__PURE__ */ BigInt(0x71); for (let round = 0, R = _1n$2, x = 1, y = 0; round < 24; round++) { // Pi [x, y] = [y, (2 * x + 3 * y) % 5]; SHA3_PI.push(2 * (5 * y + x)); // Rotational SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64); // Iota let t = _0n$1; for (let j = 0; j < 7; j++) { R = ((R << _1n$2) ^ ((R >> _7n) * _0x71n)) % _256n; if (R & _2n$1) t ^= _1n$2 << ((_1n$2 << /* @__PURE__ */ BigInt(j)) - _1n$2); } _SHA3_IOTA.push(t); } const [SHA3_IOTA_H, SHA3_IOTA_L] = /* @__PURE__ */ split(_SHA3_IOTA, true); // Left rotation (without 0, 32, 64) const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s)); const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s)); // Same as keccakf1600, but allows to skip some rounds function keccakP(s, rounds = 24) { const B = new Uint32Array(5 * 2); // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js) for (let round = 24 - rounds; round < 24; round++) { // Theta θ for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; for (let x = 0; x < 10; x += 2) { const idx1 = (x + 8) % 10; const idx0 = (x + 2) % 10; const B0 = B[idx0]; const B1 = B[idx0 + 1]; const Th = rotlH(B0, B1, 1) ^ B[idx1]; const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1]; for (let y = 0; y < 50; y += 10) { s[x + y] ^= Th; s[x + y + 1] ^= Tl; } } // Rho (ρ) and Pi (π) let curH = s[2]; let curL = s[3]; for (let t = 0; t < 24; t++) { const shift = SHA3_ROTL[t]; const Th = rotlH(curH, curL, shift); const Tl = rotlL(curH, curL, shift); const PI = SHA3_PI[t]; curH = s[PI]; curL = s[PI + 1]; s[PI] = Th; s[PI + 1] = Tl; } // Chi (χ) for (let y = 0; y < 50; y += 10) { for (let x = 0; x < 10; x++) B[x] = s[y + x]; for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10]; } // Iota (ι) s[0] ^= SHA3_IOTA_H[round]; s[1] ^= SHA3_IOTA_L[round]; } B.fill(0); } class Keccak extends Hash { // NOTE: we accept arguments in bytes instead of bits here. constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { super(); this.blockLen = blockLen; this.suffix = suffix; this.outputLen = outputLen; this.enableXOF = enableXOF; this.rounds = rounds; this.pos = 0; this.posOut = 0; this.finished = false; this.destroyed = false; // Can be passed from user as dkLen number$1(outputLen); // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes if (0 >= this.blockLen || this.blockLen >= 200) throw new Error('Sha3 supports only keccak-f1600 function'); this.state = new Uint8Array(200); this.state32 = u32$1(this.state); } keccak() { keccakP(this.state32, this.rounds); this.posOut = 0; this.pos = 0; } update(data) { exists(this); const { blockLen, state } = this; data = toBytes(data); const len = data.length; for (let pos = 0; pos < len;) { const take = Math.min(blockLen - this.pos, len - pos); for (let i = 0; i < take; i++) state[this.pos++] ^= data[pos++]; if (this.pos === blockLen) this.keccak(); } return this; } finish() { if (this.finished) return; this.finished = true; const { state, suffix, pos, blockLen } = this; // Do the padding state[pos] ^= suffix; if ((suffix & 0x80) !== 0 && pos === blockLen - 1) this.keccak(); state[blockLen - 1] ^= 0x80; this.keccak(); } writeInto(out) { exists(this, false); bytes(out); this.finish(); const bufferOut = this.state; const { blockLen } = this; for (let pos = 0, len = out.length; pos < len;) { if (this.posOut >= blockLen) this.keccak(); const take = Math.min(blockLen - this.posOut, len - pos); out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); this.posOut += take; pos += take; } return out; } xofInto(out) { // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF if (!this.enableXOF) throw new Error('XOF is not possible for this instance'); return this.writeInto(out); } xof(bytes) { number$1(bytes); return this.xofInto(new Uint8Array(bytes)); } digestInto(out) { output(out, this); if (this.finished) throw new Error('digest() was already called'); this.writeInto(out); this.destroy(); return out; } digest() { return this.digestInto(new Uint8Array(this.outputLen)); } destroy() { this.destroyed = true; this.state.fill(0); } _cloneInto(to) { const { blockLen, suffix, outputLen, rounds, enableXOF } = this; to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds)); to.state32.set(this.state32); to.pos = this.pos; to.posOut = this.posOut; to.finished = this.finished; to.rounds = rounds; // Suffix can change in cSHAKE to.suffix = suffix; to.outputLen = outputLen; to.enableXOF = enableXOF; to.destroyed = this.destroyed; return to; } } const gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen)); /** * keccak-256 hash function. Different from SHA3-256. * @param message - that would be hashed */ const keccak_256 = /* @__PURE__ */ gen(0x01, 136, 256 / 8); // SHA2-256 need to try 2^128 hashes to execute birthday attack. // BTC network is doing 2^67 hashes/sec as per early 2023. // Round constants: // first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) // prettier-ignore const SHA256_K = /* @__PURE__ */ new Uint32Array([ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]); // Initial state: // first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 // prettier-ignore const SHA256_IV = /* @__PURE__ */ new Uint32Array([ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]); // Temporary buffer, not used to store anything between runs // Named this way because it matches specification. const SHA256_W = /* @__PURE__ */ new Uint32Array(64); class SHA256 extends HashMD { constructor() { super(64, 32, 8, false); // We cannot use array here since array allows indexing by variable // which means optimizer/compiler cannot use registers. this.A = SHA256_IV[0] | 0; this.B = SHA256_IV[1] | 0; this.C = SHA256_IV[2] | 0; this.D = SHA256_IV[3] | 0; this.E = SHA256_IV[4] | 0; this.F = SHA256_IV[5] | 0; this.G = SHA256_IV[6] | 0; this.H = SHA256_IV[7] | 0; } get() { const { A, B, C, D, E, F, G, H } = this; return [A, B, C, D, E, F, G, H]; } // prettier-ignore set(A, B, C, D, E, F, G, H) { this.A = A | 0; this.B = B | 0; this.C = C | 0; this.D = D | 0; this.E = E | 0; this.F = F | 0; this.G = G | 0; this.H = H | 0; } process(view, offset) { // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false); for (let i = 16; i < 64; i++) { const W15 = SHA256_W[i - 15]; const W2 = SHA256_W[i - 2]; const s0 = rotr$1(W15, 7) ^ rotr$1(W15, 18) ^ (W15 >>> 3); const s1 = rotr$1(W2, 17) ^ rotr$1(W2, 19) ^ (W2 >>> 10); SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0; } // Compression function main loop, 64 rounds let { A, B, C, D, E, F, G, H } = this; for (let i = 0; i < 64; i++) { const sigma1 = rotr$1(E, 6) ^ rotr$1(E, 11) ^ rotr$1(E, 25); const T1 = (H + sigma1 + Chi$1(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0; const sigma0 = rotr$1(A, 2) ^ rotr$1(A, 13) ^ rotr$1(A, 22); const T2 = (sigma0 + Maj$1(A, B, C)) | 0; H = G; G = F; F = E; E = (D + T1) | 0; D = C; C = B; B = A; A = (T1 + T2) | 0; } // Add the compressed chunk to the current hash value A = (A + this.A) | 0; B = (B + this.B) | 0; C = (C + this.C) | 0; D = (D + this.D) | 0; E = (E + this.E) | 0; F = (F + this.F) | 0; G = (G + this.G) | 0; H = (H + this.H) | 0; this.set(A, B, C, D, E, F, G, H); } roundClean() { SHA256_W.fill(0); } destroy() { this.set(0, 0, 0, 0, 0, 0, 0, 0); this.buffer.fill(0); } } /** * SHA2-256 hash function * @param message - data that would be hashed */ const sha256 = /* @__PURE__ */ wrapConstructor$1(() => new SHA256()); /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // Short Weierstrass curve. The formula is: y² = x³ + ax + b function validatePointOpts(curve) { const opts = validateBasic(curve); validateObject(opts, { a: 'field', b: 'field', }, { allowedPrivateKeyLengths: 'array', wrapPrivateKey: 'boolean', isTorsionFree: 'function', clearCofactor: 'function', allowInfinityPoint: 'boolean', fromBytes: 'function', toBytes: 'function', }); const { endo, Fp, a } = opts; if (endo) { if (!Fp.eql(a, Fp.ZERO)) { throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0'); } if (typeof endo !== 'object' || typeof endo.beta !== 'bigint' || typeof endo.splitScalar !== 'function') { throw new Error('Expected endomorphism with beta: bigint and splitScalar: function'); } } return Object.freeze({ ...opts }); } // ASN.1 DER encoding utilities const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut; const DER = { // asn.1 DER encoding utils Err: class DERErr extends Error { constructor(m = '') { super(m); } }, _parseInt(data) { const { Err: E } = DER; if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag'); const len = data[1]; const res = data.subarray(2, len + 2); if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length'); // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, // since we always use positive integers here. It must always be empty: // - add zero byte if exists // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative'); if (res[0] === 0x00 && !(res[1] & 0b10000000)) throw new E('Invalid signature integer: unnecessary leading zero'); return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left }, toSig(hex) { // parse DER signature const { Err: E } = DER; const data = typeof hex === 'string' ? h2b(hex) : hex; abytes(data); let l = data.length; if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag'); if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length'); const { d: r, l: sBytes } = DER._parseInt(data.subarray(2)); const { d: s, l: rBytesLeft } = DER._parseInt(sBytes); if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing'); return { r, s }; }, hexFromSig(sig) { // Add leading zero if first byte has negative bit enabled. More details in '_parseInt' const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s); const h = (num) => { const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; }; const s = slice(h(sig.s)); const r = slice(h(sig.r)); const shl = s.length / 2; const rhl = r.length / 2; const sl = h(shl); const rl = h(rhl); return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`; }, }; // Be friendly to bad ECMAScript parsers by not using bigint literals // prettier-ignore const _0n = BigInt(0), _1n$1 = BigInt(1); BigInt(2); const _3n = BigInt(3); BigInt(4); function weierstrassPoints(opts) { const CURVE = validatePointOpts(opts); const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ const toBytes = CURVE.toBytes || ((_c, point, _isCompressed) => { const a = point.toAffine(); return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)); }); const fromBytes = CURVE.fromBytes || ((bytes) => { // const head = bytes[0]; const tail = bytes.subarray(1); // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)); const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)); return { x, y }; }); /** * y² = x³ + ax + b: Short weierstrass curve formula * @returns y² */ function weierstrassEquation(x) { const { a, b } = CURVE; const x2 = Fp.sqr(x); // x * x const x3 = Fp.mul(x2, x); // x2 * x return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b } // Validate whether the passed curve params are valid. // We check if curve equation works for generator point. // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. // ProjectivePoint class has not been initialized yet. if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) throw new Error('bad generator point: equation left != right'); // Valid group elements reside in range 1..n-1 function isWithinCurveOrder(num) { return typeof num === 'bigint' && _0n < num && num < CURVE.n; } function assertGE(num) { if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n'); } // Validates if priv key is valid and converts it to bigint. // Supports options allowedPrivateKeyLengths and wrapPrivateKey. function normPrivateKeyToScalar(key) { const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE; if (lengths && typeof key !== 'bigint') { if (isBytes$2(key)) key = bytesToHex(key); // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes if (typeof key !== 'string' || !lengths.includes(key.length)) throw new Error('Invalid key'); key = key.padStart(nByteLength * 2, '0'); } let num; try { num = typeof key === 'bigint' ? key : bytesToNumberBE(ensureBytes('private key', key, nByteLength)); } catch (error) { throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`); } if (wrapPrivateKey) num = mod(num, n); // disabled by default, enabled for BLS assertGE(num); // num in range [1..N-1] return num; } const pointPrecomputes = new Map(); function assertPrjPoint(other) { if (!(other instanceof Point)) throw new Error('ProjectivePoint expected'); } /** * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) * Default Point works in 2d / affine coordinates: (x, y) * We're doing calculations in projective, because its operations don't require costly inversion. */ class Point { constructor(px, py, pz) { this.px = px; this.py = py; this.pz = pz; if (px == null || !Fp.isValid(px)) throw new Error('x required'); if (py == null || !Fp.isValid(py)) throw new Error('y required'); if (pz == null || !Fp.isValid(pz)) throw new Error('z required'); } // Does not validate if the point is on-curve. // Use fromHex instead, or call assertValidity() later. static fromAffine(p) { const { x, y } = p || {}; if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point'); if (p instanceof Point) throw new Error('projective point not allowed'); const is0 = (i) => Fp.eql(i, Fp.ZERO); // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) if (is0(x) && is0(y)) return Point.ZERO; return new Point(x, y, Fp.ONE); } get x() { return this.toAffine().x; } get y() { return this.toAffine().y; } /** * Takes a bunch of Projective Points but executes only one * inversion on all of them. Inversion is very slow operation, * so this improves performance massively. * Optimization: converts a list of projective points to a list of identical points with Z=1. */ static normalizeZ(points) { const toInv = Fp.invertBatch(points.map((p) => p.pz)); return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine); } /** * Converts hash string or Uint8Array to Point. * @param hex short/long ECDSA hex */ static fromHex(hex) { const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))); P.assertValidity(); return P; } // Multiplies generator point by privateKey. static fromPrivateKey(privateKey) { return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)); } // "Private method", don't use it directly _setWindowSize(windowSize) { this._WINDOW_SIZE = windowSize; pointPrecomputes.delete(this); } // A point on curve is valid if it conforms to equation. assertValidity() { if (this.is0()) { // (0, 1, 0) aka ZERO is invalid in most contexts. // In BLS, ZERO can be serialized, so we allow it. // (0, 0, 0) is wrong representation of ZERO and is always invalid. if (CURVE.allowInfinityPoint && !Fp.is0(this.py)) return; throw new Error('bad point: ZERO'); } // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` const { x, y } = this.toAffine(); // Check if x, y are valid field elements if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE'); const left = Fp.sqr(y); // y² const right = weierstrassEquation(x); // x³ + ax + b if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right'); if (!this.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup'); } hasEvenY() { const { y } = this.toAffine(); if (Fp.isOdd) return !Fp.isOdd(y); throw new Error("Field doesn't support isOdd"); } /** * Compare one point to another. */ equals(other) { assertPrjPoint(other); const { px: X1, py: Y1, pz: Z1 } = this; const { px: X2, py: Y2, pz: Z2 } = other; const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)); const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)); return U1 && U2; } /** * Flips point to one corresponding to (x, -y) in Affine coordinates. */ negate() { return new Point(this.px, Fp.neg(this.py), this.pz); } // Renes-Costello-Batina exception-free doubling formula. // There is 30% faster Jacobian formula, but it is not complete. // https://eprint.iacr.org/2015/1060, algorithm 3 // Cost: 8M + 3S + 3*a + 2*b3 + 15add. double() { const { a, b } = CURVE; const b3 = Fp.mul(b, _3n); const { px: X1, py: Y1, pz: Z1 } = this; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore let t0 = Fp.mul(X1, X1); // step 1 let t1 = Fp.mul(Y1, Y1); let t2 = Fp.mul(Z1, Z1); let t3 = Fp.mul(X1, Y1); t3 = Fp.add(t3, t3); // step 5 Z3 = Fp.mul(X1, Z1); Z3 = Fp.add(Z3, Z3); X3 = Fp.mul(a, Z3); Y3 = Fp.mul(b3, t2); Y3 = Fp.add(X3, Y3); // step 10 X3 = Fp.sub(t1, Y3); Y3 = Fp.add(t1, Y3); Y3 = Fp.mul(X3, Y3); X3 = Fp.mul(t3, X3); Z3 = Fp.mul(b3, Z3); // step 15 t2 = Fp.mul(a, t2); t3 = Fp.sub(t0, t2); t3 = Fp.mul(a, t3); t3 = Fp.add(t3, Z3); Z3 = Fp.add(t0, t0); // step 20 t0 = Fp.add(Z3, t0); t0 = Fp.add(t0, t2); t0 = Fp.mul(t0, t3); Y3 = Fp.add(Y3, t0); t2 = Fp.mul(Y1, Z1); // step 25 t2 = Fp.add(t2, t2); t0 = Fp.mul(t2, t3); X3 = Fp.sub(X3, t0); Z3 = Fp.mul(t2, t1); Z3 = Fp.add(Z3, Z3); // step 30 Z3 = Fp.add(Z3, Z3); return new Point(X3, Y3, Z3); } // Renes-Costello-Batina exception-free addition formula. // There is 30% faster Jacobian formula, but it is not complete. // https://eprint.iacr.org/2015/1060, algorithm 1 // Cost: 12M + 0S + 3*a + 3*b3 + 23add. add(other) { assertPrjPoint(other); const { px: X1, py: Y1, pz: Z1 } = this; const { px: X2, py: Y2, pz: Z2 } = other; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore const a = CURVE.a; const b3 = Fp.mul(CURVE.b, _3n); let t0 = Fp.mul(X1, X2); // step 1 let t1 = Fp.mul(Y1, Y2); let t2 = Fp.mul(Z1, Z2); let t3 = Fp.add(X1, Y1); let t4 = Fp.add(X2, Y2); // step 5 t3 = Fp.mul(t3, t4); t4 = Fp.add(t0, t1); t3 = Fp.sub(t3, t4); t4 = Fp.add(X1, Z1); let t5 = Fp.add(X2, Z2); // step 10 t4 = Fp.mul(t4, t5); t5 = Fp.add(t0, t2); t4 = Fp.sub(t4, t5); t5 = Fp.add(Y1, Z1); X3 = Fp.add(Y2, Z2); // step 15 t5 = Fp.mul(t5, X3); X3 = Fp.add(t1, t2); t5 = Fp.sub(t5, X3); Z3 = Fp.mul(a, t4); X3 = Fp.mul(b3, t2); // step 20 Z3 = Fp.add(X3, Z3); X3 = Fp.sub(t1, Z3); Z3 = Fp.add(t1, Z3); Y3 = Fp.mul(X3, Z3); t1 = Fp.add(t0, t0); // step 25 t1 = Fp.add(t1, t0); t2 = Fp.mul(a, t2); t4 = Fp.mul(b3, t4); t1 = Fp.add(t1, t2); t2 = Fp.sub(t0, t2); // step 30 t2 = Fp.mul(a, t2); t4 = Fp.add(t4, t2); t0 = Fp.mul(t1, t4); Y3 = Fp.add(Y3, t0); t0 = Fp.mul(t5, t4); // step 35 X3 = Fp.mul(t3, X3); X3 = Fp.sub(X3, t0); t0 = Fp.mul(t3, t1); Z3 = Fp.mul(t5, Z3); Z3 = Fp.add(Z3, t0); // step 40 return new Point(X3, Y3, Z3); } subtract(other) { return this.add(other.negate()); } is0() { return this.equals(Point.ZERO); } wNAF(n) { return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => { const toInv = Fp.invertBatch(comp.map((p) => p.pz)); return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine); }); } /** * Non-constant-time multiplication. Uses double-and-add algorithm. * It's faster, but should only be used when you don't care about * an exposed private key e.g. sig verification, which works over *public* keys. */ multiplyUnsafe(n) { const I = Point.ZERO; if (n === _0n) return I; assertGE(n); // Will throw on 0 if (n === _1n$1) return this; const { endo } = CURVE; if (!endo) return wnaf.unsafeLadder(this, n); // Apply endomorphism let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); let k1p = I; let k2p = I; let d = this; while (k1 > _0n || k2 > _0n) { if (k1 & _1n$1) k1p = k1p.add(d); if (k2 & _1n$1) k2p = k2p.add(d); d = d.double(); k1 >>= _1n$1; k2 >>= _1n$1; } if (k1neg) k1p = k1p.negate(); if (k2neg) k2p = k2p.negate(); k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz); return k1p.add(k2p); } /** * Constant time multiplication. * Uses wNAF method. Windowed method may be 10% faster, * but takes 2x longer to generate and consumes 2x memory. * Uses precomputes when available. * Uses endomorphism for Koblitz curves. * @param scalar by which the point would be multiplied * @returns New point */ multiply(scalar) { assertGE(scalar); let n = scalar; let point, fake; // Fake point is used to const-time mult const { endo } = CURVE; if (endo) { const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n); let { p: k1p, f: f1p } = this.wNAF(k1); let { p: k2p, f: f2p } = this.wNAF(k2); k1p = wnaf.constTimeNegate(k1neg, k1p); k2p = wnaf.constTimeNegate(k2neg, k2p); k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz); point = k1p.add(k2p); fake = f1p.add(f2p); } else { const { p, f } = this.wNAF(n); point = p; fake = f; } // Normalize `z` for both points, but return only real one return Point.normalizeZ([point, fake])[0]; } /** * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. * Not using Strauss-Shamir trick: precomputation tables are faster. * The trick could be useful if both P and Q are not G (not in our case). * @returns non-zero affine point */ multiplyAndAddUnsafe(Q, a, b) { const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes const mul = (P, a // Select faster multiply() method ) => (a === _0n || a === _1n$1 || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)); const sum = mul(this, a).add(mul(Q, b)); return sum.is0() ? undefined : sum; } // Converts Projective point to affine (x, y) coordinates. // Can accept precomputed Z^-1 - for example, from invertBatch. // (x, y, z) ∋ (x=x/z, y=y/z) toAffine(iz) { const { px: x, py: y, pz: z } = this; const is0 = this.is0(); // If invZ was 0, we return zero point. However we still want to execute // all operations, so we replace invZ with a random number, 1. if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z); const ax = Fp.mul(x, iz); const ay = Fp.mul(y, iz); const zz = Fp.mul(z, iz); if (is0) return { x: Fp.ZERO, y: Fp.ZERO }; if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid'); return { x: ax, y: ay }; } isTorsionFree() { const { h: cofactor, isTorsionFree } = CURVE; if (cofactor === _1n$1) return true; // No subgroups, always torsion-free if (isTorsionFree) return isTorsionFree(Point, this); throw new Error('isTorsionFree() has not been declared for the elliptic curve'); } clearCofactor() { const { h: cofactor, clearCofactor } = CURVE; if (cofactor === _1n$1) return this; // Fast-path if (clearCofactor) return clearCofactor(Point, this); return this.multiplyUnsafe(CURVE.h); } toRawBytes(isCompressed = true) { this.assertValidity(); return toBytes(Point, this, isCompressed); } toHex(isCompressed = true) { return bytesToHex(this.toRawBytes(isCompressed)); } } Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE); Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); const _bits = CURVE.nBitLength; const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits); // Validate if generator point is on curve return { CURVE, ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, }; } function validateOpts(curve) { const opts = validateBasic(curve); validateObject(opts, { hash: 'hash', hmac: 'function', randomBytes: 'function', }, { bits2int: 'function', bits2int_modN: 'function', lowS: 'boolean', }); return Object.freeze({ lowS: true, ...opts }); } function weierstrass(curveDef) { const CURVE = validateOpts(curveDef); const { Fp, n: CURVE_ORDER } = CURVE; const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32 const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32 function isValidFieldElement(num) { return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE } function modN(a) { return mod(a, CURVE_ORDER); } function invN(a) { return invert(a, CURVE_ORDER); } const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({ ...CURVE, toBytes(_c, point, isCompressed) { const a = point.toAffine(); const x = Fp.toBytes(a.x); const cat = concatBytes; if (isCompressed) { return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x); } else { return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)); } }, fromBytes(bytes) { const len = bytes.length; const head = bytes[0]; const tail = bytes.subarray(1); // this.assertValidity() is done inside of fromHex if (len === compressedLen && (head === 0x02 || head === 0x03)) { const x = bytesToNumberBE(tail); if (!isValidFieldElement(x)) throw new Error('Point is not on curve'); const y2 = weierstrassEquation(x); // y² = x³ + ax + b let y; try { y = Fp.sqrt(y2); // y = y² ^ (p+1)/4 } catch (sqrtError) { const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : ''; throw new Error('Point is not on curve' + suffix); } const isYOdd = (y & _1n$1) === _1n$1; // ECDSA const isHeadOdd = (head & 1) === 1; if (isHeadOdd !== isYOdd) y = Fp.neg(y); return { x, y }; } else if (len === uncompressedLen && head === 0x04) { const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)); const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)); return { x, y }; } else { throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`); } }, }); const numToNByteStr = (num) => bytesToHex(numberToBytesBE(num, CURVE.nByteLength)); function isBiggerThanHalfOrder(number) { const HALF = CURVE_ORDER >> _1n$1; return number > HALF; } function normalizeS(s) { return isBiggerThanHalfOrder(s) ? modN(-s) : s; } // slice bytes num const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to)); /** * ECDSA signature with its (r, s) properties. Supports DER & compact representations. */ class Signature { constructor(r, s, recovery) { this.r = r; this.s = s; this.recovery = recovery; this.assertValidity(); } // pair (bytes of r, bytes of s) static fromCompact(hex) { const l = CURVE.nByteLength; hex = ensureBytes('compactSignature', hex, l * 2); return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)); } // DER encoded ECDSA signature // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script static fromDER(hex) { const { r, s } = DER.toSig(ensureBytes('DER', hex)); return new Signature(r, s); } assertValidity() { // can use assertGE here if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < CURVE.n'); if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < CURVE.n'); } addRecoveryBit(recovery) { return new Signature(this.r, this.s, recovery); } recoverPublicKey(msgHash) { const { r, s, recovery: rec } = this; const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid'); const radj = rec === 2 || rec === 3 ? r + CURVE.n : r; if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid'); const prefix = (rec & 1) === 0 ? '02' : '03'; const R = Point.fromHex(prefix + numToNByteStr(radj)); const ir = invN(radj); // r^-1 const u1 = modN(-h * ir); // -hr^-1 const u2 = modN(s * ir); // sr^-1 const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) if (!Q) throw new Error('point at infinify'); // unsafe is fine: no priv data leaked Q.assertValidity(); return Q; } // Signatures should be low-s, to prevent malleability. hasHighS() { return isBiggerThanHalfOrder(this.s); } normalizeS() { return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this; } // DER-encoded toDERRawBytes() { return hexToBytes(this.toDERHex()); } toDERHex() { return DER.hexFromSig({ r: this.r, s: this.s }); } // padded bytes of r, then padded bytes of s toCompactRawBytes() { return hexToBytes(this.toCompactHex()); } toCompactHex() { return numToNByteStr(this.r) + numToNByteStr(this.s); } } const utils = { isValidPrivateKey(privateKey) { try { normPrivateKeyToScalar(privateKey); return true; } catch (error) { return false; } }, normPrivateKeyToScalar: normPrivateKeyToScalar, /** * Produces cryptographically secure private key from random of size * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. */ randomPrivateKey: () => { const length = getMinHashLength(CURVE.n); return mapHashToField(CURVE.randomBytes(length), CURVE.n); }, /** * Creates precompute table for an arbitrary EC point. Makes point "cached". * Allows to massively speed-up `point.multiply(scalar)`. * @returns cached point * @example * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); * fast.multiply(privKey); // much faster ECDH now */ precompute(windowSize = 8, point = Point.BASE) { point._setWindowSize(windowSize); point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here return point; }, }; /** * Computes public key for a private key. Checks for validity of the private key. * @param privateKey private key * @param isCompressed whether to return compact (default), or full key * @returns Public key, full when isCompressed=false; short when isCompressed=true */ function getPublicKey(privateKey, isCompressed = true) { return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed); } /** * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. */ function isProbPub(item) { const arr = isBytes$2(item); const str = typeof item === 'string'; const len = (arr || str) && item.length; if (arr) return len === compressedLen || len === uncompressedLen; if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen; if (item instanceof Point) return true; return false; } /** * ECDH (Elliptic Curve Diffie Hellman). * Computes shared public key from private key and public key. * Checks: 1) private key validity 2) shared key is on-curve. * Does NOT hash the result. * @param privateA private key * @param publicB different public key * @param isCompressed whether to return compact (default), or full key * @returns shared public key */ function getSharedSecret(privateA, publicB, isCompressed = true) { if (isProbPub(privateA)) throw new Error('first arg must be private key'); if (!isProbPub(publicB)) throw new Error('second arg must be public key'); const b = Point.fromHex(publicB); // check for being on-curve return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed); } // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors const bits2int = CURVE.bits2int || function (bytes) { // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) // for some cases, since bytes.length * 8 is not actual bitLength. const num = bytesToNumberBE(bytes); // check for == u8 done here const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits return delta > 0 ? num >> BigInt(delta) : num; }; const bits2int_modN = CURVE.bits2int_modN || function (bytes) { return modN(bits2int(bytes)); // can't use bytesToNumberBE here }; // NOTE: pads output with zero as per spec const ORDER_MASK = bitMask(CURVE.nBitLength); /** * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. */ function int2octets(num) { if (typeof num !== 'bigint') throw new Error('bigint expected'); if (!(_0n <= num && num < ORDER_MASK)) throw new Error(`bigint expected < 2^${CURVE.nBitLength}`); // works with order, can have different size than numToField! return numberToBytesBE(num, CURVE.nByteLength); } // Steps A, D of RFC6979 3.2 // Creates RFC6979 seed; converts msg/privKey to numbers. // Used only in sign, not in verify. // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521. // Also it can be bigger for P224 + SHA256 function prepSig(msgHash, privateKey, opts = defaultSigOpts) { if (['recovered', 'canonical'].some((k) => k in opts)) throw new Error('sign() legacy options not supported'); const { hash, randomBytes } = CURVE; let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash msgHash = ensureBytes('msgHash', msgHash); if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)); // We can't later call bits2octets, since nested bits2int is broken for curves // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) const h1int = bits2int_modN(msgHash); const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint const seedArgs = [int2octets(d), int2octets(h1int)]; // extraEntropy. RFC6979 3.6: additional k' (optional). if (ent != null && ent !== false) { // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes } const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2 const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash! // Converts signature params into point w r/s, checks result for validity. function k2sig(kBytes) { // RFC 6979 Section 3.2, step 3: k = bits2int(T) const k = bits2int(kBytes); // Cannot use fields methods, since it is group element if (!isWithinCurveOrder(k)) return; // Important: all mod() calls here must be done over N const ik = invN(k); // k^-1 mod n const q = Point.BASE.multiply(k).toAffine(); // q = Gk const r = modN(q.x); // r = q.x mod n if (r === _0n) return; // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT const s = modN(ik * modN(m + r * d)); // Not using blinding here if (s === _0n) return; let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$1); // recovery bit (2 or 3, when q.x > n) let normS = s; if (lowS && isBiggerThanHalfOrder(s)) { normS = normalizeS(s); // if lowS was passed, ensure s is always recovery ^= 1; // // in the bottom half of N } return new Signature(r, normS, recovery); // use normS, not s } return { seed, k2sig }; } const defaultSigOpts = { lowS: CURVE.lowS, prehash: false }; const defaultVerOpts = { lowS: CURVE.lowS, prehash: false }; /** * Signs message hash with a private key. * ``` * sign(m, d, k) where * (x, y) = G × k * r = x mod n * s = (m + dr)/k mod n * ``` * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. * @param privKey private key * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. * @returns signature with recovery param */ function sign(msgHash, privKey, opts = defaultSigOpts) { const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2. const C = CURVE; const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac); return drbg(seed, k2sig); // Steps B, C, D, E, F, G } // Enable precomputes. Slows down first publicKey computation by 20ms. Point.BASE._setWindowSize(8); // utils.precompute(8, ProjectivePoint.BASE) /** * Verifies a signature against message hash and public key. * Rejects lowS signatures by default: to override, * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: * * ``` * verify(r, s, h, P) where * U1 = hs^-1 mod n * U2 = rs^-1 mod n * R = U1⋅G - U2⋅P * mod(R.x, n) == r * ``` */ function verify(signature, msgHash, publicKey, opts = defaultVerOpts) { const sg = signature; msgHash = ensureBytes('msgHash', msgHash); publicKey = ensureBytes('publicKey', publicKey); if ('strict' in opts) throw new Error('options.strict was renamed to lowS'); const { lowS, prehash } = opts; let _sig = undefined; let P; try { if (typeof sg === 'string' || isBytes$2(sg)) { // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). // Since DER can also be 2*nByteLength bytes, we check for it first. try { _sig = Signature.fromDER(sg); } catch (derError) { if (!(derError instanceof DER.Err)) throw derError; _sig = Signature.fromCompact(sg); } } else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') { const { r, s } = sg; _sig = new Signature(r, s); } else { throw new Error('PARSE'); } P = Point.fromHex(publicKey); } catch (error) { if (error.message === 'PARSE') throw new Error(`signature must be Signature instance, Uint8Array or hex string`); return false; } if (lowS && _sig.hasHighS()) return false; if (prehash) msgHash = CURVE.hash(msgHash); const { r, s } = _sig; const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element const is = invN(s); // s^-1 const u1 = modN(h * is); // u1 = hs^-1 mod n const u2 = modN(r * is); // u2 = rs^-1 mod n const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P if (!R) return false; const v = modN(R.x); return v === r; } return { CURVE, getPublicKey, getSharedSecret, sign, verify, ProjectivePoint: Point, Signature, utils, }; } // HMAC (RFC 2104) class HMAC extends Hash$1 { constructor(hash$1, _key) { super(); this.finished = false; this.destroyed = false; hash(hash$1); const key = toBytes$1(_key); this.iHash = hash$1.create(); if (typeof this.iHash.update !== 'function') throw new Error('Expected instance of class which extends utils.Hash'); this.blockLen = this.iHash.blockLen; this.outputLen = this.iHash.outputLen; const blockLen = this.blockLen; const pad = new Uint8Array(blockLen); // blockLen can be bigger than outputLen pad.set(key.length > blockLen ? hash$1.create().update(key).digest() : key); for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36; this.iHash.update(pad); // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone this.oHash = hash$1.create(); // Undo internal XOR && apply outer XOR for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c; this.oHash.update(pad); pad.fill(0); } update(buf) { exists$1(this); this.iHash.update(buf); return this; } digestInto(out) { exists$1(this); bytes$1(out, this.outputLen); this.finished = true; this.iHash.digestInto(out); this.oHash.update(out); this.oHash.digestInto(out); this.destroy(); } digest() { const out = new Uint8Array(this.oHash.outputLen); this.digestInto(out); return out; } _cloneInto(to) { // Create new instance without calling constructor since key already in state and we don't know it. to || (to = Object.create(Object.getPrototypeOf(this), {})); const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this; to = to; to.finished = finished; to.destroyed = destroyed; to.blockLen = blockLen; to.outputLen = outputLen; to.oHash = oHash._cloneInto(to.oHash); to.iHash = iHash._cloneInto(to.iHash); return to; } destroy() { this.destroyed = true; this.oHash.destroy(); this.iHash.destroy(); } } /** * HMAC: RFC2104 message authentication code. * @param hash - function that would be used e.g. sha256 * @param key - message key * @param message - message data */ const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest(); hmac.create = (hash, key) => new HMAC(hash, key); /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ // connects noble-curves to noble-hashes function getHash(hash) { return { hash, hmac: (key, ...msgs) => hmac(hash, key, concatBytes$1(...msgs)), randomBytes, }; } function createCurve(curveDef, defHash) { const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) }); return Object.freeze({ ...create(defHash), create }); } /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'); const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'); const _1n = BigInt(1); const _2n = BigInt(2); const divNearest = (a, b) => (a + b / _2n) / b; /** * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] */ function sqrtMod(y) { const P = secp256k1P; // prettier-ignore const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22); // prettier-ignore const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88); const b2 = (y * y * y) % P; // x^3, 11 const b3 = (b2 * b2 * y) % P; // x^7 const b6 = (pow2(b3, _3n, P) * b3) % P; const b9 = (pow2(b6, _3n, P) * b3) % P; const b11 = (pow2(b9, _2n, P) * b2) % P; const b22 = (pow2(b11, _11n, P) * b11) % P; const b44 = (pow2(b22, _22n, P) * b22) % P; const b88 = (pow2(b44, _44n, P) * b44) % P; const b176 = (pow2(b88, _88n, P) * b88) % P; const b220 = (pow2(b176, _44n, P) * b44) % P; const b223 = (pow2(b220, _3n, P) * b3) % P; const t1 = (pow2(b223, _23n, P) * b22) % P; const t2 = (pow2(t1, _6n, P) * b2) % P; const root = pow2(t2, _2n, P); if (!Fp.eql(Fp.sqr(root), y)) throw new Error('Cannot find square root'); return root; } const Fp = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }); const secp256k1 = createCurve({ a: BigInt(0), // equation params: a, b b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975 Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n n: secp256k1N, // Curve order, total count of valid points in the field // Base point (x, y) aka generator point Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), h: BigInt(1), // Cofactor lowS: true, // Allow only low-S signatures by default in sign() and verify() /** * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066 */ endo: { beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), splitScalar: (k) => { const n = secp256k1N; const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15'); const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3'); const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'); const b2 = a1; const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16) const c1 = divNearest(b2 * k, n); const c2 = divNearest(-b1 * k, n); let k1 = mod(k - c1 * a1 - c2 * a2, n); let k2 = mod(-c1 * b1 - c2 * b2, n); const k1neg = k1 > POW_2_128; const k2neg = k2 > POW_2_128; if (k1neg) k1 = n - k1; if (k2neg) k2 = n - k2; if (k1 > POW_2_128 || k2 > POW_2_128) { throw new Error('splitScalar: Endomorphism failed, k=' + k); } return { k1neg, k1, k2neg, k2 }; }, }, }, sha256); // Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. // https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BigInt(0); secp256k1.ProjectivePoint; const ecdsaSign = (msgHash, privKey) => { const signature = secp256k1.sign(msgHash, privKey); return [signature.toCompactRawBytes(), signature.recovery]; }; secp256k1.utils.isValidPrivateKey; const publicKeyCreate = secp256k1.getPublicKey; const PRIVATE_KEY_BYTES = 32; const ETHEREUM_ADDRESS_BYTES = 20; const PUBLIC_KEY_BYTES = 64; const SIGNATURE_OFFSETS_SERIALIZED_SIZE = 11; /** * Params for creating an secp256k1 instruction using a public key */ /** * Params for creating an secp256k1 instruction using an Ethereum address */ /** * Params for creating an secp256k1 instruction using a private key */ const SECP256K1_INSTRUCTION_LAYOUT = struct([u8('numSignatures'), u16('signatureOffset'), u8('signatureInstructionIndex'), u16('ethAddressOffset'), u8('ethAddressInstructionIndex'), u16('messageDataOffset'), u16('messageDataSize'), u8('messageInstructionIndex'), blob(20, 'ethAddress'), blob(64, 'signature'), u8('recoveryId')]); class Secp256k1Program { /** * @internal */ constructor() {} /** * Public key that identifies the secp256k1 program */ /** * Construct an Ethereum address from a secp256k1 public key buffer. * @param {Buffer} publicKey a 64 byte secp256k1 public key buffer */ static publicKeyToEthAddress(publicKey) { assert$1(publicKey.length === PUBLIC_KEY_BYTES, `Public key must be ${PUBLIC_KEY_BYTES} bytes but received ${publicKey.length} bytes`); try { return buffer.Buffer.from(keccak_256(toBuffer(publicKey))).slice(-ETHEREUM_ADDRESS_BYTES); } catch (error) { throw new Error(`Error constructing Ethereum address: ${error}`); } } /** * Create an secp256k1 instruction with a public key. The public key * must be a buffer that is 64 bytes long. */ static createInstructionWithPublicKey(params) { const { publicKey, message, signature, recoveryId, instructionIndex } = params; return Secp256k1Program.createInstructionWithEthAddress({ ethAddress: Secp256k1Program.publicKeyToEthAddress(publicKey), message, signature, recoveryId, instructionIndex }); } /** * Create an secp256k1 instruction with an Ethereum address. The address * must be a hex string or a buffer that is 20 bytes long. */ static createInstructionWithEthAddress(params) { const { ethAddress: rawAddress, message, signature, recoveryId, instructionIndex = 0 } = params; let ethAddress; if (typeof rawAddress === 'string') { if (rawAddress.startsWith('0x')) { ethAddress = buffer.Buffer.from(rawAddress.substr(2), 'hex'); } else { ethAddress = buffer.Buffer.from(rawAddress, 'hex'); } } else { ethAddress = rawAddress; } assert$1(ethAddress.length === ETHEREUM_ADDRESS_BYTES, `Address must be ${ETHEREUM_ADDRESS_BYTES} bytes but received ${ethAddress.length} bytes`); const dataStart = 1 + SIGNATURE_OFFSETS_SERIALIZED_SIZE; const ethAddressOffset = dataStart; const signatureOffset = dataStart + ethAddress.length; const messageDataOffset = signatureOffset + signature.length + 1; const numSignatures = 1; const instructionData = buffer.Buffer.alloc(SECP256K1_INSTRUCTION_LAYOUT.span + message.length); SECP256K1_INSTRUCTION_LAYOUT.encode({ numSignatures, signatureOffset, signatureInstructionIndex: instructionIndex, ethAddressOffset, ethAddressInstructionIndex: instructionIndex, messageDataOffset, messageDataSize: message.length, messageInstructionIndex: instructionIndex, signature: toBuffer(signature), ethAddress: toBuffer(ethAddress), recoveryId }, instructionData); instructionData.fill(toBuffer(message), SECP256K1_INSTRUCTION_LAYOUT.span); return new TransactionInstruction({ keys: [], programId: Secp256k1Program.programId, data: instructionData }); } /** * Create an secp256k1 instruction with a private key. The private key * must be a buffer that is 32 bytes long. */ static createInstructionWithPrivateKey(params) { const { privateKey: pkey, message, instructionIndex } = params; assert$1(pkey.length === PRIVATE_KEY_BYTES, `Private key must be ${PRIVATE_KEY_BYTES} bytes but received ${pkey.length} bytes`); try { const privateKey = toBuffer(pkey); const publicKey = publicKeyCreate(privateKey, false /* isCompressed */).slice(1); // throw away leading byte const messageHash = buffer.Buffer.from(keccak_256(toBuffer(message))); const [signature, recoveryId] = ecdsaSign(messageHash, privateKey); return this.createInstructionWithPublicKey({ publicKey, message, signature, recoveryId, instructionIndex }); } catch (error) { throw new Error(`Error creating instruction; ${error}`); } } } Secp256k1Program.programId = new PublicKey('KeccakSecp256k11111111111111111111111111111'); var _class2; /** * Address of the stake config account which configures the rate * of stake warmup and cooldown as well as the slashing penalty. */ const STAKE_CONFIG_ID = new PublicKey('StakeConfig11111111111111111111111111111111'); /** * Stake account authority info */ class Authorized { /** * Create a new Authorized object * @param staker the stake authority * @param withdrawer the withdraw authority */ constructor(staker, withdrawer) { /** stake authority */ this.staker = void 0; /** withdraw authority */ this.withdrawer = void 0; this.staker = staker; this.withdrawer = withdrawer; } } /** * Stake account lockup info */ class Lockup { /** * Create a new Lockup object */ constructor(unixTimestamp, epoch, custodian) { /** Unix timestamp of lockup expiration */ this.unixTimestamp = void 0; /** Epoch of lockup expiration */ this.epoch = void 0; /** Lockup custodian authority */ this.custodian = void 0; this.unixTimestamp = unixTimestamp; this.epoch = epoch; this.custodian = custodian; } /** * Default, inactive Lockup value */ } _class2 = Lockup; Lockup.default = new _class2(0, 0, PublicKey.default); /** * Create stake account transaction params */ /** * Create stake account with seed transaction params */ /** * Initialize stake instruction params */ /** * Delegate stake instruction params */ /** * Authorize stake instruction params */ /** * Authorize stake instruction params using a derived key */ /** * Split stake instruction params */ /** * Split with seed transaction params */ /** * Withdraw stake instruction params */ /** * Deactivate stake instruction params */ /** * Merge stake instruction params */ /** * Stake Instruction class */ class StakeInstruction { /** * @internal */ constructor() {} /** * Decode a stake instruction and retrieve the instruction type. */ static decodeInstructionType(instruction) { this.checkProgramId(instruction.programId); const instructionTypeLayout = u32('instruction'); const typeIndex = instructionTypeLayout.decode(instruction.data); let type; for (const [ixType, layout] of Object.entries(STAKE_INSTRUCTION_LAYOUTS)) { if (layout.index == typeIndex) { type = ixType; break; } } if (!type) { throw new Error('Instruction type incorrect; not a StakeInstruction'); } return type; } /** * Decode a initialize stake instruction and retrieve the instruction params. */ static decodeInitialize(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { authorized, lockup } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Initialize, instruction.data); return { stakePubkey: instruction.keys[0].pubkey, authorized: new Authorized(new PublicKey(authorized.staker), new PublicKey(authorized.withdrawer)), lockup: new Lockup(lockup.unixTimestamp, lockup.epoch, new PublicKey(lockup.custodian)) }; } /** * Decode a delegate stake instruction and retrieve the instruction params. */ static decodeDelegate(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 6); decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Delegate, instruction.data); return { stakePubkey: instruction.keys[0].pubkey, votePubkey: instruction.keys[1].pubkey, authorizedPubkey: instruction.keys[5].pubkey }; } /** * Decode an authorize stake instruction and retrieve the instruction params. */ static decodeAuthorize(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { newAuthorized, stakeAuthorizationType } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Authorize, instruction.data); const o = { stakePubkey: instruction.keys[0].pubkey, authorizedPubkey: instruction.keys[2].pubkey, newAuthorizedPubkey: new PublicKey(newAuthorized), stakeAuthorizationType: { index: stakeAuthorizationType } }; if (instruction.keys.length > 3) { o.custodianPubkey = instruction.keys[3].pubkey; } return o; } /** * Decode an authorize-with-seed stake instruction and retrieve the instruction params. */ static decodeAuthorizeWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 2); const { newAuthorized, stakeAuthorizationType, authoritySeed, authorityOwner } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed, instruction.data); const o = { stakePubkey: instruction.keys[0].pubkey, authorityBase: instruction.keys[1].pubkey, authoritySeed: authoritySeed, authorityOwner: new PublicKey(authorityOwner), newAuthorizedPubkey: new PublicKey(newAuthorized), stakeAuthorizationType: { index: stakeAuthorizationType } }; if (instruction.keys.length > 3) { o.custodianPubkey = instruction.keys[3].pubkey; } return o; } /** * Decode a split stake instruction and retrieve the instruction params. */ static decodeSplit(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { lamports } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Split, instruction.data); return { stakePubkey: instruction.keys[0].pubkey, splitStakePubkey: instruction.keys[1].pubkey, authorizedPubkey: instruction.keys[2].pubkey, lamports }; } /** * Decode a merge stake instruction and retrieve the instruction params. */ static decodeMerge(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Merge, instruction.data); return { stakePubkey: instruction.keys[0].pubkey, sourceStakePubKey: instruction.keys[1].pubkey, authorizedPubkey: instruction.keys[4].pubkey }; } /** * Decode a withdraw stake instruction and retrieve the instruction params. */ static decodeWithdraw(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 5); const { lamports } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Withdraw, instruction.data); const o = { stakePubkey: instruction.keys[0].pubkey, toPubkey: instruction.keys[1].pubkey, authorizedPubkey: instruction.keys[4].pubkey, lamports }; if (instruction.keys.length > 5) { o.custodianPubkey = instruction.keys[5].pubkey; } return o; } /** * Decode a deactivate stake instruction and retrieve the instruction params. */ static decodeDeactivate(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Deactivate, instruction.data); return { stakePubkey: instruction.keys[0].pubkey, authorizedPubkey: instruction.keys[2].pubkey }; } /** * @internal */ static checkProgramId(programId) { if (!programId.equals(StakeProgram.programId)) { throw new Error('invalid instruction; programId is not StakeProgram'); } } /** * @internal */ static checkKeyLength(keys, expectedLength) { if (keys.length < expectedLength) { throw new Error(`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`); } } } /** * An enumeration of valid StakeInstructionType's */ /** * An enumeration of valid stake InstructionType's * @internal */ const STAKE_INSTRUCTION_LAYOUTS = Object.freeze({ Initialize: { index: 0, layout: struct([u32('instruction'), authorized(), lockup()]) }, Authorize: { index: 1, layout: struct([u32('instruction'), publicKey('newAuthorized'), u32('stakeAuthorizationType')]) }, Delegate: { index: 2, layout: struct([u32('instruction')]) }, Split: { index: 3, layout: struct([u32('instruction'), ns64('lamports')]) }, Withdraw: { index: 4, layout: struct([u32('instruction'), ns64('lamports')]) }, Deactivate: { index: 5, layout: struct([u32('instruction')]) }, Merge: { index: 7, layout: struct([u32('instruction')]) }, AuthorizeWithSeed: { index: 8, layout: struct([u32('instruction'), publicKey('newAuthorized'), u32('stakeAuthorizationType'), rustString('authoritySeed'), publicKey('authorityOwner')]) } }); /** * Stake authorization type */ /** * An enumeration of valid StakeAuthorizationLayout's */ const StakeAuthorizationLayout = Object.freeze({ Staker: { index: 0 }, Withdrawer: { index: 1 } }); /** * Factory class for transactions to interact with the Stake program */ class StakeProgram { /** * @internal */ constructor() {} /** * Public key that identifies the Stake program */ /** * Generate an Initialize instruction to add to a Stake Create transaction */ static initialize(params) { const { stakePubkey, authorized, lockup: maybeLockup } = params; const lockup = maybeLockup || Lockup.default; const type = STAKE_INSTRUCTION_LAYOUTS.Initialize; const data = encodeData(type, { authorized: { staker: toBuffer(authorized.staker.toBuffer()), withdrawer: toBuffer(authorized.withdrawer.toBuffer()) }, lockup: { unixTimestamp: lockup.unixTimestamp, epoch: lockup.epoch, custodian: toBuffer(lockup.custodian.toBuffer()) } }); const instructionData = { keys: [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }], programId: this.programId, data }; return new TransactionInstruction(instructionData); } /** * Generate a Transaction that creates a new Stake account at * an address generated with `from`, a seed, and the Stake programId */ static createAccountWithSeed(params) { const transaction = new Transaction(); transaction.add(SystemProgram.createAccountWithSeed({ fromPubkey: params.fromPubkey, newAccountPubkey: params.stakePubkey, basePubkey: params.basePubkey, seed: params.seed, lamports: params.lamports, space: this.space, programId: this.programId })); const { stakePubkey, authorized, lockup } = params; return transaction.add(this.initialize({ stakePubkey, authorized, lockup })); } /** * Generate a Transaction that creates a new Stake account */ static createAccount(params) { const transaction = new Transaction(); transaction.add(SystemProgram.createAccount({ fromPubkey: params.fromPubkey, newAccountPubkey: params.stakePubkey, lamports: params.lamports, space: this.space, programId: this.programId })); const { stakePubkey, authorized, lockup } = params; return transaction.add(this.initialize({ stakePubkey, authorized, lockup })); } /** * Generate a Transaction that delegates Stake tokens to a validator * Vote PublicKey. This transaction can also be used to redelegate Stake * to a new validator Vote PublicKey. */ static delegate(params) { const { stakePubkey, authorizedPubkey, votePubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Delegate; const data = encodeData(type); return new Transaction().add({ keys: [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: votePubkey, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false }, { pubkey: STAKE_CONFIG_ID, isSigner: false, isWritable: false }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } /** * Generate a Transaction that authorizes a new PublicKey as Staker * or Withdrawer on the Stake account. */ static authorize(params) { const { stakePubkey, authorizedPubkey, newAuthorizedPubkey, stakeAuthorizationType, custodianPubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Authorize; const data = encodeData(type, { newAuthorized: toBuffer(newAuthorizedPubkey.toBuffer()), stakeAuthorizationType: stakeAuthorizationType.index }); const keys = [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: true }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }]; if (custodianPubkey) { keys.push({ pubkey: custodianPubkey, isSigner: true, isWritable: false }); } return new Transaction().add({ keys, programId: this.programId, data }); } /** * Generate a Transaction that authorizes a new PublicKey as Staker * or Withdrawer on the Stake account. */ static authorizeWithSeed(params) { const { stakePubkey, authorityBase, authoritySeed, authorityOwner, newAuthorizedPubkey, stakeAuthorizationType, custodianPubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed; const data = encodeData(type, { newAuthorized: toBuffer(newAuthorizedPubkey.toBuffer()), stakeAuthorizationType: stakeAuthorizationType.index, authoritySeed: authoritySeed, authorityOwner: toBuffer(authorityOwner.toBuffer()) }); const keys = [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: authorityBase, isSigner: true, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }]; if (custodianPubkey) { keys.push({ pubkey: custodianPubkey, isSigner: true, isWritable: false }); } return new Transaction().add({ keys, programId: this.programId, data }); } /** * @internal */ static splitInstruction(params) { const { stakePubkey, authorizedPubkey, splitStakePubkey, lamports } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Split; const data = encodeData(type, { lamports }); return new TransactionInstruction({ keys: [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: splitStakePubkey, isSigner: false, isWritable: true }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } /** * Generate a Transaction that splits Stake tokens into another stake account */ static split(params, // Compute the cost of allocating the new stake account in lamports rentExemptReserve) { const transaction = new Transaction(); transaction.add(SystemProgram.createAccount({ fromPubkey: params.authorizedPubkey, newAccountPubkey: params.splitStakePubkey, lamports: rentExemptReserve, space: this.space, programId: this.programId })); return transaction.add(this.splitInstruction(params)); } /** * Generate a Transaction that splits Stake tokens into another account * derived from a base public key and seed */ static splitWithSeed(params, // If this stake account is new, compute the cost of allocating it in lamports rentExemptReserve) { const { stakePubkey, authorizedPubkey, splitStakePubkey, basePubkey, seed, lamports } = params; const transaction = new Transaction(); transaction.add(SystemProgram.allocate({ accountPubkey: splitStakePubkey, basePubkey, seed, space: this.space, programId: this.programId })); if (rentExemptReserve && rentExemptReserve > 0) { transaction.add(SystemProgram.transfer({ fromPubkey: params.authorizedPubkey, toPubkey: splitStakePubkey, lamports: rentExemptReserve })); } return transaction.add(this.splitInstruction({ stakePubkey, authorizedPubkey, splitStakePubkey, lamports })); } /** * Generate a Transaction that merges Stake accounts. */ static merge(params) { const { stakePubkey, sourceStakePubKey, authorizedPubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Merge; const data = encodeData(type); return new Transaction().add({ keys: [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: sourceStakePubKey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } /** * Generate a Transaction that withdraws deactivated Stake tokens. */ static withdraw(params) { const { stakePubkey, authorizedPubkey, toPubkey, lamports, custodianPubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Withdraw; const data = encodeData(type, { lamports }); const keys = [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: toPubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }]; if (custodianPubkey) { keys.push({ pubkey: custodianPubkey, isSigner: true, isWritable: false }); } return new Transaction().add({ keys, programId: this.programId, data }); } /** * Generate a Transaction that deactivates Stake tokens. */ static deactivate(params) { const { stakePubkey, authorizedPubkey } = params; const type = STAKE_INSTRUCTION_LAYOUTS.Deactivate; const data = encodeData(type); return new Transaction().add({ keys: [{ pubkey: stakePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }], programId: this.programId, data }); } } StakeProgram.programId = new PublicKey('Stake11111111111111111111111111111111111111'); /** * Max space of a Stake account * * This is generated from the solana-stake-program StakeState struct as * `StakeStateV2::size_of()`: * https://docs.rs/solana-stake-program/latest/solana_stake_program/stake_state/enum.StakeStateV2.html */ StakeProgram.space = 200; /** * Vote account info */ class VoteInit { /** [0, 100] */ constructor(nodePubkey, authorizedVoter, authorizedWithdrawer, commission) { this.nodePubkey = void 0; this.authorizedVoter = void 0; this.authorizedWithdrawer = void 0; this.commission = void 0; this.nodePubkey = nodePubkey; this.authorizedVoter = authorizedVoter; this.authorizedWithdrawer = authorizedWithdrawer; this.commission = commission; } } /** * Create vote account transaction params */ /** * InitializeAccount instruction params */ /** * Authorize instruction params */ /** * AuthorizeWithSeed instruction params */ /** * Withdraw from vote account transaction params */ /** * Update validator identity (node pubkey) vote account instruction params. */ /** * Vote Instruction class */ class VoteInstruction { /** * @internal */ constructor() {} /** * Decode a vote instruction and retrieve the instruction type. */ static decodeInstructionType(instruction) { this.checkProgramId(instruction.programId); const instructionTypeLayout = u32('instruction'); const typeIndex = instructionTypeLayout.decode(instruction.data); let type; for (const [ixType, layout] of Object.entries(VOTE_INSTRUCTION_LAYOUTS)) { if (layout.index == typeIndex) { type = ixType; break; } } if (!type) { throw new Error('Instruction type incorrect; not a VoteInstruction'); } return type; } /** * Decode an initialize vote instruction and retrieve the instruction params. */ static decodeInitializeAccount(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 4); const { voteInit } = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.InitializeAccount, instruction.data); return { votePubkey: instruction.keys[0].pubkey, nodePubkey: instruction.keys[3].pubkey, voteInit: new VoteInit(new PublicKey(voteInit.nodePubkey), new PublicKey(voteInit.authorizedVoter), new PublicKey(voteInit.authorizedWithdrawer), voteInit.commission) }; } /** * Decode an authorize instruction and retrieve the instruction params. */ static decodeAuthorize(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { newAuthorized, voteAuthorizationType } = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.Authorize, instruction.data); return { votePubkey: instruction.keys[0].pubkey, authorizedPubkey: instruction.keys[2].pubkey, newAuthorizedPubkey: new PublicKey(newAuthorized), voteAuthorizationType: { index: voteAuthorizationType } }; } /** * Decode an authorize instruction and retrieve the instruction params. */ static decodeAuthorizeWithSeed(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { voteAuthorizeWithSeedArgs: { currentAuthorityDerivedKeyOwnerPubkey, currentAuthorityDerivedKeySeed, newAuthorized, voteAuthorizationType } } = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed, instruction.data); return { currentAuthorityDerivedKeyBasePubkey: instruction.keys[2].pubkey, currentAuthorityDerivedKeyOwnerPubkey: new PublicKey(currentAuthorityDerivedKeyOwnerPubkey), currentAuthorityDerivedKeySeed: currentAuthorityDerivedKeySeed, newAuthorizedPubkey: new PublicKey(newAuthorized), voteAuthorizationType: { index: voteAuthorizationType }, votePubkey: instruction.keys[0].pubkey }; } /** * Decode a withdraw instruction and retrieve the instruction params. */ static decodeWithdraw(instruction) { this.checkProgramId(instruction.programId); this.checkKeyLength(instruction.keys, 3); const { lamports } = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.Withdraw, instruction.data); return { votePubkey: instruction.keys[0].pubkey, authorizedWithdrawerPubkey: instruction.keys[2].pubkey, lamports, toPubkey: instruction.keys[1].pubkey }; } /** * @internal */ static checkProgramId(programId) { if (!programId.equals(VoteProgram.programId)) { throw new Error('invalid instruction; programId is not VoteProgram'); } } /** * @internal */ static checkKeyLength(keys, expectedLength) { if (keys.length < expectedLength) { throw new Error(`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`); } } } /** * An enumeration of valid VoteInstructionType's */ /** @internal */ const VOTE_INSTRUCTION_LAYOUTS = Object.freeze({ InitializeAccount: { index: 0, layout: struct([u32('instruction'), voteInit()]) }, Authorize: { index: 1, layout: struct([u32('instruction'), publicKey('newAuthorized'), u32('voteAuthorizationType')]) }, Withdraw: { index: 3, layout: struct([u32('instruction'), ns64('lamports')]) }, UpdateValidatorIdentity: { index: 4, layout: struct([u32('instruction')]) }, AuthorizeWithSeed: { index: 10, layout: struct([u32('instruction'), voteAuthorizeWithSeedArgs()]) } }); /** * VoteAuthorize type */ /** * An enumeration of valid VoteAuthorization layouts. */ const VoteAuthorizationLayout = Object.freeze({ Voter: { index: 0 }, Withdrawer: { index: 1 } }); /** * Factory class for transactions to interact with the Vote program */ class VoteProgram { /** * @internal */ constructor() {} /** * Public key that identifies the Vote program */ /** * Generate an Initialize instruction. */ static initializeAccount(params) { const { votePubkey, nodePubkey, voteInit } = params; const type = VOTE_INSTRUCTION_LAYOUTS.InitializeAccount; const data = encodeData(type, { voteInit: { nodePubkey: toBuffer(voteInit.nodePubkey.toBuffer()), authorizedVoter: toBuffer(voteInit.authorizedVoter.toBuffer()), authorizedWithdrawer: toBuffer(voteInit.authorizedWithdrawer.toBuffer()), commission: voteInit.commission } }); const instructionData = { keys: [{ pubkey: votePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: nodePubkey, isSigner: true, isWritable: false }], programId: this.programId, data }; return new TransactionInstruction(instructionData); } /** * Generate a transaction that creates a new Vote account. */ static createAccount(params) { const transaction = new Transaction(); transaction.add(SystemProgram.createAccount({ fromPubkey: params.fromPubkey, newAccountPubkey: params.votePubkey, lamports: params.lamports, space: this.space, programId: this.programId })); return transaction.add(this.initializeAccount({ votePubkey: params.votePubkey, nodePubkey: params.voteInit.nodePubkey, voteInit: params.voteInit })); } /** * Generate a transaction that authorizes a new Voter or Withdrawer on the Vote account. */ static authorize(params) { const { votePubkey, authorizedPubkey, newAuthorizedPubkey, voteAuthorizationType } = params; const type = VOTE_INSTRUCTION_LAYOUTS.Authorize; const data = encodeData(type, { newAuthorized: toBuffer(newAuthorizedPubkey.toBuffer()), voteAuthorizationType: voteAuthorizationType.index }); const keys = [{ pubkey: votePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: authorizedPubkey, isSigner: true, isWritable: false }]; return new Transaction().add({ keys, programId: this.programId, data }); } /** * Generate a transaction that authorizes a new Voter or Withdrawer on the Vote account * where the current Voter or Withdrawer authority is a derived key. */ static authorizeWithSeed(params) { const { currentAuthorityDerivedKeyBasePubkey, currentAuthorityDerivedKeyOwnerPubkey, currentAuthorityDerivedKeySeed, newAuthorizedPubkey, voteAuthorizationType, votePubkey } = params; const type = VOTE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed; const data = encodeData(type, { voteAuthorizeWithSeedArgs: { currentAuthorityDerivedKeyOwnerPubkey: toBuffer(currentAuthorityDerivedKeyOwnerPubkey.toBuffer()), currentAuthorityDerivedKeySeed: currentAuthorityDerivedKeySeed, newAuthorized: toBuffer(newAuthorizedPubkey.toBuffer()), voteAuthorizationType: voteAuthorizationType.index } }); const keys = [{ pubkey: votePubkey, isSigner: false, isWritable: true }, { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, { pubkey: currentAuthorityDerivedKeyBasePubkey, isSigner: true, isWritable: false }]; return new Transaction().add({ keys, programId: this.programId, data }); } /** * Generate a transaction to withdraw from a Vote account. */ static withdraw(params) { const { votePubkey, authorizedWithdrawerPubkey, lamports, toPubkey } = params; const type = VOTE_INSTRUCTION_LAYOUTS.Withdraw; const data = encodeData(type, { lamports }); const keys = [{ pubkey: votePubkey, isSigner: false, isWritable: true }, { pubkey: toPubkey, isSigner: false, isWritable: true }, { pubkey: authorizedWithdrawerPubkey, isSigner: true, isWritable: false }]; return new Transaction().add({ keys, programId: this.programId, data }); } /** * Generate a transaction to withdraw safely from a Vote account. * * This function was created as a safeguard for vote accounts running validators, `safeWithdraw` * checks that the withdraw amount will not exceed the specified balance while leaving enough left * to cover rent. If you wish to close the vote account by withdrawing the full amount, call the * `withdraw` method directly. */ static safeWithdraw(params, currentVoteAccountBalance, rentExemptMinimum) { if (params.lamports > currentVoteAccountBalance - rentExemptMinimum) { throw new Error('Withdraw will leave vote account with insufficient funds.'); } return VoteProgram.withdraw(params); } /** * Generate a transaction to update the validator identity (node pubkey) of a Vote account. */ static updateValidatorIdentity(params) { const { votePubkey, authorizedWithdrawerPubkey, nodePubkey } = params; const type = VOTE_INSTRUCTION_LAYOUTS.UpdateValidatorIdentity; const data = encodeData(type); const keys = [{ pubkey: votePubkey, isSigner: false, isWritable: true }, { pubkey: nodePubkey, isSigner: true, isWritable: false }, { pubkey: authorizedWithdrawerPubkey, isSigner: true, isWritable: false }]; return new Transaction().add({ keys, programId: this.programId, data }); } } VoteProgram.programId = new PublicKey('Vote111111111111111111111111111111111111111'); /** * Max space of a Vote account * * This is generated from the solana-vote-program VoteState struct as * `VoteState::size_of()`: * https://docs.rs/solana-vote-program/1.9.5/solana_vote_program/vote_state/struct.VoteState.html#method.size_of * * KEEP IN SYNC WITH `VoteState::size_of()` in https://github.com/solana-labs/solana/blob/a474cb24b9238f5edcc982f65c0b37d4a1046f7e/sdk/program/src/vote/state/mod.rs#L340-L342 */ VoteProgram.space = 3762; const VALIDATOR_INFO_KEY = new PublicKey('Va1idator1nfo111111111111111111111111111111'); /** * @internal */ /** * Info used to identity validators. */ const InfoString = type({ name: string(), website: optional(string()), details: optional(string()), keybaseUsername: optional(string()) }); /** * ValidatorInfo class */ class ValidatorInfo { /** * Construct a valid ValidatorInfo * * @param key validator public key * @param info validator information */ constructor(key, info) { /** * validator public key */ this.key = void 0; /** * validator information */ this.info = void 0; this.key = key; this.info = info; } /** * Deserialize ValidatorInfo from the config account data. Exactly two config * keys are required in the data. * * @param buffer config account data * @return null if info was not found */ static fromConfigData(buffer$1) { let byteArray = [...buffer$1]; const configKeyCount = decodeLength(byteArray); if (configKeyCount !== 2) return null; const configKeys = []; for (let i = 0; i < 2; i++) { const publicKey = new PublicKey(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH)); const isSigner = guardedShift(byteArray) === 1; configKeys.push({ publicKey, isSigner }); } if (configKeys[0].publicKey.equals(VALIDATOR_INFO_KEY)) { if (configKeys[1].isSigner) { const rawInfo = rustString().decode(buffer.Buffer.from(byteArray)); const info = JSON.parse(rawInfo); assert(info, InfoString); return new ValidatorInfo(configKeys[1].publicKey, info); } } return null; } } const VOTE_PROGRAM_ID = new PublicKey('Vote111111111111111111111111111111111111111'); /** * History of how many credits earned by the end of each epoch */ /** * See https://github.com/solana-labs/solana/blob/8a12ed029cfa38d4a45400916c2463fb82bbec8c/programs/vote_api/src/vote_state.rs#L68-L88 * * @internal */ const VoteAccountLayout = struct([publicKey('nodePubkey'), publicKey('authorizedWithdrawer'), u8('commission'), nu64(), // votes.length seq(struct([nu64('slot'), u32('confirmationCount')]), offset(u32(), -8), 'votes'), u8('rootSlotValid'), nu64('rootSlot'), nu64(), // authorizedVoters.length seq(struct([nu64('epoch'), publicKey('authorizedVoter')]), offset(u32(), -8), 'authorizedVoters'), struct([seq(struct([publicKey('authorizedPubkey'), nu64('epochOfLastAuthorizedSwitch'), nu64('targetEpoch')]), 32, 'buf'), nu64('idx'), u8('isEmpty')], 'priorVoters'), nu64(), // epochCredits.length seq(struct([nu64('epoch'), nu64('credits'), nu64('prevCredits')]), offset(u32(), -8), 'epochCredits'), struct([nu64('slot'), nu64('timestamp')], 'lastTimestamp')]); /** * VoteAccount class */ class VoteAccount { /** * @internal */ constructor(args) { this.nodePubkey = void 0; this.authorizedWithdrawer = void 0; this.commission = void 0; this.rootSlot = void 0; this.votes = void 0; this.authorizedVoters = void 0; this.priorVoters = void 0; this.epochCredits = void 0; this.lastTimestamp = void 0; this.nodePubkey = args.nodePubkey; this.authorizedWithdrawer = args.authorizedWithdrawer; this.commission = args.commission; this.rootSlot = args.rootSlot; this.votes = args.votes; this.authorizedVoters = args.authorizedVoters; this.priorVoters = args.priorVoters; this.epochCredits = args.epochCredits; this.lastTimestamp = args.lastTimestamp; } /** * Deserialize VoteAccount from the account data. * * @param buffer account data * @return VoteAccount */ static fromAccountData(buffer) { const versionOffset = 4; const va = VoteAccountLayout.decode(toBuffer(buffer), versionOffset); let rootSlot = va.rootSlot; if (!va.rootSlotValid) { rootSlot = null; } return new VoteAccount({ nodePubkey: new PublicKey(va.nodePubkey), authorizedWithdrawer: new PublicKey(va.authorizedWithdrawer), commission: va.commission, votes: va.votes, rootSlot, authorizedVoters: va.authorizedVoters.map(parseAuthorizedVoter), priorVoters: getPriorVoters(va.priorVoters), epochCredits: va.epochCredits, lastTimestamp: va.lastTimestamp }); } } function parseAuthorizedVoter({ authorizedVoter, epoch }) { return { epoch, authorizedVoter: new PublicKey(authorizedVoter) }; } function parsePriorVoters({ authorizedPubkey, epochOfLastAuthorizedSwitch, targetEpoch }) { return { authorizedPubkey: new PublicKey(authorizedPubkey), epochOfLastAuthorizedSwitch, targetEpoch }; } function getPriorVoters({ buf, idx, isEmpty }) { if (isEmpty) { return []; } return [...buf.slice(idx + 1).map(parsePriorVoters), ...buf.slice(0, idx).map(parsePriorVoters)]; } const endpoint = { http: { devnet: 'http://api.devnet.solana.com', testnet: 'http://api.testnet.solana.com', 'mainnet-beta': 'http://api.mainnet-beta.solana.com/' }, https: { devnet: 'https://api.devnet.solana.com', testnet: 'https://api.testnet.solana.com', 'mainnet-beta': 'https://api.mainnet-beta.solana.com/' } }; /** * Retrieves the RPC API URL for the specified cluster * @param {Cluster} [cluster="devnet"] - The cluster name of the RPC API URL to use. Possible options: 'devnet' | 'testnet' | 'mainnet-beta' * @param {boolean} [tls="http"] - Use TLS when connecting to cluster. * * @returns {string} URL string of the RPC endpoint */ function clusterApiUrl(cluster, tls) { const key = tls === false ? 'http' : 'https'; if (!cluster) { return endpoint[key]['devnet']; } const url = endpoint[key][cluster]; if (!url) { throw new Error(`Unknown ${key} cluster: ${cluster}`); } return url; } /** * Send and confirm a raw transaction * * If `commitment` option is not specified, defaults to 'max' commitment. * * @param {Connection} connection * @param {Buffer} rawTransaction * @param {TransactionConfirmationStrategy} confirmationStrategy * @param {ConfirmOptions} [options] * @returns {Promise} */ /** * @deprecated Calling `sendAndConfirmRawTransaction()` without a `confirmationStrategy` * is no longer supported and will be removed in a future version. */ // eslint-disable-next-line no-redeclare // eslint-disable-next-line no-redeclare async function sendAndConfirmRawTransaction(connection, rawTransaction, confirmationStrategyOrConfirmOptions, maybeConfirmOptions) { let confirmationStrategy; let options; if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'lastValidBlockHeight')) { confirmationStrategy = confirmationStrategyOrConfirmOptions; options = maybeConfirmOptions; } else if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'nonceValue')) { confirmationStrategy = confirmationStrategyOrConfirmOptions; options = maybeConfirmOptions; } else { options = confirmationStrategyOrConfirmOptions; } const sendOptions = options && { skipPreflight: options.skipPreflight, preflightCommitment: options.preflightCommitment || options.commitment, minContextSlot: options.minContextSlot }; const signature = await connection.sendRawTransaction(rawTransaction, sendOptions); const commitment = options && options.commitment; const confirmationPromise = confirmationStrategy ? connection.confirmTransaction(confirmationStrategy, commitment) : connection.confirmTransaction(signature, commitment); const status = (await confirmationPromise).value; if (status.err) { throw new Error(`Raw transaction ${signature} failed (${JSON.stringify(status)})`); } return signature; } /** * There are 1-billion lamports in one SOL */ const LAMPORTS_PER_SOL = 1000000000; exports.Account = Account; exports.AddressLookupTableAccount = AddressLookupTableAccount; exports.AddressLookupTableInstruction = AddressLookupTableInstruction; exports.AddressLookupTableProgram = AddressLookupTableProgram; exports.Authorized = Authorized; exports.BLOCKHASH_CACHE_TIMEOUT_MS = BLOCKHASH_CACHE_TIMEOUT_MS; exports.BPF_LOADER_DEPRECATED_PROGRAM_ID = BPF_LOADER_DEPRECATED_PROGRAM_ID; exports.BPF_LOADER_PROGRAM_ID = BPF_LOADER_PROGRAM_ID; exports.BpfLoader = BpfLoader; exports.COMPUTE_BUDGET_INSTRUCTION_LAYOUTS = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS; exports.ComputeBudgetInstruction = ComputeBudgetInstruction; exports.ComputeBudgetProgram = ComputeBudgetProgram; exports.Connection = Connection; exports.Ed25519Program = Ed25519Program; exports.Enum = Enum; exports.EpochSchedule = EpochSchedule; exports.FeeCalculatorLayout = FeeCalculatorLayout; exports.Keypair = Keypair; exports.LAMPORTS_PER_SOL = LAMPORTS_PER_SOL; exports.LOOKUP_TABLE_INSTRUCTION_LAYOUTS = LOOKUP_TABLE_INSTRUCTION_LAYOUTS; exports.Loader = Loader; exports.Lockup = Lockup; exports.MAX_SEED_LENGTH = MAX_SEED_LENGTH; exports.Message = Message; exports.MessageAccountKeys = MessageAccountKeys; exports.MessageV0 = MessageV0; exports.NONCE_ACCOUNT_LENGTH = NONCE_ACCOUNT_LENGTH; exports.NonceAccount = NonceAccount; exports.PACKET_DATA_SIZE = PACKET_DATA_SIZE; exports.PUBLIC_KEY_LENGTH = PUBLIC_KEY_LENGTH; exports.PublicKey = PublicKey; exports.SIGNATURE_LENGTH_IN_BYTES = SIGNATURE_LENGTH_IN_BYTES; exports.SOLANA_SCHEMA = SOLANA_SCHEMA; exports.STAKE_CONFIG_ID = STAKE_CONFIG_ID; exports.STAKE_INSTRUCTION_LAYOUTS = STAKE_INSTRUCTION_LAYOUTS; exports.SYSTEM_INSTRUCTION_LAYOUTS = SYSTEM_INSTRUCTION_LAYOUTS; exports.SYSVAR_CLOCK_PUBKEY = SYSVAR_CLOCK_PUBKEY; exports.SYSVAR_EPOCH_SCHEDULE_PUBKEY = SYSVAR_EPOCH_SCHEDULE_PUBKEY; exports.SYSVAR_INSTRUCTIONS_PUBKEY = SYSVAR_INSTRUCTIONS_PUBKEY; exports.SYSVAR_RECENT_BLOCKHASHES_PUBKEY = SYSVAR_RECENT_BLOCKHASHES_PUBKEY; exports.SYSVAR_RENT_PUBKEY = SYSVAR_RENT_PUBKEY; exports.SYSVAR_REWARDS_PUBKEY = SYSVAR_REWARDS_PUBKEY; exports.SYSVAR_SLOT_HASHES_PUBKEY = SYSVAR_SLOT_HASHES_PUBKEY; exports.SYSVAR_SLOT_HISTORY_PUBKEY = SYSVAR_SLOT_HISTORY_PUBKEY; exports.SYSVAR_STAKE_HISTORY_PUBKEY = SYSVAR_STAKE_HISTORY_PUBKEY; exports.Secp256k1Program = Secp256k1Program; exports.SendTransactionError = SendTransactionError; exports.SolanaJSONRPCError = SolanaJSONRPCError; exports.SolanaJSONRPCErrorCode = SolanaJSONRPCErrorCode; exports.StakeAuthorizationLayout = StakeAuthorizationLayout; exports.StakeInstruction = StakeInstruction; exports.StakeProgram = StakeProgram; exports.Struct = Struct$1; exports.SystemInstruction = SystemInstruction; exports.SystemProgram = SystemProgram; exports.Transaction = Transaction; exports.TransactionExpiredBlockheightExceededError = TransactionExpiredBlockheightExceededError; exports.TransactionExpiredNonceInvalidError = TransactionExpiredNonceInvalidError; exports.TransactionExpiredTimeoutError = TransactionExpiredTimeoutError; exports.TransactionInstruction = TransactionInstruction; exports.TransactionMessage = TransactionMessage; exports.TransactionStatus = TransactionStatus; exports.VALIDATOR_INFO_KEY = VALIDATOR_INFO_KEY; exports.VERSION_PREFIX_MASK = VERSION_PREFIX_MASK; exports.VOTE_PROGRAM_ID = VOTE_PROGRAM_ID; exports.ValidatorInfo = ValidatorInfo; exports.VersionedMessage = VersionedMessage; exports.VersionedTransaction = VersionedTransaction; exports.VoteAccount = VoteAccount; exports.VoteAuthorizationLayout = VoteAuthorizationLayout; exports.VoteInit = VoteInit; exports.VoteInstruction = VoteInstruction; exports.VoteProgram = VoteProgram; exports.clusterApiUrl = clusterApiUrl; exports.sendAndConfirmRawTransaction = sendAndConfirmRawTransaction; exports.sendAndConfirmTransaction = sendAndConfirmTransaction; return exports; })({}); //# sourceMappingURL=index.iife.js.map