UNPKG

@web3-onboard/core

Version:

Web3-Onboard makes it simple to connect Ethereum hardware and software wallets to your dapp. Features standardized spec compliant web3 providers for all supported wallets, framework agnostic modern javascript UI with code splitting, CSS customization, mul

1,539 lines (1,508 loc) 60.5 kB
const version = '2.12.0'; const getContractAddress = (address) => address; const getUrl = (url) => url; const getVersion = () => `viem@${version}`; class BaseError extends Error { constructor(shortMessage, args = {}) { super(); Object.defineProperty(this, "details", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "docsPath", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "metaMessages", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "shortMessage", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'ViemError' }); Object.defineProperty(this, "version", { enumerable: true, configurable: true, writable: true, value: getVersion() }); const details = args.cause instanceof BaseError ? args.cause.details : args.cause?.message ? args.cause.message : args.details; const docsPath = args.cause instanceof BaseError ? args.cause.docsPath || args.docsPath : args.docsPath; this.message = [ shortMessage || 'An error occurred.', '', ...(args.metaMessages ? [...args.metaMessages, ''] : []), ...(docsPath ? [ `Docs: https://viem.sh${docsPath}${args.docsSlug ? `#${args.docsSlug}` : ''}`, ] : []), ...(details ? [`Details: ${details}`] : []), `Version: ${this.version}`, ].join('\n'); if (args.cause) this.cause = args.cause; this.details = details; this.docsPath = docsPath; this.metaMessages = args.metaMessages; this.shortMessage = shortMessage; } walk(fn) { return walk(this, fn); } } function walk(err, fn) { if (fn?.(err)) return err; if (err && typeof err === 'object' && 'cause' in err) return walk(err.cause, fn); return fn ? null : err; } class IntegerOutOfRangeError extends BaseError { constructor({ max, min, signed, size, value, }) { super(`Number "${value}" is not in safe ${size ? `${size * 8}-bit ${signed ? 'signed' : 'unsigned'} ` : ''}integer range ${max ? `(${min} to ${max})` : `(above ${min})`}`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'IntegerOutOfRangeError' }); } } class InvalidBytesBooleanError extends BaseError { constructor(bytes) { super(`Bytes value "${bytes}" is not a valid boolean. The bytes array must contain a single byte of either a 0 or 1 value.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidBytesBooleanError' }); } } class SizeOverflowError extends BaseError { constructor({ givenSize, maxSize }) { super(`Size cannot exceed ${maxSize} bytes. Given size: ${givenSize} bytes.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'SizeOverflowError' }); } } function isHex(value, { strict = true } = {}) { if (!value) return false; if (typeof value !== 'string') return false; return strict ? /^0x[0-9a-fA-F]*$/.test(value) : value.startsWith('0x'); } /** * @description Retrieves the size of the value (in bytes). * * @param value The value (hex or byte array) to retrieve the size of. * @returns The size of the value (in bytes). */ function size(value) { if (isHex(value, { strict: false })) return Math.ceil((value.length - 2) / 2); return value.length; } function trim(hexOrBytes, { dir = 'left' } = {}) { let data = typeof hexOrBytes === 'string' ? hexOrBytes.replace('0x', '') : hexOrBytes; let sliceLength = 0; for (let i = 0; i < data.length - 1; i++) { if (data[dir === 'left' ? i : data.length - i - 1].toString() === '0') sliceLength++; else break; } data = dir === 'left' ? data.slice(sliceLength) : data.slice(0, data.length - sliceLength); if (typeof hexOrBytes === 'string') { if (data.length === 1 && dir === 'right') data = `${data}0`; return `0x${data.length % 2 === 1 ? `0${data}` : data}`; } return data; } class SliceOffsetOutOfBoundsError extends BaseError { constructor({ offset, position, size, }) { super(`Slice ${position === 'start' ? 'starting' : 'ending'} at offset "${offset}" is out-of-bounds (size: ${size}).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'SliceOffsetOutOfBoundsError' }); } } class SizeExceedsPaddingSizeError extends BaseError { constructor({ size, targetSize, type, }) { super(`${type.charAt(0).toUpperCase()}${type .slice(1) .toLowerCase()} size (${size}) exceeds padding size (${targetSize}).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'SizeExceedsPaddingSizeError' }); } } class InvalidBytesLengthError extends BaseError { constructor({ size, targetSize, type, }) { super(`${type.charAt(0).toUpperCase()}${type .slice(1) .toLowerCase()} is expected to be ${targetSize} ${type} long, but is ${size} ${type} long.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidBytesLengthError' }); } } function pad(hexOrBytes, { dir, size = 32 } = {}) { if (typeof hexOrBytes === 'string') return padHex(hexOrBytes, { dir, size }); return padBytes(hexOrBytes, { dir, size }); } function padHex(hex_, { dir, size = 32 } = {}) { if (size === null) return hex_; const hex = hex_.replace('0x', ''); if (hex.length > size * 2) throw new SizeExceedsPaddingSizeError({ size: Math.ceil(hex.length / 2), targetSize: size, type: 'hex', }); return `0x${hex[dir === 'right' ? 'padEnd' : 'padStart'](size * 2, '0')}`; } function padBytes(bytes, { dir, size = 32 } = {}) { if (size === null) return bytes; if (bytes.length > size) throw new SizeExceedsPaddingSizeError({ size: bytes.length, targetSize: size, type: 'bytes', }); const paddedBytes = new Uint8Array(size); for (let i = 0; i < size; i++) { const padEnd = dir === 'right'; paddedBytes[padEnd ? i : size - i - 1] = bytes[padEnd ? i : bytes.length - i - 1]; } return paddedBytes; } const hexes = /*#__PURE__*/ Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, '0')); /** * Encodes a string, number, bigint, or ByteArray into a hex string * * - Docs: https://viem.sh/docs/utilities/toHex * - Example: https://viem.sh/docs/utilities/toHex#usage * * @param value Value to encode. * @param opts Options. * @returns Hex value. * * @example * import { toHex } from 'viem' * const data = toHex('Hello world') * // '0x48656c6c6f20776f726c6421' * * @example * import { toHex } from 'viem' * const data = toHex(420) * // '0x1a4' * * @example * import { toHex } from 'viem' * const data = toHex('Hello world', { size: 32 }) * // '0x48656c6c6f20776f726c64210000000000000000000000000000000000000000' */ function toHex(value, opts = {}) { if (typeof value === 'number' || typeof value === 'bigint') return numberToHex(value, opts); if (typeof value === 'string') { return stringToHex(value, opts); } if (typeof value === 'boolean') return boolToHex(value, opts); return bytesToHex(value, opts); } /** * Encodes a boolean into a hex string * * - Docs: https://viem.sh/docs/utilities/toHex#booltohex * * @param value Value to encode. * @param opts Options. * @returns Hex value. * * @example * import { boolToHex } from 'viem' * const data = boolToHex(true) * // '0x1' * * @example * import { boolToHex } from 'viem' * const data = boolToHex(false) * // '0x0' * * @example * import { boolToHex } from 'viem' * const data = boolToHex(true, { size: 32 }) * // '0x0000000000000000000000000000000000000000000000000000000000000001' */ function boolToHex(value, opts = {}) { const hex = `0x${Number(value)}`; if (typeof opts.size === 'number') { assertSize(hex, { size: opts.size }); return pad(hex, { size: opts.size }); } return hex; } /** * Encodes a bytes array into a hex string * * - Docs: https://viem.sh/docs/utilities/toHex#bytestohex * * @param value Value to encode. * @param opts Options. * @returns Hex value. * * @example * import { bytesToHex } from 'viem' * const data = bytesToHex(Uint8Array.from([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]) * // '0x48656c6c6f20576f726c6421' * * @example * import { bytesToHex } from 'viem' * const data = bytesToHex(Uint8Array.from([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]), { size: 32 }) * // '0x48656c6c6f20576f726c64210000000000000000000000000000000000000000' */ function bytesToHex(value, opts = {}) { let string = ''; for (let i = 0; i < value.length; i++) { string += hexes[value[i]]; } const hex = `0x${string}`; if (typeof opts.size === 'number') { assertSize(hex, { size: opts.size }); return pad(hex, { dir: 'right', size: opts.size }); } return hex; } /** * Encodes a number or bigint into a hex string * * - Docs: https://viem.sh/docs/utilities/toHex#numbertohex * * @param value Value to encode. * @param opts Options. * @returns Hex value. * * @example * import { numberToHex } from 'viem' * const data = numberToHex(420) * // '0x1a4' * * @example * import { numberToHex } from 'viem' * const data = numberToHex(420, { size: 32 }) * // '0x00000000000000000000000000000000000000000000000000000000000001a4' */ function numberToHex(value_, opts = {}) { const { signed, size } = opts; const value = BigInt(value_); let maxValue; if (size) { if (signed) maxValue = (1n << (BigInt(size) * 8n - 1n)) - 1n; else maxValue = 2n ** (BigInt(size) * 8n) - 1n; } else if (typeof value_ === 'number') { maxValue = BigInt(Number.MAX_SAFE_INTEGER); } const minValue = typeof maxValue === 'bigint' && signed ? -maxValue - 1n : 0; if ((maxValue && value > maxValue) || value < minValue) { const suffix = typeof value_ === 'bigint' ? 'n' : ''; throw new IntegerOutOfRangeError({ max: maxValue ? `${maxValue}${suffix}` : undefined, min: `${minValue}${suffix}`, signed, size, value: `${value_}${suffix}`, }); } const hex = `0x${(signed && value < 0 ? (1n << BigInt(size * 8)) + BigInt(value) : value).toString(16)}`; if (size) return pad(hex, { size }); return hex; } const encoder$1 = /*#__PURE__*/ new TextEncoder(); /** * Encodes a UTF-8 string into a hex string * * - Docs: https://viem.sh/docs/utilities/toHex#stringtohex * * @param value Value to encode. * @param opts Options. * @returns Hex value. * * @example * import { stringToHex } from 'viem' * const data = stringToHex('Hello World!') * // '0x48656c6c6f20576f726c6421' * * @example * import { stringToHex } from 'viem' * const data = stringToHex('Hello World!', { size: 32 }) * // '0x48656c6c6f20576f726c64210000000000000000000000000000000000000000' */ function stringToHex(value_, opts = {}) { const value = encoder$1.encode(value_); return bytesToHex(value, opts); } const encoder = /*#__PURE__*/ new TextEncoder(); /** * Encodes a UTF-8 string, hex value, bigint, number or boolean to a byte array. * * - Docs: https://viem.sh/docs/utilities/toBytes * - Example: https://viem.sh/docs/utilities/toBytes#usage * * @param value Value to encode. * @param opts Options. * @returns Byte array value. * * @example * import { toBytes } from 'viem' * const data = toBytes('Hello world') * // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]) * * @example * import { toBytes } from 'viem' * const data = toBytes(420) * // Uint8Array([1, 164]) * * @example * import { toBytes } from 'viem' * const data = toBytes(420, { size: 4 }) * // Uint8Array([0, 0, 1, 164]) */ function toBytes$1(value, opts = {}) { if (typeof value === 'number' || typeof value === 'bigint') return numberToBytes(value, opts); if (typeof value === 'boolean') return boolToBytes(value, opts); if (isHex(value)) return hexToBytes(value, opts); return stringToBytes(value, opts); } /** * Encodes a boolean into a byte array. * * - Docs: https://viem.sh/docs/utilities/toBytes#booltobytes * * @param value Boolean value to encode. * @param opts Options. * @returns Byte array value. * * @example * import { boolToBytes } from 'viem' * const data = boolToBytes(true) * // Uint8Array([1]) * * @example * import { boolToBytes } from 'viem' * const data = boolToBytes(true, { size: 32 }) * // Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) */ function boolToBytes(value, opts = {}) { const bytes = new Uint8Array(1); bytes[0] = Number(value); if (typeof opts.size === 'number') { assertSize(bytes, { size: opts.size }); return pad(bytes, { size: opts.size }); } return bytes; } // We use very optimized technique to convert hex string to byte array const charCodeMap = { zero: 48, nine: 57, A: 65, F: 70, a: 97, f: 102, }; function charCodeToBase16(char) { if (char >= charCodeMap.zero && char <= charCodeMap.nine) return char - charCodeMap.zero; if (char >= charCodeMap.A && char <= charCodeMap.F) return char - (charCodeMap.A - 10); if (char >= charCodeMap.a && char <= charCodeMap.f) return char - (charCodeMap.a - 10); return undefined; } /** * Encodes a hex string into a byte array. * * - Docs: https://viem.sh/docs/utilities/toBytes#hextobytes * * @param hex Hex string to encode. * @param opts Options. * @returns Byte array value. * * @example * import { hexToBytes } from 'viem' * const data = hexToBytes('0x48656c6c6f20776f726c6421') * // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]) * * @example * import { hexToBytes } from 'viem' * const data = hexToBytes('0x48656c6c6f20776f726c6421', { size: 32 }) * // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) */ function hexToBytes(hex_, opts = {}) { let hex = hex_; if (opts.size) { assertSize(hex, { size: opts.size }); hex = pad(hex, { dir: 'right', size: opts.size }); } let hexString = hex.slice(2); if (hexString.length % 2) hexString = `0${hexString}`; const length = hexString.length / 2; const bytes = new Uint8Array(length); for (let index = 0, j = 0; index < length; index++) { const nibbleLeft = charCodeToBase16(hexString.charCodeAt(j++)); const nibbleRight = charCodeToBase16(hexString.charCodeAt(j++)); if (nibbleLeft === undefined || nibbleRight === undefined) { throw new BaseError(`Invalid byte sequence ("${hexString[j - 2]}${hexString[j - 1]}" in "${hexString}").`); } bytes[index] = nibbleLeft * 16 + nibbleRight; } return bytes; } /** * Encodes a number into a byte array. * * - Docs: https://viem.sh/docs/utilities/toBytes#numbertobytes * * @param value Number to encode. * @param opts Options. * @returns Byte array value. * * @example * import { numberToBytes } from 'viem' * const data = numberToBytes(420) * // Uint8Array([1, 164]) * * @example * import { numberToBytes } from 'viem' * const data = numberToBytes(420, { size: 4 }) * // Uint8Array([0, 0, 1, 164]) */ function numberToBytes(value, opts) { const hex = numberToHex(value, opts); return hexToBytes(hex); } /** * Encodes a UTF-8 string into a byte array. * * - Docs: https://viem.sh/docs/utilities/toBytes#stringtobytes * * @param value String to encode. * @param opts Options. * @returns Byte array value. * * @example * import { stringToBytes } from 'viem' * const data = stringToBytes('Hello world!') * // Uint8Array([72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]) * * @example * import { stringToBytes } from 'viem' * const data = stringToBytes('Hello world!', { size: 32 }) * // Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) */ function stringToBytes(value, opts = {}) { const bytes = encoder.encode(value); if (typeof opts.size === 'number') { assertSize(bytes, { size: opts.size }); return pad(bytes, { dir: 'right', size: opts.size }); } return bytes; } function assertSize(hexOrBytes, { size: size$1 }) { if (size(hexOrBytes) > size$1) throw new SizeOverflowError({ givenSize: size(hexOrBytes), maxSize: size$1, }); } /** * Decodes a hex value into a bigint. * * - Docs: https://viem.sh/docs/utilities/fromHex#hextobigint * * @param hex Hex value to decode. * @param opts Options. * @returns BigInt value. * * @example * import { hexToBigInt } from 'viem' * const data = hexToBigInt('0x1a4', { signed: true }) * // 420n * * @example * import { hexToBigInt } from 'viem' * const data = hexToBigInt('0x00000000000000000000000000000000000000000000000000000000000001a4', { size: 32 }) * // 420n */ function hexToBigInt(hex, opts = {}) { const { signed } = opts; if (opts.size) assertSize(hex, { size: opts.size }); const value = BigInt(hex); if (!signed) return value; const size = (hex.length - 2) / 2; const max = (1n << (BigInt(size) * 8n - 1n)) - 1n; if (value <= max) return value; return value - BigInt(`0x${'f'.padStart(size * 2, 'f')}`) - 1n; } /** * Decodes a hex string into a number. * * - Docs: https://viem.sh/docs/utilities/fromHex#hextonumber * * @param hex Hex value to decode. * @param opts Options. * @returns Number value. * * @example * import { hexToNumber } from 'viem' * const data = hexToNumber('0x1a4') * // 420 * * @example * import { hexToNumber } from 'viem' * const data = hexToBigInt('0x00000000000000000000000000000000000000000000000000000000000001a4', { size: 32 }) * // 420 */ function hexToNumber(hex, opts = {}) { return Number(hexToBigInt(hex, opts)); } function defineFormatter(type, format) { return ({ exclude, format: overrides, }) => { return { exclude, format: (args) => { const formatted = format(args); if (exclude) { for (const key of exclude) { delete formatted[key]; } } return { ...formatted, ...overrides(args), }; }, type, }; }; } class InvalidAddressError extends BaseError { constructor({ address }) { super(`Address "${address}" is invalid.`, { metaMessages: [ '- Address must be a hex value of 20 bytes (40 hex characters).', '- Address must match its checksum counterpart.', ], }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidAddressError' }); } } /** * Map with a LRU (Least recently used) policy. * * @link https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU */ class LruMap extends Map { constructor(size) { super(); Object.defineProperty(this, "maxSize", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.maxSize = size; } set(key, value) { super.set(key, value); if (this.maxSize && this.size > this.maxSize) this.delete(this.keys().next().value); return this; } } function number(n) { if (!Number.isSafeInteger(n) || n < 0) throw new Error(`Wrong positive integer: ${n}`); } function bytes(b, ...lengths) { if (!(b instanceof Uint8Array)) 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}`); } } 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)); /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ const u8a = (a) => a instanceof Uint8Array; const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); // 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. 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 (!u8a(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; } // 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 = /* @__PURE__ */ BigInt(0); const _1n = /* @__PURE__ */ BigInt(1); const _2n = /* @__PURE__ */ BigInt(2); const _7n = /* @__PURE__ */ BigInt(7); const _256n = /* @__PURE__ */ BigInt(256); const _0x71n = /* @__PURE__ */ BigInt(0x71); for (let round = 0, R = _1n, 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; for (let j = 0; j < 7; j++) { R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n; if (R & _2n) t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n); } _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(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(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(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); function keccak256(value, to_) { const to = to_ || 'hex'; const bytes = keccak_256(isHex(value, { strict: false }) ? toBytes$1(value) : value); if (to === 'bytes') return bytes; return toHex(bytes); } const checksumAddressCache = /*#__PURE__*/ new LruMap(8192); function checksumAddress(address_, /** * Warning: EIP-1191 checksum addresses are generally not backwards compatible with the * wider Ethereum ecosystem, meaning it will break when validated against an application/tool * that relies on EIP-55 checksum encoding (checksum without chainId). * * It is highly recommended to not use this feature unless you * know what you are doing. * * See more: https://github.com/ethereum/EIPs/issues/1121 */ chainId) { if (checksumAddressCache.has(`${address_}.${chainId}`)) return checksumAddressCache.get(`${address_}.${chainId}`); const hexAddress = chainId ? `${chainId}${address_.toLowerCase()}` : address_.substring(2).toLowerCase(); const hash = keccak256(stringToBytes(hexAddress), 'bytes'); const address = (chainId ? hexAddress.substring(`${chainId}0x`.length) : hexAddress).split(''); for (let i = 0; i < 40; i += 2) { if (hash[i >> 1] >> 4 >= 8 && address[i]) { address[i] = address[i].toUpperCase(); } if ((hash[i >> 1] & 0x0f) >= 8 && address[i + 1]) { address[i + 1] = address[i + 1].toUpperCase(); } } const result = `0x${address.join('')}`; checksumAddressCache.set(`${address_}.${chainId}`, result); return result; } const addressRegex = /^0x[a-fA-F0-9]{40}$/; const isAddressCache = /*#__PURE__*/ new LruMap(8192); function isAddress(address, options) { const { strict = true } = options ?? {}; if (isAddressCache.has(address)) return isAddressCache.get(address); const result = (() => { if (!addressRegex.test(address)) return false; if (address.toLowerCase() === address) return true; if (strict) return checksumAddress(address) === address; return true; })(); isAddressCache.set(address, result); return result; } function concat(values) { if (typeof values[0] === 'string') return concatHex(values); return concatBytes(values); } function concatBytes(values) { let length = 0; for (const arr of values) { length += arr.length; } const result = new Uint8Array(length); let offset = 0; for (const arr of values) { result.set(arr, offset); offset += arr.length; } return result; } function concatHex(values) { return `0x${values.reduce((acc, x) => acc + x.replace('0x', ''), '')}`; } class NegativeOffsetError extends BaseError { constructor({ offset }) { super(`Offset \`${offset}\` cannot be negative.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'NegativeOffsetError' }); } } class PositionOutOfBoundsError extends BaseError { constructor({ length, position }) { super(`Position \`${position}\` is out of bounds (\`0 < position < ${length}\`).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'PositionOutOfBoundsError' }); } } class RecursiveReadLimitExceededError extends BaseError { constructor({ count, limit }) { super(`Recursive read limit of \`${limit}\` exceeded (recursive read count: \`${count}\`).`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'RecursiveReadLimitExceededError' }); } } const staticCursor = { bytes: new Uint8Array(), dataView: new DataView(new ArrayBuffer(0)), position: 0, positionReadCount: new Map(), recursiveReadCount: 0, recursiveReadLimit: Number.POSITIVE_INFINITY, assertReadLimit() { if (this.recursiveReadCount >= this.recursiveReadLimit) throw new RecursiveReadLimitExceededError({ count: this.recursiveReadCount + 1, limit: this.recursiveReadLimit, }); }, assertPosition(position) { if (position < 0 || position > this.bytes.length - 1) throw new PositionOutOfBoundsError({ length: this.bytes.length, position, }); }, decrementPosition(offset) { if (offset < 0) throw new NegativeOffsetError({ offset }); const position = this.position - offset; this.assertPosition(position); this.position = position; }, getReadCount(position) { return this.positionReadCount.get(position || this.position) || 0; }, incrementPosition(offset) { if (offset < 0) throw new NegativeOffsetError({ offset }); const position = this.position + offset; this.assertPosition(position); this.position = position; }, inspectByte(position_) { const position = position_ ?? this.position; this.assertPosition(position); return this.bytes[position]; }, inspectBytes(length, position_) { const position = position_ ?? this.position; this.assertPosition(position + length - 1); return this.bytes.subarray(position, position + length); }, inspectUint8(position_) { const position = position_ ?? this.position; this.assertPosition(position); return this.bytes[position]; }, inspectUint16(position_) { const position = position_ ?? this.position; this.assertPosition(position + 1); return this.dataView.getUint16(position); }, inspectUint24(position_) { const position = position_ ?? this.position; this.assertPosition(position + 2); return ((this.dataView.getUint16(position) << 8) + this.dataView.getUint8(position + 2)); }, inspectUint32(position_) { const position = position_ ?? this.position; this.assertPosition(position + 3); return this.dataView.getUint32(position); }, pushByte(byte) { this.assertPosition(this.position); this.bytes[this.position] = byte; this.position++; }, pushBytes(bytes) { this.assertPosition(this.position + bytes.length - 1); this.bytes.set(bytes, this.position); this.position += bytes.length; }, pushUint8(value) { this.assertPosition(this.position); this.bytes[this.position] = value; this.position++; }, pushUint16(value) { this.assertPosition(this.position + 1); this.dataView.setUint16(this.position, value); this.position += 2; }, pushUint24(value) { this.assertPosition(this.position + 2); this.dataView.setUint16(this.position, value >> 8); this.dataView.setUint8(this.position + 2, value & ~4294967040); this.position += 3; }, pushUint32(value) { this.assertPosition(this.position + 3); this.dataView.setUint32(this.position, value); this.position += 4; }, readByte() { this.assertReadLimit(); this._touch(); const value = this.inspectByte(); this.position++; return value; }, readBytes(length, size) { this.assertReadLimit(); this._touch(); const value = this.inspectBytes(length); this.position += size ?? length; return value; }, readUint8() { this.assertReadLimit(); this._touch(); const value = this.inspectUint8(); this.position += 1; return value; }, readUint16() { this.assertReadLimit(); this._touch(); const value = this.inspectUint16(); this.position += 2; return value; }, readUint24() { this.assertReadLimit(); this._touch(); const value = this.inspectUint24(); this.position += 3; return value; }, readUint32() { this.assertReadLimit(); this._touch(); const value = this.inspectUint32(); this.position += 4; return value; }, get remaining() { return this.bytes.length - this.position; }, setPosition(position) { const oldPosition = this.position; this.assertPosition(position); this.position = position; return () => (this.position = oldPosition); }, _touch() { if (this.recursiveReadLimit === Number.POSITIVE_INFINITY) return; const count = this.getReadCount(); this.positionReadCount.set(this.position, count + 1); if (count > 0) this.recursiveReadCount++; }, }; function createCursor(bytes, { recursiveReadLimit = 8_192 } = {}) { const cursor = Object.create(staticCursor); cursor.bytes = bytes; cursor.dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); cursor.positionReadCount = new Map(); cursor.recursiveReadLimit = recursiveReadLimit; return cursor; } const etherUnits = { gwei: 9, wei: 18, }; const gweiUnits = { ether: -9, wei: 9, }; /** * Divides a number by a given exponent of base 10 (10exponent), and formats it into a string representation of the number.. * * - Docs: https://viem.sh/docs/utilities/formatUnits * * @example * import { formatUnits } from 'viem' * * formatUnits(420000000000n, 9) * // '420' */ function formatUnits(value, decimals) { let display = value.toString(); const negative = display.startsWith('-'); if (negative) display = display.slice(1); display = display.padStart(decimals, '0'); let [integer, fraction] = [ display.slice(0, display.length - decimals), display.slice(display.length - decimals), ]; fraction = fraction.replace(/(0+)$/, ''); return `${negative ? '-' : ''}${integer || '0'}${fraction ? `.${fraction}` : ''}`; } /** * Converts numerical wei to a string representation of gwei. * * - Docs: https://viem.sh/docs/utilities/formatGwei * * @example * import { formatGwei } from 'viem' * * formatGwei(1000000000n) * // '1' */ function formatGwei(wei, unit = 'wei') { return formatUnits(wei, gweiUnits[unit]); } function prettyPrint(args) { const entries = Object.entries(args) .map(([key, value]) => { if (value === undefined || value === false) return null; return [key, value]; }) .filter(Boolean); const maxLength = entries.reduce((acc, [key]) => Math.max(acc, key.length), 0); return entries .map(([key, value]) => ` ${`${key}:`.padEnd(maxLength + 1)} ${value}`) .join('\n'); } class FeeConflictError extends BaseError { constructor() { super([ 'Cannot specify both a `gasPrice` and a `maxFeePerGas`/`maxPriorityFeePerGas`.', 'Use `maxFeePerGas`/`maxPriorityFeePerGas` for EIP-1559 compatible networks, and `gasPrice` for others.', ].join('\n')); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'FeeConflictError' }); } } class InvalidLegacyVError extends BaseError { constructor({ v }) { super(`Invalid \`v\` value "${v}". Expected 27 or 28.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidLegacyVError' }); } } class InvalidSerializableTransactionError extends BaseError { constructor({ transaction }) { super('Cannot infer a transaction type from provided transaction.', { metaMessages: [ 'Provided Transaction:', '{', prettyPrint(transaction), '}', '', 'To infer the type, either provide:', '- a `type` to the Transaction, or', '- an EIP-1559 Transaction with `maxFeePerGas`, or', '- an EIP-2930 Transaction with `gasPrice` & `accessList`, or', '- an EIP-4844 Transaction with `blobs`, `blobVersionedHashes`, `sidecars`, or', '- a Legacy Transaction with `gasPrice`', ], }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidSerializableTransactionError' }); } } class InvalidStorageKeySizeError extends BaseError { constructor({ storageKey }) { super(`Size for storage key "${storageKey}" is invalid. Expected 32 bytes. Got ${Math.floor((storageKey.length - 2) / 2)} bytes.`); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidStorageKeySizeError' }); } } class ChainDoesNotSupportContract extends BaseError { constructor({ blockNumber, chain, contract, }) { super(`Chain "${chain.name}" does not support contract "${contract.name}".`, { metaMessages: [ 'This could be due to any of the following:', ...(blockNumber && contract.blockCreated && contract.blockCreated > blockNumber ? [ `- The contract "${contract.name}" was not deployed until block ${contract.blockCreated} (current block ${blockNumber}).`, ] : [ `- The chain does not have the contract "${contract.name}" configured.`, ]), ], }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'ChainDoesNotSupportContract' }); } } class ClientChainNotConfiguredError extends BaseError { constructor() { super('No chain was provided to the Client.'); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'ClientChainNotConfiguredError' }); } } class InvalidChainIdError extends BaseError { constructor({ chainId }) { super(typeof chainId === 'number' ? `Chain ID "${chainId}" is invalid.` : 'Chain ID is invalid.'); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'InvalidChainIdError' }); } } class ExecutionRevertedError extends BaseError { constructor({ cause, message, } = {}) { const reason = message ?.replace('execution reverted: ', '') ?.replace('execution reverted', ''); super(`Execution reverted ${reason ? `with reason: ${reason}` : 'for an unknown reason'}.`, { cause, }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'ExecutionRevertedError' }); } } Object.defineProperty(ExecutionRevertedError, "code", { enumerable: true, configurable: true, writable: true, value: 3 }); Object.defineProperty(ExecutionRevertedError, "nodeMessage", { enumerable: true, configurable: true, writable: true, value: /execution reverted/ }); class FeeCapTooHighError extends BaseError { constructor({ cause, maxFeePerGas, } = {}) { super(`The fee cap (\`maxFeePerGas\`${maxFeePerGas ? ` = ${formatGwei(maxFeePerGas)} gwei` : ''}) cannot be higher than the maximum allowed value (2^256-1).`, { cause, }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'FeeCapTooHigh' }); } } Object.defineProperty(FeeCapTooHighError, "nodeMessage", { enumerable: true, configurable: true, writable: true, value: /max fee per gas higher than 2\^256-1|fee cap higher than 2\^256-1/ }); class FeeCapTooLowError extends BaseError { constructor({ cause, maxFeePerGas, } = {}) { super(`The fee cap (\`maxFeePerGas\`${maxFeePerGas ? ` = ${formatGwei(maxFeePerGas)}` : ''} gwei) cannot be lower than the block base fee.`, { cause, }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'FeeCapTooLow' }); } } Object.defineProperty(FeeCapTooLowError, "nodeMessage", { enumerable: true, configurable: true, writable: true, value: /max fee per gas less than block base fee|fee cap less than block base fee|transaction is outdated/ }); class NonceTooHighError extends BaseError { constructor({ cause, nonce, } = {}) { super(`Nonce provided for the transaction ${nonce ? `(${nonce}) ` : ''}is higher than the next one expected.`, { cause }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'NonceTooHighError' }); } } Object.defineProperty(NonceTooHighError, "nodeMessage", { enumerable: true, configurable: true, writable: true, value: /nonce too high/ }); class NonceTooLowError extends BaseError { constructor({ cause, nonce, } = {}) { super([ `Nonce provided for the transaction ${nonce ? `(${nonce}) ` : ''}is lower than the current nonce of the account.`, 'Try increasing the nonce or find the latest nonce with `getTransactionCount`.', ].join('\n'), { cause }); Object.defineProperty(this, "name", { enumerable: true,