@naculus/connect-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/_u64.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/cryptoNode.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/utils.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/sha3.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/_u64.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/cryptoNode.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/utils.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/sha3.ts","../src/token/errors.ts","../src/token/units.ts","../src/index.ts","../src/account-abstraction/errors.ts","../src/account-abstraction/paymaster.ts","../src/account-abstraction/types.ts","../src/account-abstraction/user-operation.ts","../src/account-abstraction/SmartAccountManager.ts","../src/address-validation.ts","../src/auto-reconnect.ts","../src/logger.ts","../src/chain-abstraction/providers/AxelarProvider.ts","../src/chain-abstraction/providers/LiFiProvider.ts","../src/chain-abstraction/route-engine.ts","../src/chain-abstraction/types.ts","../src/chain-registry.ts","../src/connector.ts","../src/errors.ts","../src/platform.ts","../src/connector-manager.ts","../src/constants.ts","../src/fee-estimation/conversion.ts","../src/fee-estimation/errors.ts","../src/fee-estimation/feeEstimation.ts","../src/notification/channels.ts","../src/notification/Notifier.ts","../src/permissions.ts","../src/rpc.ts","../src/resolver/providers/ens.ts","../src/resolver/types.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/_md.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/sha2.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/sha256.ts","../src/resolver/providers/sns.ts","../src/resolver/NameResolver.ts","../src/storage.ts","../src/session.ts","../src/session-keys/errors.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/hmac.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/abstract/weierstrass.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/utils.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/abstract/modular.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/abstract/curve.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/_shortw_utils.ts","../../../node_modules/.pnpm/@noble+curves@1.9.7/node_modules/@noble/curves/src/secp256k1.ts","../src/session-keys/SessionKeyManager.ts","../../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/src/pbkdf2.ts","../src/session-keys/storage.ts","../src/session-keys/types.ts","../src/session-manager/errors.ts","../src/session-manager/events.ts","../src/session-manager/persistence.ts","../src/session-manager/types.ts","../src/session-manager/session-manager.ts","../src/simulation/providers/BlowfishProvider.ts","../src/simulation/providers/EthCallProvider.ts","../src/abortable-fetch.ts","../src/token/abi.ts","../src/token/ERC20TokenHelper.ts","../src/simulation/SimulationManager.ts","../src/token/index.ts","../src/token-list/auto-detect.ts","../src/token-list/lists.ts","../src/token-list/TokenListManager.ts","../src/token-price.ts"],"sourcesContent":["/**\n * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.\n * @todo re-check https://issues.chromium.org/issues/42212588\n * @module\n */\nconst U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n\nfunction fromBig(\n n: bigint,\n le = false\n): {\n h: number;\n l: number;\n} {\n if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n\nfunction split(lst: bigint[], le = false): Uint32Array[] {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n\nconst toBig = (h: number, l: number): bigint => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h: number, _l: number, s: number): number => h >>> s;\nconst shrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h: number, l: number, s: number): number => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h: number, l: number, s: number): number => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h: number, l: number, s: number): number => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (_h: number, l: number): number => l;\nconst rotr32L = (h: number, _l: number): number => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h: number, l: number, s: number): number => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h: number, l: number, s: number): number => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h: number, l: number, s: number): number => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h: number, l: number, s: number): number => (h << (s - 32)) | (l >>> (64 - s));\n\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\nfunction add(\n Ah: number,\n Al: number,\n Bh: number,\n Bl: number\n): {\n h: number;\n l: number;\n} {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al: number, Bl: number, Cl: number): number => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low: number, Ah: number, Bh: number, Ch: number): number =>\n (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al: number, Bl: number, Cl: number, Dl: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number): number =>\n (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al: number, Bl: number, Cl: number, Dl: number, El: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number): number =>\n (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n\n// prettier-ignore\nexport {\n add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig\n};\n// prettier-ignore\nconst u64: { fromBig: typeof fromBig; split: typeof split; toBig: (h: number, l: number) => bigint; shrSH: (h: number, _l: number, s: number) => number; shrSL: (h: number, l: number, s: number) => number; rotrSH: (h: number, l: number, s: number) => number; rotrSL: (h: number, l: number, s: number) => number; rotrBH: (h: number, l: number, s: number) => number; rotrBL: (h: number, l: number, s: number) => number; rotr32H: (_h: number, l: number) => number; rotr32L: (h: number, _l: number) => number; rotlSH: (h: number, l: number, s: number) => number; rotlSL: (h: number, l: number, s: number) => number; rotlBH: (h: number, l: number, s: number) => number; rotlBL: (h: number, l: number, s: number) => number; add: typeof add; add3L: (Al: number, Bl: number, Cl: number) => number; add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; } = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\nexport default u64;\n","/**\n * Internal webcrypto alias.\n * We prefer WebCrypto aka globalThis.crypto, which exists in node.js 16+.\n * Falls back to Node.js built-in crypto for Node.js <=v14.\n * See utils.ts for details.\n * @module\n */\n// @ts-ignore\nimport * as nc from 'node:crypto';\nexport const crypto: any =\n nc && typeof nc === 'object' && 'webcrypto' in nc\n ? (nc.webcrypto as any)\n : nc && typeof nc === 'object' && 'randomBytes' in nc\n ? nc\n : undefined;\n","/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\n\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a: unknown): a is Uint8Array {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n\n/** Asserts something is positive integer. */\nexport function anumber(n: number): void {\n if (!Number.isSafeInteger(n) || n < 0) throw new Error('positive integer expected, got ' + n);\n}\n\n/** Asserts something is Uint8Array. */\nexport function abytes(b: Uint8Array | undefined, ...lengths: number[]): void {\n if (!isBytes(b)) throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n\n/** Asserts something is hash */\nexport function ahash(h: IHash): void {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance: any, checkFinished = true): void {\n if (instance.destroyed) throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called');\n}\n\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out: any, instance: any): void {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n\n/** Generic type encompassing 8/16/32-byte arrays - but not 64-byte. */\n// prettier-ignore\nexport type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |\n Uint16Array | Int16Array | Uint32Array | Int32Array;\n\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr: TypedArray): Uint8Array {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr: TypedArray): Uint32Array {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays: TypedArray[]): void {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr: TypedArray): DataView {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** The rotate right (circular right shift) operation for uint32 */\nexport function rotr(word: number, shift: number): number {\n return (word << (32 - shift)) | (word >>> shift);\n}\n\n/** The rotate left (circular left shift) operation for uint32 */\nexport function rotl(word: number, shift: number): number {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE: boolean = /* @__PURE__ */ (() =>\n new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n\n/** The byte swap operation for uint32 */\nexport function byteSwap(word: number): number {\n return (\n ((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff)\n );\n}\n/** Conditionally byte swap if on a big-endian platform */\nexport const swap8IfBE: (n: number) => number = isLE\n ? (n: number) => n\n : (n: number) => byteSwap(n);\n\n/** @deprecated */\nexport const byteSwapIfBE: typeof swap8IfBE = swap8IfBE;\n/** In place byte swap for Uint32Array */\nexport function byteSwap32(arr: Uint32Array): Uint32Array {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n\nexport const swap32IfBE: (u: Uint32Array) => Uint32Array = isLE\n ? (u: Uint32Array) => u\n : byteSwap32;\n\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin: boolean = /* @__PURE__ */ (() =>\n // @ts-ignore\n typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n i.toString(16).padStart(2, '0')\n);\n\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin) return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const;\nfunction asciiToBase16(ch: number): number | undefined {\n if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin) return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * Call of async fn will return Promise, which will be fullfiled only on\n * next scheduler queue processing step and this is exactly what we need.\n */\nexport const nextTick = async (): Promise<void> => {};\n\n/** Returns control to thread each 'tick' ms to avoid blocking. */\nexport async function asyncLoop(\n iters: number,\n tick: number,\n cb: (i: number) => void\n): Promise<void> {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick) continue;\n await nextTick();\n ts += diff;\n }\n}\n\n// Global symbols, but ts doesn't see them: https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\ndeclare const TextDecoder: any;\n\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n if (typeof str !== 'string') throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\n/** Accepted input of hash functions. Strings are converted to byte arrays. */\nexport type Input = string | Uint8Array;\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data: Input): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** KDFs can accept string or Uint8Array for user convenience. */\nexport type KDFInput = string | Uint8Array;\n/**\n * Helper for KDFs: consumes uint8array or string.\n * When string is passed, does utf8 decoding, using TextDecoder.\n */\nexport function kdfInputToBytes(data: KDFInput): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** Copies several Uint8Arrays into one. */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n\ntype EmptyObj = {};\nexport function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(\n defaults: T1,\n opts?: T2\n): T1 & T2 {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new Error('options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged as T1 & T2;\n}\n\n/** Hash interface. */\nexport type IHash = {\n (data: Uint8Array): Uint8Array;\n blockLen: number;\n outputLen: number;\n create: any;\n};\n\n/** For runtime check if class implements interface */\nexport abstract class Hash<T extends Hash<T>> {\n abstract blockLen: number; // Bytes per block\n abstract outputLen: number; // Bytes in output\n abstract update(buf: Input): this;\n // Writes digest into buf\n abstract digestInto(buf: Uint8Array): void;\n abstract digest(): Uint8Array;\n /**\n * Resets internal state. Makes Hash instance unusable.\n * Reset is impossible for keyed hashes if key is consumed into state. If digest is not consumed\n * by user, they will need to manually call `destroy()` when zeroing is necessary.\n */\n abstract destroy(): void;\n /**\n * Clones hash instance. Unsafe: doesn't check whether `to` is valid. Can be used as `clone()`\n * when no options are passed.\n * Reasons to use `_cloneInto` instead of clone: 1) performance 2) reuse instance => all internal\n * buffers are overwritten => causes buffer overwrite which is used for digest in some cases.\n * There are no guarantees for clean-up because it's impossible in JS.\n */\n abstract _cloneInto(to?: T): T;\n // Safe version that clones internal state\n abstract clone(): T;\n}\n\n/**\n * XOF: streaming API to read digest in chunks.\n * Same as 'squeeze' in keccak/k12 and 'seek' in blake3, but more generic name.\n * When hash used in XOF mode it is up to user to call '.destroy' afterwards, since we cannot\n * destroy state, next call can require more bytes.\n */\nexport type HashXOF<T extends Hash<T>> = Hash<T> & {\n xof(bytes: number): Uint8Array; // Read 'bytes' bytes from digest stream\n xofInto(buf: Uint8Array): Uint8Array; // read buf.length bytes from digest stream into buf\n};\n\n/** Hash function */\nexport type CHash = ReturnType<typeof createHasher>;\n/** Hash function with output */\nexport type CHashO = ReturnType<typeof createOptHasher>;\n/** XOF with output */\nexport type CHashXO = ReturnType<typeof createXOFer>;\n\n/** Wraps hash function, creating an interface on top of it */\nexport function createHasher<T extends Hash<T>>(\n hashCons: () => Hash<T>\n): {\n (msg: Input): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(): Hash<T>;\n} {\n const hashC = (msg: Input): Uint8Array => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\n\nexport function createOptHasher<H extends Hash<H>, T extends Object>(\n hashCons: (opts?: T) => Hash<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): Hash<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\n\nexport function createXOFer<H extends HashXOF<H>, T extends Object>(\n hashCons: (opts?: T) => HashXOF<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): HashXOF<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\nexport const wrapConstructor: typeof createHasher = createHasher;\nexport const wrapConstructorWithOpts: typeof createOptHasher = createOptHasher;\nexport const wrapXOFConstructorWithOpts: typeof createXOFer = createXOFer;\n\n/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */\nexport function randomBytes(bytesLength = 32): Uint8Array {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n // Legacy Node.js compatibility\n if (crypto && typeof crypto.randomBytes === 'function') {\n return Uint8Array.from(crypto.randomBytes(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n","/**\n * SHA3 (keccak) hash function, based on a new \"Sponge function\" design.\n * Different from older hashes, the internal state is bigger than output size.\n *\n * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),\n * [Website](https://keccak.team/keccak.html),\n * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).\n *\n * Check out `sha3-addons` module for cSHAKE, k12, and others.\n * @module\n */\nimport { rotlBH, rotlBL, rotlSH, rotlSL, split } from './_u64.ts';\n// prettier-ignore\nimport {\n abytes, aexists, anumber, aoutput,\n clean, createHasher, createXOFer, Hash,\n swap32IfBE,\n toBytes, u32,\n type CHash, type CHashXO, type HashXOF, type Input\n} from './utils.ts';\n\n// No __PURE__ annotations in sha3 header:\n// EVERYTHING is in fact used on every export.\n// Various per round constants calculations\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _7n = BigInt(7);\nconst _256n = BigInt(256);\nconst _0x71n = BigInt(0x71);\nconst SHA3_PI: number[] = [];\nconst SHA3_ROTL: number[] = [];\nconst _SHA3_IOTA: bigint[] = [];\nfor (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {\n // Pi\n [x, y] = [y, (2 * x + 3 * y) % 5];\n SHA3_PI.push(2 * (5 * y + x));\n // Rotational\n SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n // Iota\n let t = _0n;\n for (let j = 0; j < 7; j++) {\n R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;\n if (R & _2n) t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n);\n }\n _SHA3_IOTA.push(t);\n}\nconst IOTAS = split(_SHA3_IOTA, true);\nconst SHA3_IOTA_H = IOTAS[0];\nconst SHA3_IOTA_L = IOTAS[1];\n\n// Left rotation (without 0, 32, 64)\nconst rotlH = (h: number, l: number, s: number) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));\nconst rotlL = (h: number, l: number, s: number) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));\n\n/** `keccakf1600` internal function, additionally allows to adjust round count. */\nexport function keccakP(s: Uint32Array, rounds: number = 24): void {\n const B = new Uint32Array(5 * 2);\n // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)\n for (let round = 24 - rounds; round < 24; round++) {\n // Theta θ\n for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n for (let x = 0; x < 10; x += 2) {\n const idx1 = (x + 8) % 10;\n const idx0 = (x + 2) % 10;\n const B0 = B[idx0];\n const B1 = B[idx0 + 1];\n const Th = rotlH(B0, B1, 1) ^ B[idx1];\n const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];\n for (let y = 0; y < 50; y += 10) {\n s[x + y] ^= Th;\n s[x + y + 1] ^= Tl;\n }\n }\n // Rho (ρ) and Pi (π)\n let curH = s[2];\n let curL = s[3];\n for (let t = 0; t < 24; t++) {\n const shift = SHA3_ROTL[t];\n const Th = rotlH(curH, curL, shift);\n const Tl = rotlL(curH, curL, shift);\n const PI = SHA3_PI[t];\n curH = s[PI];\n curL = s[PI + 1];\n s[PI] = Th;\n s[PI + 1] = Tl;\n }\n // Chi (χ)\n for (let y = 0; y < 50; y += 10) {\n for (let x = 0; x < 10; x++) B[x] = s[y + x];\n for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n }\n // Iota (ι)\n s[0] ^= SHA3_IOTA_H[round];\n s[1] ^= SHA3_IOTA_L[round];\n }\n clean(B);\n}\n\n/** Keccak sponge function. */\nexport class Keccak extends Hash<Keccak> implements HashXOF<Keccak> {\n protected state: Uint8Array;\n protected pos = 0;\n protected posOut = 0;\n protected finished = false;\n protected state32: Uint32Array;\n protected destroyed = false;\n\n public blockLen: number;\n public suffix: number;\n public outputLen: number;\n protected enableXOF = false;\n protected rounds: number;\n\n // NOTE: we accept arguments in bytes instead of bits here.\n constructor(\n blockLen: number,\n suffix: number,\n outputLen: number,\n enableXOF = false,\n rounds: number = 24\n ) {\n super();\n this.blockLen = blockLen;\n this.suffix = suffix;\n this.outputLen = outputLen;\n this.enableXOF = enableXOF;\n this.rounds = rounds;\n // Can be passed from user as dkLen\n anumber(outputLen);\n // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes\n // 0 < blockLen < 200\n if (!(0 < blockLen && blockLen < 200))\n throw new Error('only keccak-f1600 function is supported');\n this.state = new Uint8Array(200);\n this.state32 = u32(this.state);\n }\n clone(): Keccak {\n return this._cloneInto();\n }\n protected keccak(): void {\n swap32IfBE(this.state32);\n keccakP(this.state32, this.rounds);\n swap32IfBE(this.state32);\n this.posOut = 0;\n this.pos = 0;\n }\n update(data: Input): this {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { blockLen, state } = this;\n const len = data.length;\n for (let pos = 0; pos < len; ) {\n const take = Math.min(blockLen - this.pos, len - pos);\n for (let i = 0; i < take; i++) state[this.pos++] ^= data[pos++];\n if (this.pos === blockLen) this.keccak();\n }\n return this;\n }\n protected finish(): void {\n if (this.finished) return;\n this.finished = true;\n const { state, suffix, pos, blockLen } = this;\n // Do the padding\n state[pos] ^= suffix;\n if ((suffix & 0x80) !== 0 && pos === blockLen - 1) this.keccak();\n state[blockLen - 1] ^= 0x80;\n this.keccak();\n }\n protected writeInto(out: Uint8Array): Uint8Array {\n aexists(this, false);\n abytes(out);\n this.finish();\n const bufferOut = this.state;\n const { blockLen } = this;\n for (let pos = 0, len = out.length; pos < len; ) {\n if (this.posOut >= blockLen) this.keccak();\n const take = Math.min(blockLen - this.posOut, len - pos);\n out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);\n this.posOut += take;\n pos += take;\n }\n return out;\n }\n xofInto(out: Uint8Array): Uint8Array {\n // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF\n if (!this.enableXOF) throw new Error('XOF is not possible for this instance');\n return this.writeInto(out);\n }\n xof(bytes: number): Uint8Array {\n anumber(bytes);\n return this.xofInto(new Uint8Array(bytes));\n }\n digestInto(out: Uint8Array): Uint8Array {\n aoutput(out, this);\n if (this.finished) throw new Error('digest() was already called');\n this.writeInto(out);\n this.destroy();\n return out;\n }\n digest(): Uint8Array {\n return this.digestInto(new Uint8Array(this.outputLen));\n }\n destroy(): void {\n this.destroyed = true;\n clean(this.state);\n }\n _cloneInto(to?: Keccak): Keccak {\n const { blockLen, suffix, outputLen, rounds, enableXOF } = this;\n to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds);\n to.state32.set(this.state32);\n to.pos = this.pos;\n to.posOut = this.posOut;\n to.finished = this.finished;\n to.rounds = rounds;\n // Suffix can change in cSHAKE\n to.suffix = suffix;\n to.outputLen = outputLen;\n to.enableXOF = enableXOF;\n to.destroyed = this.destroyed;\n return to;\n }\n}\n\nconst gen = (suffix: number, blockLen: number, outputLen: number) =>\n createHasher(() => new Keccak(blockLen, suffix, outputLen));\n\n/** SHA3-224 hash function. */\nexport const sha3_224: CHash = /* @__PURE__ */ (() => gen(0x06, 144, 224 / 8))();\n/** SHA3-256 hash function. Different from keccak-256. */\nexport const sha3_256: CHash = /* @__PURE__ */ (() => gen(0x06, 136, 256 / 8))();\n/** SHA3-384 hash function. */\nexport const sha3_384: CHash = /* @__PURE__ */ (() => gen(0x06, 104, 384 / 8))();\n/** SHA3-512 hash function. */\nexport const sha3_512: CHash = /* @__PURE__ */ (() => gen(0x06, 72, 512 / 8))();\n\n/** keccak-224 hash function. */\nexport const keccak_224: CHash = /* @__PURE__ */ (() => gen(0x01, 144, 224 / 8))();\n/** keccak-256 hash function. Different from SHA3-256. */\nexport const keccak_256: CHash = /* @__PURE__ */ (() => gen(0x01, 136, 256 / 8))();\n/** keccak-384 hash function. */\nexport const keccak_384: CHash = /* @__PURE__ */ (() => gen(0x01, 104, 384 / 8))();\n/** keccak-512 hash function. */\nexport const keccak_512: CHash = /* @__PURE__ */ (() => gen(0x01, 72, 512 / 8))();\n\nexport type ShakeOpts = { dkLen?: number };\n\nconst genShake = (suffix: number, blockLen: number, outputLen: number) =>\n createXOFer<HashXOF<Keccak>, ShakeOpts>(\n (opts: ShakeOpts = {}) =>\n new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true)\n );\n\n/** SHAKE128 XOF with 128-bit security. */\nexport const shake128: CHashXO = /* @__PURE__ */ (() => genShake(0x1f, 168, 128 / 8))();\n/** SHAKE256 XOF with 256-bit security. */\nexport const shake256: CHashXO = /* @__PURE__ */ (() => genShake(0x1f, 136, 256 / 8))();\n","/**\n * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.\n * @todo re-check https://issues.chromium.org/issues/42212588\n * @module\n */\nconst U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n\nfunction fromBig(\n n: bigint,\n le = false\n): {\n h: number;\n l: number;\n} {\n if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n\nfunction split(lst: bigint[], le = false): Uint32Array[] {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n\nconst toBig = (h: number, l: number): bigint => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h: number, _l: number, s: number): number => h >>> s;\nconst shrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h: number, l: number, s: number): number => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h: number, l: number, s: number): number => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h: number, l: number, s: number): number => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (_h: number, l: number): number => l;\nconst rotr32L = (h: number, _l: number): number => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h: number, l: number, s: number): number => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h: number, l: number, s: number): number => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h: number, l: number, s: number): number => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h: number, l: number, s: number): number => (h << (s - 32)) | (l >>> (64 - s));\n\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\nfunction add(\n Ah: number,\n Al: number,\n Bh: number,\n Bl: number\n): {\n h: number;\n l: number;\n} {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al: number, Bl: number, Cl: number): number => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low: number, Ah: number, Bh: number, Ch: number): number =>\n (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al: number, Bl: number, Cl: number, Dl: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number): number =>\n (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al: number, Bl: number, Cl: number, Dl: number, El: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number): number =>\n (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n\n// prettier-ignore\nexport {\n add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig\n};\n// prettier-ignore\nconst u64: { fromBig: typeof fromBig; split: typeof split; toBig: (h: number, l: number) => bigint; shrSH: (h: number, _l: number, s: number) => number; shrSL: (h: number, l: number, s: number) => number; rotrSH: (h: number, l: number, s: number) => number; rotrSL: (h: number, l: number, s: number) => number; rotrBH: (h: number, l: number, s: number) => number; rotrBL: (h: number, l: number, s: number) => number; rotr32H: (_h: number, l: number) => number; rotr32L: (h: number, _l: number) => number; rotlSH: (h: number, l: number, s: number) => number; rotlSL: (h: number, l: number, s: number) => number; rotlBH: (h: number, l: number, s: number) => number; rotlBL: (h: number, l: number, s: number) => number; add: typeof add; add3L: (Al: number, Bl: number, Cl: number) => number; add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; } = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\nexport default u64;\n","/**\n * Internal webcrypto alias.\n * We prefer WebCrypto aka globalThis.crypto, which exists in node.js 16+.\n * Falls back to Node.js built-in crypto for Node.js <=v14.\n * See utils.ts for details.\n * @module\n */\n// @ts-ignore\nimport * as nc from 'node:crypto';\nexport const crypto: any =\n nc && typeof nc === 'object' && 'webcrypto' in nc\n ? (nc.webcrypto as any)\n : nc && typeof nc === 'object' && 'randomBytes' in nc\n ? nc\n : undefined;\n","/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\n\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a: unknown): a is Uint8Array {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n\n/** Asserts something is positive integer. */\nexport function anumber(n: number): void {\n if (!Number.isSafeInteger(n) || n < 0) throw new Error('positive integer expected, got ' + n);\n}\n\n/** Asserts something is Uint8Array. */\nexport function abytes(b: Uint8Array | undefined, ...lengths: number[]): void {\n if (!isBytes(b)) throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n\n/** Asserts something is hash */\nexport function ahash(h: IHash): void {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance: any, checkFinished = true): void {\n if (instance.destroyed) throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called');\n}\n\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out: any, instance: any): void {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n\n/** Generic type encompassing 8/16/32-byte arrays - but not 64-byte. */\n// prettier-ignore\nexport type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |\n Uint16Array | Int16Array | Uint32Array | Int32Array;\n\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr: TypedArray): Uint8Array {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr: TypedArray): Uint32Array {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays: TypedArray[]): void {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr: TypedArray): DataView {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** The rotate right (circular right shift) operation for uint32 */\nexport function rotr(word: number, shift: number): number {\n return (word << (32 - shift)) | (word >>> shift);\n}\n\n/** The rotate left (circular left shift) operation for uint32 */\nexport function rotl(word: number, shift: number): number {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE: boolean = /* @__PURE__ */ (() =>\n new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n\n/** The byte swap operation for uint32 */\nexport function byteSwap(word: number): number {\n return (\n ((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff)\n );\n}\n/** Conditionally byte swap if on a big-endian platform */\nexport const swap8IfBE: (n: number) => number = isLE\n ? (n: number) => n\n : (n: number) => byteSwap(n);\n\n/** @deprecated */\nexport const byteSwapIfBE: typeof swap8IfBE = swap8IfBE;\n/** In place byte swap for Uint32Array */\nexport function byteSwap32(arr: Uint32Array): Uint32Array {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n\nexport const swap32IfBE: (u: Uint32Array) => Uint32Array = isLE\n ? (u: Uint32Array) => u\n : byteSwap32;\n\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin: boolean = /* @__PURE__ */ (() =>\n // @ts-ignore\n typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n i.toString(16).padStart(2, '0')\n);\n\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin) return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const;\nfunction asciiToBase16(ch: number): number | undefined {\n if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin) return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * Call of async fn will return Promise, which will be fullfiled only on\n * next scheduler queue processing step and this is exactly what we need.\n */\nexport const nextTick = async (): Promise<void> => {};\n\n/** Returns control to thread each 'tick' ms to avoid blocking. */\nexport async function asyncLoop(\n iters: number,\n tick: number,\n cb: (i: number) => void\n): Promise<void> {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick) continue;\n await nextTick();\n ts += diff;\n }\n}\n\n// Global symbols, but ts doesn't see them: https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\ndeclare const TextDecoder: any;\n\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n if (typeof str !== 'string') throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\n/** Accepted input of hash functions. Strings are converted to byte arrays. */\nexport type Input = string | Uint8Array;\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data: Input): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** KDFs can accept string or Uint8Array for user convenience. */\nexport type KDFInput = string | Uint8Array;\n/**\n * Helper for KDFs: consumes uint8array or string.\n * When string is passed, does utf8 decoding, using TextDecoder.\n */\nexport function kdfInputToBytes(data: KDFInput): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** Copies several Uint8Arrays into one. */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n\ntype EmptyObj = {};\nexport function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(\n defaults: T1,\n opts?: T2\n): T1 & T2 {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new Error('options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged as T1 & T2;\n}\n\n/** Hash interface. */\nexport type IHash = {\n (data: Uint8Array): Uint8Array;\n blockLen: number;\n outputLen: number;\n create: any;\n};\n\n/** For runtime check if class implements interface */\nexport abstract class Hash<T extends Hash<T>> {\n abstract blockLen: number; // Bytes per block\n abstract outputLen: number; // Bytes in output\n abstract update(buf: Input): this;\n // Writes digest into buf\n abstract digestInto(buf: Uint8Array): void;\n abstract digest(): Uint8Array;\n /**\n * Resets internal state. Makes Hash instance unusable.\n * Reset is impossible for keyed hashes if key is consumed into state. If digest is not consumed\n * by user, they will need to manually call `destroy()` when zeroing is necessary.\n */\n abstract destroy(): void;\n /**\n * Clones hash instance. Unsafe: doesn't check whether `to` is valid. Can be used as `clone()`\n * when no options are passed.\n * Reasons to use `_cloneInto` instead of clone: 1) performance 2) reuse instance => all internal\n * buffers are overwritten => causes buffer overwrite which is used for digest in some cases.\n * There are no guarantees for clean-up because it's impossible in JS.\n */\n abstract _cloneInto(to?: T): T;\n // Safe version that clones internal state\n abstract clone(): T;\n}\n\n/**\n * XOF: streaming API to read digest in chunks.\n * Same as 'squeeze' in keccak/k12 and 'seek' in blake3, but more generic name.\n * When hash used in XOF mode it is up to user to call '.destroy' afterwards, since we cannot\n * destroy state, next call can require more bytes.\n */\nexport type HashXOF<T extends Hash<T>> = Hash<T> & {\n xof(bytes: number): Uint8Array; // Read 'bytes' bytes from digest stream\n xofInto(buf: Uint8Array): Uint8Array; // read buf.length bytes from digest stream into buf\n};\n\n/** Hash function */\nexport type CHash = ReturnType<typeof createHasher>;\n/** Hash function with output */\nexport type CHashO = ReturnType<typeof createOptHasher>;\n/** XOF with output */\nexport type CHashXO = ReturnType<typeof createXOFer>;\n\n/** Wraps hash function, creating an interface on top of it */\nexport function createHasher<T extends Hash<T>>(\n hashCons: () => Hash<T>\n): {\n (msg: Input): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(): Hash<T>;\n} {\n const hashC = (msg: Input): Uint8Array => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\n\nexport function createOptHasher<H extends Hash<H>, T extends Object>(\n hashCons: (opts?: T) => Hash<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): Hash<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\n\nexport function createXOFer<H extends HashXOF<H>, T extends Object>(\n hashCons: (opts?: T) => HashXOF<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): HashXOF<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\nexport const wrapConstructor: typeof createHasher = createHasher;\nexport const wrapConstructorWithOpts: typeof createOptHasher = createOptHasher;\nexport const wrapXOFConstructorWithOpts: typeof createXOFer = createXOFer;\n\n/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */\nexport function randomBytes(bytesLength = 32): Uint8Array {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n // Legacy Node.js compatibility\n if (crypto && typeof crypto.randomBytes === 'function') {\n return Uint8Array.from(crypto.randomBytes(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n","/**\n * SHA3 (keccak) hash function, based on a new \"Sponge function\" design.\n * Different from older hashes, the internal state is bigger than output size.\n *\n * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),\n * [Website](https://keccak.team/keccak.html),\n * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).\n *\n * Check out `sha3-addons` module for cSHAKE, k12, and others.\n * @module\n */\nimport { rotlBH, rotlBL, rotlSH, rotlSL, split } from './_u64.ts';\n// prettier-ignore\nimport {\n abytes, aexists, anumber, aoutput,\n clean, createHasher, createXOFer, Hash,\n swap32IfBE,\n toBytes, u32,\n type CHash, type CHashXO, type HashXOF, type Input\n} from './utils.ts';\n\n// No __PURE__ annotations in sha3 header:\n// EVERYTHING is in fact used on every export.\n// Various per round constants calculations\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _7n = BigInt(7);\nconst _256n = BigInt(256);\nconst _0x71n = BigInt(0x71);\nconst SHA3_PI: number[] = [];\nconst SHA3_ROTL: number[] = [];\nconst _SHA3_IOTA: bigint[] = [];\nfor (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {\n // Pi\n [x, y] = [y, (2 * x + 3 * y) % 5];\n SHA3_PI.push(2 * (5 * y + x));\n // Rotational\n SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n // Iota\n let t = _0n;\n for (let j = 0; j < 7; j++) {\n R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;\n if (R & _2n) t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n);\n }\n _SHA3_IOTA.push(t);\n}\nconst IOTAS = split(_SHA3_IOTA, true);\nconst SHA3_IOTA_H = IOTAS[0];\nconst SHA3_IOTA_L = IOTAS[1];\n\n// Left rotation (without 0, 32, 64)\nconst rotlH = (h: number, l: number, s: number) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));\nconst rotlL = (h: number, l: number, s: number) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));\n\n/** `keccakf1600` internal function, additionally allows to adjust round count. */\nexport function keccakP(s: Uint32Array, rounds: number = 24): void {\n const B = new Uint32Array(5 * 2);\n // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)\n for (let round = 24 - rounds; round < 24; round++) {\n // Theta θ\n for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n for (let x = 0; x < 10; x += 2) {\n const idx1 = (x + 8) % 10;\n const idx0 = (x + 2) % 10;\n const B0 = B[idx0];\n const B1 = B[idx0 + 1];\n const Th = rotlH(B0, B1, 1) ^ B[idx1];\n const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];\n for (let y = 0; y < 50; y += 10) {\n s[x + y] ^= Th;\n s[x + y + 1] ^= Tl;\n }\n }\n // Rho (ρ) and Pi (π)\n let curH = s[2];\n let curL = s[3];\n for (let t = 0; t < 24; t++) {\n const shift = SHA3_ROTL[t];\n const Th = rotlH(curH, curL, shift);\n const Tl = rotlL(curH, curL, shift);\n const PI = SHA3_PI[t];\n curH = s[PI];\n curL = s[PI + 1];\n s[PI] = Th;\n s[PI + 1] = Tl;\n }\n // Chi (χ)\n for (let y = 0; y < 50; y += 10) {\n for (let x = 0; x < 10; x++) B[x] = s[y + x];\n for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n }\n // Iota (ι)\n s[0] ^= SHA3_IOTA_H[round];\n s[1] ^= SHA3_IOTA_L[round];\n }\n clean(B);\n}\n\n/** Keccak sponge function. */\nexport class Keccak extends Hash<Keccak> implements HashXOF<Keccak> {\n protected state: Uint8Array;\n protected pos = 0;\n protected posOut = 0;\n protected finished = false;\n protected state32: Uint32Array;\n protected destroyed = false;\n\n public blockLen: number;\n public suffix: number;\n public outputLen: number;\n protected enableXOF = false;\n protected rounds: number;\n\n // NOTE: we accept arguments in bytes instead of bits here.\n constructor(\n blockLen: number,\n suffix: number,\n outputLen: number,\n enableXOF = false,\n rounds: number = 24\n ) {\n super();\n this.blockLen = blockLen;\n this.suffix = suffix;\n this.outputLen = outputLen;\n this.enableXOF = enableXOF;\n this.rounds = rounds;\n // Can be passed from user as dkLen\n anumber(outputLen);\n // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes\n // 0 < blockLen < 200\n if (!(0 < blockLen && blockLen < 200))\n throw new Error('only keccak-f1600 function is supported');\n this.state = new Uint8Array(200);\n this.state32 = u32(this.state);\n }\n clone(): Keccak {\n return this._cloneInto();\n }\n protected keccak(): void {\n swap32IfBE(this.state32);\n keccakP(this.state32, this.rounds);\n swap32IfBE(this.state32);\n this.posOut = 0;\n this.pos = 0;\n }\n update(data: Input): this {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { blockLen, state } = this;\n const len = data.length;\n for (let pos = 0; pos < len; ) {\n const take = Math.min(blockLen - this.pos, len - pos);\n for (let i = 0; i < take; i++) state[this.pos++] ^= data[pos++];\n if (this.pos === blockLen) this.keccak();\n }\n return this;\n }\n protected finish(): void {\n if (this.finished) return;\n this.finished = true;\n const { state, suffix, pos, blockLen } = this;\n // Do the padding\n state[pos] ^= suffix;\n if ((suffix & 0x80) !== 0 && pos === blockLen - 1) this.keccak();\n state[blockLen - 1] ^= 0x80;\n this.keccak();\n }\n protected writeInto(out: Uint8Array): Uint8Array {\n aexists(this, false);\n abytes(out);\n this.finish();\n const bufferOut = this.state;\n const { blockLen } = this;\n for (let pos = 0, len = out.length; pos < len; ) {\n if (this.posOut >= blockLen) this.keccak();\n const take = Math.min(blockLen - this.posOut, len - pos);\n out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);\n this.posOut += take;\n pos += take;\n }\n return out;\n }\n xofInto(out: Uint8Array): Uint8Array {\n // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF\n if (!this.enableXOF) throw new Error('XOF is not possible for this instance');\n return this.writeInto(out);\n }\n xof(bytes: number): Uint8Array {\n anumber(bytes);\n return this.xofInto(new Uint8Array(bytes));\n }\n digestInto(out: Uint8Array): Uint8Array {\n aoutput(out, this);\n if (this.finished) throw new Error('digest() was already called');\n this.writeInto(out);\n this.destroy();\n return out;\n }\n digest(): Uint8Array {\n return this.digestInto(new Uint8Array(this.outputLen));\n }\n destroy(): void {\n this.destroyed = true;\n clean(this.state);\n }\n _cloneInto(to?: Keccak): Keccak {\n const { blockLen, suffix, outputLen, rounds, enableXOF } = this;\n to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds);\n to.state32.set(this.state32);\n to.pos = this.pos;\n to.posOut = this.posOut;\n to.finished = this.finished;\n to.rounds = rounds;\n // Suffix can change in cSHAKE\n to.suffix = suffix;\n to.outputLen = outputLen;\n to.enableXOF = enableXOF;\n to.destroyed = this.destroyed;\n return to;\n }\n}\n\nconst gen = (suffix: number, blockLen: number, outputLen: number) =>\n createHasher(() => new Keccak(blockLen, suffix, outputLen));\n\n/** SHA3-224 hash function. */\nexport const sha3_224: CHash = /* @__PURE__ */ (() => gen(0x06, 144, 224 / 8))();\n/** SHA3-256 hash function. Different from keccak-256. */\nexport const sha3_256: CHash = /* @__PURE__ */ (() => gen(0x06, 136, 256 / 8))();\n/** SHA3-384 hash function. */\nexport const sha3_384: CHash = /* @__PURE__ */ (() => gen(0x06, 104, 384 / 8))();\n/** SHA3-512 hash function. */\nexport const sha3_512: CHash = /* @__PURE__ */ (() => gen(0x06, 72, 512 / 8))();\n\n/** keccak-224 hash function. */\nexport const keccak_224: CHash = /* @__PURE__ */ (() => gen(0x01, 144, 224 / 8))();\n/** keccak-256 hash function. Different from SHA3-256. */\nexport const keccak_256: CHash = /* @__PURE__ */ (() => gen(0x01, 136, 256 / 8))();\n/** keccak-384 hash function. */\nexport const keccak_384: CHash = /* @__PURE__ */ (() => gen(0x01, 104, 384 / 8))();\n/** keccak-512 hash function. */\nexport const keccak_512: CHash = /* @__PURE__ */ (() => gen(0x01, 72, 512 / 8))();\n\nexport type ShakeOpts = { dkLen?: number };\n\nconst genShake = (suffix: number, blockLen: number, outputLen: number) =>\n createXOFer<HashXOF<Keccak>, ShakeOpts>(\n (opts: ShakeOpts = {}) =>\n new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true)\n );\n\n/** SHAKE128 XOF with 128-bit security. */\nexport const shake128: CHashXO = /* @__PURE__ */ (() => genShake(0x1f, 168, 128 / 8))();\n/** SHAKE256 XOF with 256-bit security. */\nexport const shake256: CHashXO = /* @__PURE__ */ (() => genShake(0x1f, 136, 256 / 8))();\n","/**\n * Unified error handling for ERC-20 token operations.\n *\n * ERC20TokenError is independent of WalletError — the core package\n * shouldn't depend on wallet-engine. Wallet-engine integration wraps\n * these into WalletError when needed.\n */\n\nexport type ERC20TokenErrorCode =\n | \"token_not_deployed\" // Contract has no code on target chain\n | \"invalid_address\" // from/to/spender is not a valid address\n | \"invalid_amount\" // Amount format error (NaN, negative, too many decimals)\n | \"insufficient_allowance\" // allowance(owner, spender) < amount\n | \"insufficient_balance\" // balanceOf(owner) < amount\n | \"decimals_fetch_failed\" // Cannot read decimals from chain\n | \"token_info_fetch_failed\" // Cannot read token metadata\n | \"rpc_error\" // Underlying RPC error\n | \"encoding_error\" // ABI encoding failure\n | \"unknown_error\"; // Catch-all\n\n/** Human-readable messages for each error code */\nexport const ERC20_TOKEN_ERROR_MESSAGES: Record<ERC20TokenErrorCode, string> = {\n token_not_deployed: \"Token contract is not deployed on this chain.\",\n invalid_address: \"Address is not a valid EVM address.\",\n invalid_amount: \"Amount is invalid.\",\n insufficient_allowance:\n \"Insufficient allowance. Please approve the spender first.\",\n insufficient_balance: \"Insufficient token balance.\",\n decimals_fetch_failed: \"Failed to fetch token decimals from chain.\",\n token_info_fetch_failed: \"Failed to fetch token metadata from chain.\",\n rpc_error: \"RPC error occurred.\",\n encoding_error: \"Failed to encode ABI data.\",\n unknown_error: \"An unknown error occurred.\",\n};\n\nexport class ERC20TokenError extends Error {\n constructor(\n public readonly code: ERC20TokenErrorCode,\n message?: string,\n public readonly cause?: unknown,\n ) {\n super(message ?? ERC20_TOKEN_ERROR_MESSAGES[code]);\n this.name = \"ERC20TokenError\";\n }\n\n /** Check if this error has a specific code */\n hasCode(code: ERC20TokenErrorCode): boolean {\n return this.code === code;\n }\n}\n\n/** Type guard */\nexport function isERC20TokenError(e: unknown): e is ERC20TokenError {\n return e instanceof ERC20TokenError;\n}\n","/**\n * Amount formatting utilities for ERC-20 tokens.\n *\n * Provides parseUnits (human-readable → raw bigint) and\n * formatUnits (raw bigint → human-readable string).\n *\n * Handles any decimal count (0–255 as per ERC-20 spec).\n */\n\nimport { ERC20TokenError } from \"./errors\";\n\n/**\n * Convert a human-readable amount (string, number, or bigint) to the smallest unit.\n *\n * @example\n * parseUnits(\"1.5\", 6) → 1500000n (USDC: 1.5 → 1,500,000)\n * parseUnits(\"0.01\", 18) → 10000000000000000n\n * parseUnits(\"100\", 0) → 100n\n *\n * @throws {ERC20TokenError} on invalid input\n */\nexport function parseUnits(\n amount: string | number | bigint,\n decimals: number,\n): bigint {\n if (\n typeof decimals !== \"number\" ||\n !Number.isInteger(decimals) ||\n decimals < 0\n ) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Invalid decimals value: ${decimals}. Must be a non-negative integer.`,\n );\n }\n\n // Handle bigint directly (already in raw units)\n if (typeof amount === \"bigint\") {\n return amount;\n }\n\n let str: string;\n if (typeof amount === \"number\") {\n if (!Number.isFinite(amount)) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount is not a finite number: ${amount}`,\n );\n }\n if (amount < 0) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount must be non-negative, got: ${amount}`,\n );\n }\n str = amount.toString();\n } else {\n // string\n str = amount.trim();\n }\n\n if (str === \"\" || str === \".\") {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount string is empty or invalid: \"${amount}\"`,\n );\n }\n\n // Validate characters\n if (!/^[0-9]*\\.?[0-9]*$/.test(str)) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount contains invalid characters: \"${amount}\"`,\n );\n }\n\n // Handle negative (should not happen after trimming, but just in case)\n if (str.startsWith(\"-\")) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount must be non-negative, got: \"${amount}\"`,\n );\n }\n\n // Split into integer and fractional parts\n const dotIndex = str.indexOf(\".\");\n let integerPart: string;\n let fractionalPart: string;\n\n if (dotIndex === -1) {\n integerPart = str;\n fractionalPart = \"\";\n } else {\n integerPart = str.slice(0, dotIndex);\n fractionalPart = str.slice(dotIndex + 1);\n }\n\n // Check fractional length\n if (fractionalPart.length > decimals) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Amount \"${amount}\" has ${fractionalPart.length} decimal places, but max is ${decimals}.`,\n );\n }\n\n // Pad fractional part to required decimals\n fractionalPart = fractionalPart.padEnd(decimals, \"0\");\n\n // Remove leading zeros from integer part (but keep at least \"0\")\n integerPart = integerPart.replace(/^0+/, \"\") || \"0\";\n\n const combined = integerPart + fractionalPart;\n\n try {\n return BigInt(combined);\n } catch {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Failed to parse amount as bigint: \"${amount}\"`,\n );\n }\n}\n\n/**\n * Convert a raw bigint amount to a human-readable decimal string.\n *\n * @example\n * formatUnits(1500000n, 6) → \"1.5\"\n * formatUnits(10000000000000000n, 18) → \"0.01\"\n * formatUnits(0n, 18) → \"0\"\n */\nexport function formatUnits(amount: bigint, decimals: number): string {\n if (\n typeof decimals !== \"number\" ||\n !Number.isInteger(decimals) ||\n decimals < 0\n ) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Invalid decimals value: ${decimals}. Must be a non-negative integer.`,\n );\n }\n\n const negative = amount < 0n;\n const absAmount = negative ? -amount : amount;\n\n const str = absAmount.toString();\n const padded = str.padStart(decimals + 1, \"0\");\n\n const dotPos = padded.length - decimals;\n let integerPart = padded.slice(0, dotPos);\n let fractionalPart = padded.slice(dotPos);\n\n // Remove trailing zeros from fractional part\n fractionalPart = fractionalPart.replace(/0+$/, \"\");\n\n // Remove leading zeros (but keep at least \"0\")\n integerPart = integerPart.replace(/^0+/, \"\") || \"0\";\n\n if (fractionalPart.length === 0) {\n return negative ? `-${integerPart}` : integerPart;\n }\n\n return negative\n ? `-${integerPart}.${fractionalPart}`\n : `${integerPart}.${fractionalPart}`;\n}\n","// ── Account Abstraction (ERC-4337) ───────────────────────────────────\nexport * from \"./account-abstraction\";\nexport * from \"./address-validation\";\nexport * from \"./auto-reconnect\";\n// ── Chain Abstraction (Cross-Chain Intent Routing) ───────────────────\nexport * from \"./chain-abstraction\";\n// ── Chain Registry (SRS-007: Token Configs) ──────────────────────────\nexport { CHAINS } from \"./chain-registry\";\nexport * from \"./connector\";\nexport * from \"./connector-manager\";\nexport * from \"./constants\";\nexport * from \"./errors\";\nexport * from \"./fee-estimation\";\nexport * from \"./logger\";\nexport * from \"./notification\";\nexport * from \"./permissions\";\nexport * from \"./platform\";\nexport * from \"./resolver\";\nexport type { ChainInfo, Token } from \"./routes/types\";\nexport * from \"./rpc\";\nexport * from \"./session\";\n// ── Session Keys / Ephemeral Keys ────────────────────────────────────\nexport * from \"./session-keys\";\nexport * from \"./session-manager\";\n// ── Transaction Simulation (SRS-010) ──────────────────────────────────\nexport * from \"./simulation\";\nexport * from \"./storage\";\nexport * from \"./token\";\nexport * from \"./token-list\";\n\n// ── Token Price Oracle ──────────────────────────────────────────────\nexport { getNativeTokenPriceUsd } from \"./token-price\";\n","/**\n * Error types for Account Abstraction (ERC-4337) operations.\n *\n * Independent error class — core package does not depend on wallet-engine.\n */\n\nexport type AAErrorCode =\n | \"aa_unsupported_chain\" // Chain does not support ERC-4337\n | \"aa_no_bundler\" // No bundler URL configured\n | \"aa_no_paymaster\" // Paymaster not configured\n | \"aa_no_entry_point\" // EntryPoint address not found for chain\n | \"aa_no_factory\" // Factory address not found for chain\n | \"aa_account_not_deployed\" // Smart account not deployed\n | \"aa_account_already_deployed\" // Smart account already deployed\n | \"aa_invalid_owner\" // Invalid owner address\n | \"aa_user_op_failed\" // UserOperation failed on chain\n | \"aa_user_op_rejected\" // UserOperation rejected by bundler\n | \"aa_estimation_failed\" // Gas estimation failed\n | \"aa_signature_failed\" // UserOperation signing failed\n | \"aa_rpc_error\" // RPC call error\n | \"aa_invalid_input\" // Invalid input parameters\n | \"aa_unknown_account_type\" // Unsupported account type\n | \"aa_no_calls\" // No calls provided for UserOperation\n | \"aa_encode_error\" // ABI encode/decode error\n | \"aa_paymaster_rejected\" // Paymaster declined sponsorship\n | \"aa_receipt_timeout\" // UserOperation receipt not found after max retries\n | \"aa_unknown_error\"; // Catch-all\n\n/** Human-readable messages for each error code */\nexport const AA_ERROR_MESSAGES: Record<AAErrorCode, string> = {\n aa_unsupported_chain: \"Chain does not support ERC-4337 account abstraction.\",\n aa_no_bundler:\n \"Bundler URL not configured. Provide a bundler URL or bundlerClient.\",\n aa_no_paymaster: \"Paymaster not configured.\",\n aa_no_entry_point: \"EntryPoint contract address not found for this chain.\",\n aa_no_factory: \"Account factory contract address not found for this chain.\",\n aa_account_not_deployed: \"Smart account is not deployed on-chain.\",\n aa_account_already_deployed: \"Smart account is already deployed.\",\n aa_invalid_owner: \"Invalid owner address.\",\n aa_user_op_failed: \"UserOperation failed during execution.\",\n aa_user_op_rejected: \"UserOperation was rejected by the bundler.\",\n aa_estimation_failed: \"Failed to estimate gas for UserOperation.\",\n aa_signature_failed: \"Failed to sign UserOperation.\",\n aa_rpc_error: \"RPC call failed.\",\n aa_invalid_input: \"Invalid input parameters.\",\n aa_unknown_account_type: \"Unsupported account type.\",\n aa_no_calls: \"At least one call is required for the UserOperation.\",\n aa_encode_error: \"ABI encode/decode error.\",\n aa_paymaster_rejected: \"Paymaster declined to sponsor this UserOperation.\",\n aa_receipt_timeout: \"UserOperation receipt not found after maximum retries.\",\n aa_unknown_error: \"An unknown error occurred.\",\n};\n\nexport class AccountAbstractionError extends Error {\n constructor(\n public readonly code: AAErrorCode,\n message?: string,\n public readonly cause?: unknown,\n ) {\n super(message ?? AA_ERROR_MESSAGES[code]);\n this.name = \"AccountAbstractionError\";\n }\n\n hasCode(code: AAErrorCode): boolean {\n return this.code === code;\n }\n}\n\n/** Type guard */\nexport function isAAError(e: unknown): e is AccountAbstractionError {\n return e instanceof AccountAbstractionError;\n}\n","/**\n * Paymaster Integration for ERC-4337\n *\n * Provides Paymaster abstractions for gas sponsorship:\n * - Paymaster interface (pluggable)\n * - VerifyingPaymaster: API-based sponsorship via paymaster RPC\n * - PaymasterService: orchestrator for paymaster data injection\n *\n * @see docs/features/account-abstraction.md\n */\n\nimport { AccountAbstractionError } from \"./errors\";\nimport type {\n Address,\n Hex,\n PaymasterConfig,\n PaymasterData,\n Paymaster as PaymasterInterface,\n PaymasterType,\n UserOperation,\n} from \"./types\";\n\n// ─── Paymaster Service ─────────────────────────────────────────────────\n\nexport interface PaymasterServiceConfig {\n /** Paymaster RPC URL */\n url: string;\n /** Paymaster type */\n type: PaymasterType;\n /** Optional policy configuration */\n policy?: {\n allowedDapps?: string[];\n token?: Address;\n maxGasPerUserOp?: bigint;\n };\n /** Optional API key for authenticated paymaster */\n apiKey?: string;\n}\n\n/**\n * PaymasterService manages Paymaster interactions for ERC-4337 UserOperations.\n *\n * Supports:\n * - Verifying paymaster (API-based sponsorship approval)\n * - Sponsor paymaster (free gas for whitelisted dApps)\n * - Custom paymaster implementations\n */\nexport class PaymasterService implements PaymasterInterface {\n private config: PaymasterServiceConfig;\n private _sponsorInfo: string | null = null;\n\n constructor(config: PaymasterServiceConfig) {\n this.config = config;\n }\n\n /**\n * Get paymaster data for a UserOperation.\n *\n * For verifying paymasters, this calls the paymaster RPC's\n * pm_sponsorUserOperation method.\n *\n * @param userOp - The UserOperation to sponsor\n * @returns Paymaster data including paymasterAndData hex\n */\n async getPaymasterData(\n userOp: Partial<UserOperation>,\n ): Promise<PaymasterData> {\n switch (this.config.type) {\n case \"verifying\":\n return this.getVerifyingPaymasterData(userOp);\n case \"sponsor\":\n return this.getSponsorPaymasterData(userOp);\n case \"token\":\n return this.getTokenPaymasterData(userOp);\n case \"custom\":\n return this.getCustomPaymasterData(userOp);\n default:\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Unknown paymaster type: ${this.config.type}`,\n );\n }\n }\n\n /**\n * Check if a UserOperation is eligible for sponsorship.\n *\n * @param userOp - The UserOperation to check\n * @returns true if the paymaster would sponsor this operation\n */\n async isSponsored(userOp: Partial<UserOperation>): Promise<boolean> {\n try {\n const data = await this.getPaymasterData(userOp);\n return data.paymasterAndData !== \"0x\" && data.paymasterAndData.length > 2;\n } catch {\n return false;\n }\n }\n\n /**\n * Get human-readable sponsorship info.\n */\n get sponsorInfo(): string | null {\n return this._sponsorInfo;\n }\n\n // ── Verifying Paymaster ─────────────────────────────────────────\n\n /**\n * Get paymaster data using a verifying paymaster.\n * Calls the paymaster RPC's pm_sponsorUserOperation method.\n */\n private async getVerifyingPaymasterData(\n userOp: Partial<UserOperation>,\n ): Promise<PaymasterData> {\n const serializedOp = this.serializeForPaymaster(userOp);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.config.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.apiKey}`;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(this.config.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"pm_sponsorUserOperation\",\n params: [serializedOp],\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Paymaster returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: {\n paymasterAndData?: Hex;\n sponsor?: { name?: string };\n };\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Paymaster error: ${json.error.message}`,\n { code: json.error.code },\n );\n }\n\n const result = json.result;\n if (!result?.paymasterAndData || result.paymasterAndData === \"0x\") {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n \"Paymaster did not return paymasterAndData\",\n );\n }\n\n this._sponsorInfo = result.sponsor?.name ?? \"Sponsored by Paymaster\";\n\n return {\n paymasterAndData: result.paymasterAndData,\n sponsorInfo: this._sponsorInfo,\n };\n } catch (error) {\n if (error instanceof AccountAbstractionError) throw error;\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n \"Failed to get paymaster data\",\n error,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // ── Sponsor Paymaster ───────────────────────────────────────────\n\n /**\n * Get paymaster data for a simple sponsor paymaster.\n * Uses a static or policy-based sponsorship.\n */\n private async getSponsorPaymasterData(\n userOp: Partial<UserOperation>,\n ): Promise<PaymasterData> {\n const serializedOp = this.serializeForPaymaster(userOp);\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(this.config.url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"pm_getPaymasterStakeData\",\n params: [serializedOp],\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Sponsor paymaster returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: { paymasterAndData: Hex };\n error?: { code: number; message: string };\n };\n\n if (json.error || !json.result) {\n // If sponsor paymaster fails, try verifying endpoint\n return this.getVerifyingPaymasterData(userOp);\n }\n\n this._sponsorInfo = \"Gas sponsored by dApp\";\n return {\n paymasterAndData: json.result.paymasterAndData,\n sponsorInfo: this._sponsorInfo,\n };\n } catch (error) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n \"Sponsor paymaster failed\",\n error,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // ── Token Paymaster ─────────────────────────────────────────────\n\n /**\n * Get paymaster data for a token paymaster.\n * Requires an ERC-20 token for gas payment.\n */\n private async getTokenPaymasterData(\n userOp: Partial<UserOperation>,\n ): Promise<PaymasterData> {\n // Token paymaster implementations vary.\n // This calls the standard pm_sponsorUserOperation with token info.\n const serializedOp = this.serializeForPaymaster(userOp);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.config.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.apiKey}`;\n }\n\n // If a specific token is configured, pass it as an extra param\n const extraParams: Record<string, unknown> = {};\n if (this.config.policy?.token) {\n extraParams.token = this.config.policy.token;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(this.config.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"pm_sponsorUserOperation\",\n params: [serializedOp, this.config.policy?.token],\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Token paymaster returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: { paymasterAndData: Hex };\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new AccountAbstractionError(\n \"aa_paymaster_rejected\",\n `Token paymaster error: ${json.error.message}`,\n );\n }\n\n this._sponsorInfo = this.config.policy?.token\n ? `Gas paid with ERC-20 token`\n : \"Gas sponsored\";\n\n return {\n paymasterAndData: json.result?.paymasterAndData ?? \"0x\",\n sponsorInfo: this._sponsorInfo,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // ── Custom Paymaster ────────────────────────────────────────────\n\n /**\n * Get paymaster data using a custom paymaster implementation.\n * Delegates to the configured URL which should implement the paymaster RPC.\n */\n private async getCustomPaymasterData(\n userOp: Partial<UserOperation>,\n ): Promise<PaymasterData> {\n // Custom paymasters follow the same RPC pattern by default\n return this.getVerifyingPaymasterData(userOp);\n }\n\n // ── Helpers ─────────────────────────────────────────────────────\n\n /**\n * Serialize a partial UserOperation for paymaster RPC calls.\n * Converts bigint fields to hex strings.\n */\n private serializeForPaymaster(\n userOp: Partial<UserOperation>,\n ): Record<string, string> {\n return {\n sender: userOp.sender ?? \"0x0000000000000000000000000000000000000000\",\n nonce: `0x${(userOp.nonce ?? 0n).toString(16)}`,\n initCode: userOp.initCode ?? \"0x\",\n callData: userOp.callData ?? \"0x\",\n // v0.7: use accountGasLimits\n accountGasLimits:\n userOp.accountGasLimits ??\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n preVerificationGas: `0x${(userOp.preVerificationGas ?? 0n).toString(16)}`,\n maxFeePerGas: `0x${(userOp.maxFeePerGas ?? 0n).toString(16)}`,\n maxPriorityFeePerGas: `0x${(userOp.maxPriorityFeePerGas ?? 0n).toString(16)}`,\n paymasterAndData: userOp.paymasterAndData ?? \"0x\",\n signature: userOp.signature ?? \"0x\",\n };\n }\n}\n\n// ─── Factory ───────────────────────────────────────────────────────────\n\n/**\n * Create a PaymasterService from a PaymasterConfig.\n *\n * @param config - Paymaster configuration\n * @returns PaymasterService instance\n */\nexport function createPaymasterService(\n config: PaymasterConfig,\n): PaymasterService {\n return new PaymasterService({\n url: config.url,\n type: config.type,\n policy: config.policy,\n });\n}\n","/**\n * ERC-4337 Account Abstraction Types\n *\n * Defines the type hierarchy for Smart Contract Wallet management,\n * UserOperation construction, Paymaster integration, and batch transactions.\n *\n * @see docs/features/account-abstraction.md\n */\n\n// ─── Hex Helpers ────────────────────────────────────────────────────────\n\nexport type Address = `0x${string}`;\nexport type Hex = `0x${string}`;\n\n// ─── UserOperation (ERC-4337 v0.7) ──────────────────────────────────────\n\n/**\n * ERC-4337 UserOperation structure.\n * Follows the v0.7 spec: accountGasLimits replaces separate callGasLimit/verificationGasLimit,\n * and paymasterPostOpGasLimit is bundled into paymasterData.\n */\nexport interface UserOperation {\n sender: Address;\n nonce: bigint;\n initCode: Hex;\n callData: Hex;\n /** ABI-encoded callGasLimit + verificationGasLimit (v0.7) */\n accountGasLimits: Hex;\n preVerificationGas: bigint;\n maxFeePerGas: bigint;\n maxPriorityFeePerGas: bigint;\n /** ABI-encoded paymaster + paymasterVerificationGasLimit + paymasterPostOpGasLimit + paymasterData */\n paymasterAndData: Hex;\n signature: Hex;\n}\n\n// ─── Call (Single Operation within a UserOp) ────────────────────────────\n\nexport interface Call {\n /** Target contract address */\n to: Address;\n /** Value in wei (0n for pure function calls) */\n value: bigint;\n /** Encoded calldata */\n data: Hex;\n}\n\n// ─── Smart Account Configuration ────────────────────────────────────────\n\nexport type AccountType = \"simple\" | \"light\" | \"kernel\" | \"safe\";\n\nexport interface SmartAccountConfig {\n /** Owner address (typically an EOA) */\n owner: Address;\n /** Optional salt for CREATE2 deterministic address */\n salt?: bigint;\n /** Account implementation type */\n accountType: AccountType;\n /** ERC-4337 EntryPoint contract address */\n entryPoint: Address;\n /** Chain ID (CAIP-2 format, e.g. \"eip155:1\") */\n chainId: string;\n}\n\nexport interface SmartAccountInfo {\n /** Deterministic counterfactual address */\n address: Address;\n /** Whether the contract is deployed on-chain */\n isDeployed: boolean;\n /** Account type */\n accountType: AccountType;\n /** Owner address */\n owner: Address;\n}\n\n// ─── Bundler / RPC Types ────────────────────────────────────────────────\n\nexport interface BundlerClient {\n /** RPC endpoint URL */\n url: string;\n /** Optional API key for authenticated bundler services */\n apiKey?: string;\n}\n\nexport interface UserOperationResponse {\n /** UserOp hash (returned by eth_sendUserOperation) */\n userOpHash: Hex;\n /** Smart account sender address */\n sender: Address;\n /** UserOp nonce */\n nonce: bigint;\n}\n\nexport interface UserOperationReceipt {\n userOpHash: Hex;\n entryPoint: Address;\n sender: Address;\n nonce: bigint;\n paymaster?: Address;\n actualGasUsed: bigint;\n actualGasCost: bigint;\n success: boolean;\n /** Transaction receipt of the HandleOps bundle */\n transactionHash: Hex;\n /** Array of logs emitted during execution */\n logs: Log[];\n}\n\nexport interface Log {\n address: Address;\n topics: Hex[];\n data: Hex;\n}\n\nexport interface UserOperationGasEstimate {\n callGasLimit: bigint;\n verificationGasLimit: bigint;\n preVerificationGas: bigint;\n /** v0.7 bundlers may return accountGasLimits */\n accountGasLimits?: Hex;\n}\n\n// ─── Paymaster Types ────────────────────────────────────────────────────\n\nexport type PaymasterType = \"verifying\" | \"token\" | \"sponsor\" | \"custom\";\n\nexport interface PaymasterConfig {\n type: PaymasterType;\n /** Paymaster RPC URL */\n url: string;\n /** Optional policy configuration */\n policy?: {\n /** Whitelisted dApp origins */\n allowedDapps?: string[];\n /** ERC-20 token address for token paymaster */\n token?: Address;\n /** Maximum gas per UserOperation */\n maxGasPerUserOp?: bigint;\n };\n}\n\nexport interface PaymasterData {\n /** The paymasterAndData hex to inject into UserOperation */\n paymasterAndData: Hex;\n /** Human-readable sponsorship info */\n sponsorInfo?: string;\n}\n\nexport interface Paymaster {\n /** Get paymaster data for a UserOperation */\n getPaymasterData(userOp: Partial<UserOperation>): Promise<PaymasterData>;\n /** Verify if a UserOperation is eligible for sponsorship */\n isSponsored(userOp: Partial<UserOperation>): Promise<boolean>;\n}\n\n// ─── Send UserOperation Options ─────────────────────────────────────────\n\nexport interface SendUserOpOptions {\n /** Optional gas overrides */\n gasOverrides?: {\n callGasLimit?: bigint;\n verificationGasLimit?: bigint;\n preVerificationGas?: bigint;\n maxFeePerGas?: bigint;\n maxPriorityFeePerGas?: bigint;\n };\n /** Optional paymaster configuration */\n paymaster?: PaymasterConfig;\n /** Whether to skip deploy (for already deployed accounts) */\n skipDeploy?: boolean;\n}\n\n// ─── EntryPoint Address Constants ───────────────────────────────────────\n\n/**\n * ERC-4337 EntryPoint v0.6 contract addresses.\n * https://github.com/eth-infinitism/account-abstraction\n */\nexport const ENTRY_POINT_V0_6: Address =\n \"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789\";\n\n/**\n * ERC-4337 EntryPoint v0.7 contract address (same on all chains).\n */\nexport const ENTRY_POINT_V0_7: Address =\n \"0x0000000071727De22E5E9d8BAf0edAc6f37da032\";\n\n/**\n * Default EntryPoint address (v0.7).\n */\nexport const DEFAULT_ENTRY_POINT = ENTRY_POINT_V0_7;\n\n// ─── SimpleAccount Factory Addresses ────────────────────────────────────\n\n/**\n * SimpleAccount Factory address (eth-infinitism).\n * Deployed at the same address on all supported chains via CREATE2.\n */\nexport const SIMPLE_ACCOUNT_FACTORY: Address =\n \"0x9406Cc6185a346906296840746125a0E44976454\";\n\n// ─── Gas Budget Defaults ────────────────────────────────────────────────\n\n/** Default call gas limit for UserOperations */\nexport const DEFAULT_CALL_GAS_LIMIT = 100_000n;\n\n/** Default verification gas limit for UserOperations */\nexport const DEFAULT_VERIFICATION_GAS_LIMIT = 100_000n;\n\n/** Default pre-verification gas for UserOperations */\nexport const DEFAULT_PRE_VERIFICATION_GAS = 50_000n;\n\n// ─── Chain AA Support ───────────────────────────────────────────────────\n\n/**\n * Chains known to support ERC-4337 AA (EntryPoint deployed).\n * Keyed by CAIP-2 chain ID.\n */\nexport const AA_SUPPORTED_CHAINS: Record<\n string,\n { entryPoint: Address; factory: Address }\n> = {\n \"eip155:1\": { entryPoint: ENTRY_POINT_V0_7, factory: SIMPLE_ACCOUNT_FACTORY }, // Ethereum\n \"eip155:137\": {\n entryPoint: ENTRY_POINT_V0_6,\n factory: SIMPLE_ACCOUNT_FACTORY,\n }, // Polygon\n \"eip155:10\": {\n entryPoint: ENTRY_POINT_V0_6,\n factory: SIMPLE_ACCOUNT_FACTORY,\n }, // Optimism\n \"eip155:42161\": {\n entryPoint: ENTRY_POINT_V0_6,\n factory: SIMPLE_ACCOUNT_FACTORY,\n }, // Arbitrum\n \"eip155:8453\": {\n entryPoint: ENTRY_POINT_V0_7,\n factory: SIMPLE_ACCOUNT_FACTORY,\n }, // Base\n \"eip155:11155111\": {\n entryPoint: ENTRY_POINT_V0_7,\n factory: SIMPLE_ACCOUNT_FACTORY,\n }, // Sepolia\n};\n","/**\n * UserOperation Builder & Signer\n *\n * Provides utilities for constructing, signing, and sending ERC-4337\n * UserOperations without depending on @account-abstraction/sdk.\n *\n * @see docs/features/account-abstraction.md\n */\n\nimport { AccountAbstractionError } from \"./errors\";\nimport {\n type Address,\n type BundlerClient,\n type Call,\n DEFAULT_CALL_GAS_LIMIT,\n DEFAULT_PRE_VERIFICATION_GAS,\n DEFAULT_VERIFICATION_GAS_LIMIT,\n type Hex,\n type UserOperation,\n type UserOperationGasEstimate,\n type UserOperationReceipt,\n type UserOperationResponse,\n} from \"./types\";\n\n// ─── EIP-712 Domain & Types for UserOperation ──────────────────────────\n\n/**\n * EIP-712 typed data for UserOperation signing.\n * Used for eth_signTypedData / eth_signTypedData_v4.\n */\nexport const USER_OP_EIP712_DOMAIN = (\n chainId: number,\n verifyingContract: Address,\n) => ({\n name: \"Account\",\n version: \"1\",\n chainId,\n verifyingContract,\n});\n\n/**\n * EIP-712 type definitions for UserOperation.\n * Matches eth-infinitism's entry point contracts.\n */\nexport const USER_OP_EIP712_TYPES = {\n UserOperation: [\n { name: \"sender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"initCode\", type: \"bytes\" },\n { name: \"callData\", type: \"bytes\" },\n { name: \"accountGasLimits\", type: \"bytes32\" },\n { name: \"preVerificationGas\", type: \"uint256\" },\n { name: \"maxFeePerGas\", type: \"uint256\" },\n { name: \"maxPriorityFeePerGas\", type: \"uint256\" },\n { name: \"paymasterAndData\", type: \"bytes\" },\n { name: \"signature\", type: \"bytes\" },\n ],\n};\n\n/**\n * EIP-712 type definitions for UserOperation (v0.6 format).\n * Uses callGasLimit and verificationGasLimit separately instead of accountGasLimits.\n */\nexport const USER_OP_EIP712_TYPES_V06 = {\n UserOperation: [\n { name: \"sender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"initCode\", type: \"bytes\" },\n { name: \"callData\", type: \"bytes\" },\n { name: \"callGasLimit\", type: \"uint256\" },\n { name: \"verificationGasLimit\", type: \"uint256\" },\n { name: \"preVerificationGas\", type: \"uint256\" },\n { name: \"maxFeePerGas\", type: \"uint256\" },\n { name: \"maxPriorityFeePerGas\", type: \"uint256\" },\n { name: \"paymasterAndData\", type: \"bytes\" },\n { name: \"signature\", type: \"bytes\" },\n ],\n};\n\n// ─── Build ─────────────────────────────────────────────────────────────\n\n/**\n * Build a partial UserOperation from the given fields.\n *\n * @param params - UserOperation fields\n * @returns UserOperation with defaults applied for any missing fields\n */\nexport function buildUserOperation(\n params: Partial<UserOperation>,\n): UserOperation {\n return {\n sender: params.sender ?? \"0x\",\n nonce: params.nonce ?? 0n,\n initCode: params.initCode ?? \"0x\",\n callData: params.callData ?? \"0x\",\n accountGasLimits:\n params.accountGasLimits ??\n encodeGasLimits(DEFAULT_VERIFICATION_GAS_LIMIT, DEFAULT_CALL_GAS_LIMIT),\n preVerificationGas:\n params.preVerificationGas ?? DEFAULT_PRE_VERIFICATION_GAS,\n maxFeePerGas: params.maxFeePerGas ?? 0n,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas ?? 0n,\n paymasterAndData: params.paymasterAndData ?? \"0x\",\n signature: params.signature ?? \"0x\",\n };\n}\n\n/**\n * Build the callData for a UserOperation from one or more calls.\n *\n * For a single call, encodes as execute(to, value, data).\n * For multiple calls, encodes as executeBatch(to[], value[], data[]).\n *\n * @param calls - Array of calls to include\n * @returns Encoded calldata\n */\nexport function buildCallData(calls: Call[]): Hex {\n if (!calls.length) {\n throw new AccountAbstractionError(\"aa_no_calls\");\n }\n\n if (calls.length === 1) {\n return encodeExecute(calls[0].to, calls[0].value, calls[0].data);\n }\n\n return encodeExecuteBatch(calls);\n}\n\n/**\n * Encode a single execute call for SimpleAccount.\n */\nfunction encodeExecute(to: Address, value: bigint, data: Hex): Hex {\n const selector = \"0xb61d27f6\"; // execute(address,uint256,bytes)\n const toArg = to.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\");\n const valueArg = value.toString(16).padStart(64, \"0\");\n\n // Dynamic bytes encoding: offset(32B) + length(32B) + data\n const rawData = data.replace(\"0x\", \"\");\n const dataLen = rawData.length / 2;\n\n // ABI encoding for execute(address,uint256,bytes):\n // Head: to(32B) | value(32B) | offset_to_bytes(32B)\n // Tail: length(32B) | data(padded to 32B)\n // Offset = 3 head params × 32 bytes = 96\n const bytesOffset = (96).toString(16).padStart(64, \"0\");\n const dataLenHex = dataLen.toString(16).padStart(64, \"0\");\n\n // Pad data to 32-byte boundary\n const paddedLen = Math.ceil(rawData.length / 64) * 64;\n const paddedData = rawData.padEnd(paddedLen, \"0\");\n\n return `${selector}${toArg}${valueArg}${bytesOffset}${dataLenHex}${paddedData}` as Hex;\n}\n\n/**\n * Encode a batch execute call for SimpleAccount.\n * executeBatch(address[],uint256[],bytes[])\n */\nfunction encodeExecuteBatch(calls: Call[]): Hex {\n const selector = \"0x47e1da2a\";\n const n = calls.length;\n const nWord = n.toString(16).padStart(64, \"0\");\n\n // Build arrays\n const toArray =\n nWord +\n calls\n .map((c) => c.to.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\"))\n .join(\"\");\n const valuesArray =\n nWord + calls.map((c) => c.value.toString(16).padStart(64, \"0\")).join(\"\");\n\n // Datas: array of dynamic bytes\n const datasEntries = calls\n .map((c) => {\n const rawData = c.data.replace(\"0x\", \"\");\n const len = rawData.length / 2;\n return len.toString(16).padStart(64, \"0\") + rawData;\n })\n .join(\"\");\n const datasArray = nWord + datasEntries;\n\n const toLen = 32 + n * 32;\n const valuesLen = 32 + n * 32;\n const datasLen = 32 + datasEntries.length / 2;\n\n const headSize = 32 * 3; // 3 offsets\n const toOffset = headSize;\n const valuesOffset = headSize + toLen;\n const datasOffset = headSize + toLen + valuesLen;\n\n return (`${selector}` +\n toOffset.toString(16).padStart(64, \"0\") +\n valuesOffset.toString(16).padStart(64, \"0\") +\n datasOffset.toString(16).padStart(64, \"0\") +\n toArray +\n valuesArray +\n datasArray) as Hex;\n}\n\n// ─── Sign ──────────────────────────────────────────────────────────────\n\n/**\n * Compute the EIP-712 hash of a UserOperation for signing.\n *\n * @param userOp - The UserOperation to hash\n * @param entryPoint - EntryPoint contract address\n * @param chainId - EVM chain ID\n * @returns The EIP-712 typed data hash\n */\n/**\n * EIP-712 domain separator for UserOperation hashing.\n */\nfunction computeDomainSeparator(\n entryPoint: Address,\n chainId: number,\n): Uint8Array {\n const { concatBytes: concat } = (() => {\n return {\n concatBytes: (...arrays: Uint8Array[]) => {\n const total = arrays.reduce((a, b) => a + b.length, 0);\n const result = new Uint8Array(total);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n },\n };\n })();\n\n const toBytes = (hex: Hex): Uint8Array => {\n const raw = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const bytes = new Uint8Array(raw.length / 2);\n for (let i = 0; i < raw.length; i += 2) {\n bytes[i / 2] = parseInt(raw.slice(i, i + 2), 16);\n }\n return bytes;\n };\n\n const stringToBytes = (s: string): Uint8Array => new TextEncoder().encode(s);\n const padded32 = (b: Uint8Array): Uint8Array => {\n if (b.length >= 32) return b.slice(0, 32);\n const result = new Uint8Array(32);\n result.set(b);\n return result;\n };\n\n // EIP-712 domain: keccak256(abi.encode(\n // keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n // keccak256(\"Account\"), keccak256(\"1\"),\n // uint256(chainId), address(entryPoint)\n // ))\n const domainTypeHash = keccak256Sync(\n stringToBytes(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\",\n ),\n );\n const nameHash = keccak256Sync(stringToBytes(\"Account\"));\n const versionHash = keccak256Sync(stringToBytes(\"1\"));\n\n const chainIdBytes = new Uint8Array(32);\n const chainIdBigInt = BigInt(chainId);\n const chainIdHex = chainIdBigInt.toString(16).padStart(64, \"0\");\n const chainIdArray = toBytes(`0x${chainIdHex}`);\n\n const entryPointBytes = toBytes(entryPoint);\n const entryPointPadded = new Uint8Array(32);\n entryPointPadded.set(entryPointBytes, 12); // address is right-aligned (last 20 bytes)\n\n return keccak256Sync(\n concat(\n domainTypeHash,\n nameHash,\n versionHash,\n chainIdArray,\n entryPointPadded,\n ),\n );\n}\n\nexport function hashUserOperation(\n userOp: UserOperation,\n entryPoint: Address,\n chainId: number,\n): Hex {\n const {\n sender,\n nonce,\n initCode,\n callData,\n accountGasLimits,\n preVerificationGas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n paymasterAndData,\n } = userOp;\n\n const packed = packUserOp({\n sender,\n nonce,\n initCode,\n callData,\n accountGasLimits,\n preVerificationGas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n paymasterAndData,\n });\n\n // Inner userOp hash\n const userOpHash = keccak256Sync(packed);\n\n // EIP-712 domain separator\n const domainSeparator = computeDomainSeparator(entryPoint, chainId);\n\n // Combined: \\x19\\x01 || domainSeparator || userOpHash\n const { concatBytes } = (() => {\n return {\n concatBytes: (...arrays: Uint8Array[]) => {\n const total = arrays.reduce((a, b) => a + b.length, 0);\n const result = new Uint8Array(total);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n },\n };\n })();\n\n const prefix = new Uint8Array([0x19, 0x01]);\n const finalHash = keccak256Sync(\n concatBytes(prefix, domainSeparator, userOpHash),\n );\n\n const { bytesToHex } = requireBytesToHex();\n return `0x${bytesToHex(finalHash)}` as Hex;\n}\n\n/**\n * Pack UserOperation fields into a single bytes hash.\n * Follows the eth-infinitism pattern of hashing all fields together.\n */\nfunction packUserOp(\n userOp: Pick<\n UserOperation,\n | \"sender\"\n | \"nonce\"\n | \"initCode\"\n | \"callData\"\n | \"accountGasLimits\"\n | \"preVerificationGas\"\n | \"maxFeePerGas\"\n | \"maxPriorityFeePerGas\"\n | \"paymasterAndData\"\n >,\n): Uint8Array {\n const { concatBytes, bytesToHex } = (() => {\n // Synchronous utilities\n const encoder = new TextEncoder();\n return {\n concatBytes: (...arrays: Uint8Array[]) => {\n const total = arrays.reduce((a, b) => a + b.length, 0);\n const result = new Uint8Array(total);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n },\n bytesToHex: (bytes: Uint8Array) => {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n },\n };\n })();\n\n const toBytes = (hex: Hex): Uint8Array => {\n const raw = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const bytes = new Uint8Array(raw.length / 2);\n for (let i = 0; i < raw.length; i += 2) {\n bytes[i / 2] = parseInt(raw.slice(i, i + 2), 16);\n }\n return bytes;\n };\n\n const bigintTo32Bytes = (n: bigint): Uint8Array => {\n const hex = n.toString(16).padStart(64, \"0\");\n return toBytes(`0x${hex}`);\n };\n\n return concatBytes(\n toBytes(userOp.sender),\n bigintTo32Bytes(userOp.nonce),\n keccak256Sync(toBytes(userOp.initCode)),\n keccak256Sync(toBytes(userOp.callData)),\n toBytes(userOp.accountGasLimits),\n bigintTo32Bytes(userOp.preVerificationGas),\n bigintTo32Bytes(userOp.maxFeePerGas),\n bigintTo32Bytes(userOp.maxPriorityFeePerGas),\n keccak256Sync(toBytes(userOp.paymasterAndData)),\n );\n}\n\n/**\n * Synchronous keccak256 hash using @noble/hashes.\n */\nfunction keccak256Sync(data: Uint8Array): Uint8Array {\n // Inline to avoid dynamic import constraints — we use a pure JS fallback\n // but if @noble/hashes is available it will be used\n const { keccak_256 } = requireKeccak();\n return keccak_256(data);\n}\n\n/**\n * Memoized require for keccak256 to avoid re-importing.\n */\nlet _keccakFn: ((data: Uint8Array) => Uint8Array) | null = null;\n\nfunction requireKeccak(): { keccak_256: (data: Uint8Array) => Uint8Array } {\n if (_keccakFn) return { keccak_256: _keccakFn };\n\n // Try @noble/hashes first\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const noble = require(\"@noble/hashes/sha3\");\n _keccakFn = noble.keccak_256;\n } catch {\n throw new AccountAbstractionError(\n \"aa_encode_error\",\n \"keccak256 not available. @noble/hashes is required.\",\n );\n }\n\n return { keccak_256: _keccakFn! };\n}\n\nlet _bytesToHexFn: ((bytes: Uint8Array) => string) | null = null;\n\nfunction requireBytesToHex(): { bytesToHex: (bytes: Uint8Array) => string } {\n if (_bytesToHexFn) return { bytesToHex: _bytesToHexFn };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const noble = require(\"@noble/hashes/utils\");\n _bytesToHexFn = noble.bytesToHex;\n } catch {\n _bytesToHexFn = (bytes: Uint8Array) =>\n Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n return { bytesToHex: _bytesToHexFn! };\n}\n\n/**\n * Encode account gas limits as a packed 32-byte value (v0.7).\n */\nexport function encodeGasLimits(\n verificationGasLimit: bigint,\n callGasLimit: bigint,\n): Hex {\n const vglHex = verificationGasLimit.toString(16).padStart(32, \"0\");\n const cglHex = callGasLimit.toString(16).padStart(32, \"0\");\n return `0x${vglHex}${cglHex}` as Hex;\n}\n\n// ─── Sign ──────────────────────────────────────────────────────────────\n\n/**\n * Sign a UserOperation using EIP-191 or EIP-712.\n *\n * For SimpleAccount, the signature is a standard ECDSA signature.\n *\n * @param userOp - The UserOperation to sign (without signature)\n * @param signer - A function that signs arbitrary data (e.g. personal_sign)\n * @param entryPoint - EntryPoint contract address\n * @param chainId - EVM chain ID\n * @returns The UserOperation with signature field filled\n */\nexport async function signUserOperation(\n userOp: UserOperation,\n signer: (hash: Hex) => Promise<Hex> | Hex,\n entryPoint: Address,\n chainId: number,\n): Promise<UserOperation> {\n try {\n const hash = hashUserOperation(userOp, entryPoint, chainId);\n\n // Wrap the hash in the EIP-191 personal_sign format\n const messageHash = await wrapEIP191(hash);\n\n const signature = await signer(messageHash);\n\n return {\n ...userOp,\n signature,\n };\n } catch (error) {\n throw new AccountAbstractionError(\n \"aa_signature_failed\",\n \"Failed to sign UserOperation\",\n error,\n );\n }\n}\n\n/**\n * Wrap data in EIP-191 personal_sign format:\n * \\x19Ethereum Signed Message:\\n + len(message) + message\n */\nasync function wrapEIP191(hash: Hex): Promise<Hex> {\n const rawMessage = hash.startsWith(\"0x\") ? hash.slice(2) : hash;\n const prefix = `\\x19Ethereum Signed Message:\\n${rawMessage.length / 2}`;\n const encoder = new TextEncoder();\n const prefixBytes = encoder.encode(prefix);\n const messageBytes = new Uint8Array(rawMessage.length / 2);\n for (let i = 0; i < rawMessage.length; i += 2) {\n messageBytes[i / 2] = parseInt(rawMessage.slice(i, i + 2), 16);\n }\n\n const combined = new Uint8Array(prefixBytes.length + messageBytes.length);\n combined.set(prefixBytes);\n combined.set(messageBytes, prefixBytes.length);\n\n const { keccak_256 } = await import(\"@noble/hashes/sha3\");\n const { bytesToHex } = await import(\"@noble/hashes/utils\");\n return `0x${bytesToHex(keccak_256(combined))}` as Hex;\n}\n\n// ─── Send ──────────────────────────────────────────────────────────────\n\n/**\n * Send a UserOperation to a bundler RPC endpoint.\n *\n * @param userOp - The signed UserOperation\n * @param bundlerUrl - Bundler RPC URL\n * @param entryPoint - EntryPoint contract address\n * @returns UserOperation response with userOpHash\n */\nexport async function sendUserOperation(\n userOp: UserOperation,\n bundlerUrl: string,\n entryPoint: Address,\n): Promise<UserOperationResponse> {\n if (!bundlerUrl) {\n throw new AccountAbstractionError(\"aa_no_bundler\");\n }\n\n // Serialize for RPC: bigint → hex string\n const serializedOp = {\n sender: userOp.sender,\n nonce: `0x${userOp.nonce.toString(16)}`,\n initCode: userOp.initCode,\n callData: userOp.callData,\n accountGasLimits: userOp.accountGasLimits,\n preVerificationGas: `0x${userOp.preVerificationGas.toString(16)}`,\n maxFeePerGas: `0x${userOp.maxFeePerGas.toString(16)}`,\n maxPriorityFeePerGas: `0x${userOp.maxPriorityFeePerGas.toString(16)}`,\n paymasterAndData: userOp.paymasterAndData,\n signature: userOp.signature,\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 30_000);\n\n try {\n let response: Response;\n try {\n response = await fetch(bundlerUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"eth_sendUserOperation\",\n params: [serializedOp, entryPoint],\n }),\n signal: controller.signal,\n });\n } catch {\n throw new AccountAbstractionError(\n \"aa_user_op_rejected\",\n \"Failed to connect to bundler\",\n );\n }\n\n if (!response.ok) {\n throw new AccountAbstractionError(\n \"aa_user_op_rejected\",\n `Bundler returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: Hex;\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new AccountAbstractionError(\n \"aa_user_op_rejected\",\n json.error.message,\n { code: json.error.code },\n );\n }\n\n return {\n userOpHash: json.result as Hex,\n sender: userOp.sender,\n nonce: userOp.nonce,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n// ─── Estimate Gas ──────────────────────────────────────────────────────\n\n/**\n * Estimate gas for a UserOperation via the bundler's eth_estimateUserOperationGas.\n *\n * @param userOp - Partial UserOperation (signature not required)\n * @param entryPoint - EntryPoint contract address\n * @param bundlerUrl - Bundler RPC URL\n * @returns Gas estimates (callGasLimit, verificationGasLimit, preVerificationGas)\n */\nexport async function estimateUserOperationGas(\n userOp: Partial<UserOperation>,\n entryPoint: Address,\n bundlerUrl: string,\n): Promise<UserOperationGasEstimate> {\n if (!bundlerUrl) {\n throw new AccountAbstractionError(\"aa_no_bundler\");\n }\n\n // Serialize for RPC\n const serializedOp = {\n sender: userOp.sender ?? \"0x0000000000000000000000000000000000000000\",\n nonce: `0x${(userOp.nonce ?? 0n).toString(16)}`,\n initCode: userOp.initCode ?? \"0x\",\n callData: userOp.callData ?? \"0x\",\n accountGasLimits:\n userOp.accountGasLimits ??\n `0x${DEFAULT_VERIFICATION_GAS_LIMIT.toString(16).padStart(32, \"0\")}${DEFAULT_CALL_GAS_LIMIT.toString(16).padStart(32, \"0\")}`,\n preVerificationGas: `0x${(userOp.preVerificationGas ?? DEFAULT_PRE_VERIFICATION_GAS).toString(16)}`,\n maxFeePerGas: `0x${(userOp.maxFeePerGas ?? 0n).toString(16)}`,\n maxPriorityFeePerGas: `0x${(userOp.maxPriorityFeePerGas ?? 0n).toString(16)}`,\n paymasterAndData: userOp.paymasterAndData ?? \"0x\",\n signature: userOp.signature ?? \"0x\",\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 15_000);\n\n try {\n let response: Response;\n try {\n response = await fetch(bundlerUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"eth_estimateUserOperationGas\",\n params: [serializedOp, entryPoint],\n }),\n signal: controller.signal,\n });\n } catch {\n // Network error (DNS failure, timeout, etc.) — return defaults\n return {\n callGasLimit: DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: DEFAULT_PRE_VERIFICATION_GAS,\n };\n }\n\n if (!response.ok) {\n return {\n callGasLimit: DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: DEFAULT_PRE_VERIFICATION_GAS,\n };\n }\n\n const json = (await response.json().catch(() => ({}))) as {\n result?: {\n callGasLimit?: string;\n verificationGasLimit?: string;\n preVerificationGas?: string;\n accountGasLimits?: string;\n };\n error?: { code: number; message: string };\n };\n\n if (json.error || !json.result) {\n // If estimation fails, return default values\n return {\n callGasLimit: DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: DEFAULT_PRE_VERIFICATION_GAS,\n };\n }\n\n const result = json.result!;\n\n // Try to decode accountGasLimits (v0.7)\n if (result.accountGasLimits) {\n const raw = result.accountGasLimits.replace(\"0x\", \"\");\n return {\n callGasLimit: BigInt(`0x${raw.slice(32, 64)}`),\n verificationGasLimit: BigInt(`0x${raw.slice(0, 32)}`),\n preVerificationGas: result.preVerificationGas\n ? BigInt(result.preVerificationGas)\n : DEFAULT_PRE_VERIFICATION_GAS,\n accountGasLimits: result.accountGasLimits as Hex,\n };\n }\n\n return {\n callGasLimit: result.callGasLimit\n ? BigInt(result.callGasLimit)\n : DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: result.verificationGasLimit\n ? BigInt(result.verificationGasLimit)\n : DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: result.preVerificationGas\n ? BigInt(result.preVerificationGas)\n : DEFAULT_PRE_VERIFICATION_GAS,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n}\n","/**\n * Smart Account Manager\n *\n * Manages ERC-4337 Smart Contract Wallet lifecycle:\n * - Counterfactual address computation (CREATE2)\n * - Account deployment via factory contract\n * - Deploy-and-execute (merge deploy into first UserOperation)\n *\n * Supports SimpleAccount (eth-infinitism) with EntryPoint v0.7.\n *\n * @see docs/features/account-abstraction.md\n */\n\nimport { type AAErrorCode, AccountAbstractionError } from \"./errors\";\nimport { PaymasterService } from \"./paymaster\";\nimport {\n AA_SUPPORTED_CHAINS,\n type AccountType,\n type Address,\n type BundlerClient,\n type Call,\n DEFAULT_CALL_GAS_LIMIT,\n DEFAULT_ENTRY_POINT,\n DEFAULT_PRE_VERIFICATION_GAS,\n DEFAULT_VERIFICATION_GAS_LIMIT,\n ENTRY_POINT_V0_6,\n ENTRY_POINT_V0_7,\n type Hex,\n type PaymasterConfig,\n type SendUserOpOptions,\n SIMPLE_ACCOUNT_FACTORY,\n type SmartAccountConfig,\n type SmartAccountInfo,\n type UserOperation,\n type UserOperationGasEstimate,\n type UserOperationReceipt,\n type UserOperationResponse,\n} from \"./types\";\nimport { buildUserOperation, signUserOperation } from \"./user-operation\";\n\n/**\n * Hash map of known factory addresses for each account type.\n * Keyed by chain ID (CAIP-2 format).\n */\nfunction getFactoryAddress(\n _chainId: string,\n _accountType: AccountType,\n): Address {\n return SIMPLE_ACCOUNT_FACTORY;\n}\n\n/**\n * Get the EntryPoint address for a given chain.\n */\nfunction getEntryPointForChain(chainId: string): Address | null {\n const info = AA_SUPPORTED_CHAINS[chainId];\n if (info) return info.entryPoint;\n return null;\n}\n\n/**\n * Compute the keccak256 hash of a hex string.\n */\nasync function keccak256(data: Hex): Promise<Hex> {\n const { keccak_256 } = await import(\"@noble/hashes/sha3\");\n const { bytesToHex } = await import(\"@noble/hashes/utils\");\n const raw = data.startsWith(\"0x\") ? data.slice(2) : data;\n const bytes = new Uint8Array(raw.length / 2);\n for (let i = 0; i < raw.length; i += 2) {\n bytes[i / 2] = parseInt(raw.slice(i, i + 2), 16);\n }\n return `0x${bytesToHex(keccak_256(bytes))}` as Hex;\n}\n\n/**\n * Encode the createAccount call data for the SimpleAccountFactory.\n * The factory's `createAccount(address owner, uint256 salt)` returns the account address.\n *\n * ABI: createAccount(address,uint256) = 0xcf7aba77\n * Args: owner (left-padded to 32 bytes) + salt (left-padded to 32 bytes)\n */\nfunction encodeCreateAccount(owner: Address, salt: bigint): Hex {\n const selector = \"0xcf7aba77\";\n const ownerArg = owner.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\");\n const saltArg = salt.toString(16).padStart(64, \"0\");\n return `${selector}${ownerArg}${saltArg}` as Hex;\n}\n\n/**\n * Encode the execute call for SimpleAccount.\n * execute(address,uint256,bytes) selector = 0xb61d27f6\n */\nfunction encodeExecute(to: Address, value: bigint, data: Hex): Hex {\n const selector = \"0xb61d27f6\";\n const toArg = to.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\");\n const valueArg = value.toString(16).padStart(64, \"0\");\n // Dynamic bytes: offset + length + data\n const dataOffset = toArg.length / 2 + valueArg.length / 2 + 64; // 32 bytes for offset\n const dataLen = data.startsWith(\"0x\")\n ? (data.length - 2) / 2\n : data.length / 2;\n const offsetArg = `00000000000000000000000000000000000000000000000000000000000000${dataOffset.toString(16).padStart(2, \"0\")}`;\n const lengthArg = dataLen.toString(16).padStart(64, \"0\");\n const dataRaw = data.replace(\"0x\", \"\");\n return `${selector}${toArg}${valueArg}${offsetArg}${lengthArg}${dataRaw}` as Hex;\n}\n\n/**\n * Encode batch execute for SimpleAccount.\n * executeBatch(address[],uint256[],bytes[]) selector = 0x47e1da2a\n *\n * For simplicity, we only pass one array of calldata elements.\n */\nfunction encodeExecuteBatch(calls: Call[]): Hex {\n const selector = \"0x47e1da2a\";\n // Build the ABI-encoded arrays\n const numCalls = calls.length;\n\n // offsets and lengths\n const toOffset = 32; // after numCalls word\n const valuesOffset = toOffset + 32 * numCalls + 32; // after to array\n const datasOffset = valuesOffset + 32 * numCalls + 32; // after values array\n\n const toPart =\n numCalls.toString(16).padStart(64, \"0\") +\n calls\n .map((c) => c.to.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\"))\n .join(\"\");\n\n const valuePart =\n numCalls.toString(16).padStart(64, \"0\") +\n calls.map((c) => c.value.toString(16).padStart(64, \"0\")).join(\"\");\n\n // Datas: dynamic array of dynamic bytes\n const dataLengths = calls.map((c) => c.data.replace(\"0x\", \"\").length / 2);\n const dataBody = calls\n .map(\n (c, i) =>\n dataLengths[i].toString(16).padStart(64, \"0\") +\n c.data.replace(\"0x\", \"\"),\n )\n .join(\"\");\n\n // Compute total data body length for the outer array\n const totalDataLength = 32 + dataBody.length / 2; // length word + data\n const dataArrayLengthWord = numCalls.toString(16).padStart(64, \"0\");\n\n const dataPart = dataArrayLengthWord + dataBody;\n\n // Locations (offsets from start of encoded data):\n // 0x00: numCalls\n // 0x20: to array offset (= 32)\n // 0x40: values array offset (= 32 + to array total size)\n // 0x60: datas array offset (= values array offset + values array total size)\n\n // Recalculate precisely:\n // Each array: 32 bytes for length + 32*N bytes for elements\n // But values are uint256 so 32 bytes each, to addresses are address so also padded to 32\n const toArraySize = 32 + numCalls * 32;\n const valuesArraySize = 32 + numCalls * 32;\n const datasArraySize = 32 + dataBody.length / 2;\n\n const toArrOffset = 32 + 32 + 32; // after the 3 offset words + numCalls\n // Actually the outer encoding:\n // [0x00-0x1f] = offset to to[] array\n // [0x20-0x3f] = offset to values[] array\n // [0x40-0x5f] = offset to datas[] array\n // Wait executeBatch(address[],uint256[],bytes[]) takes 3 tuple args\n // Actually executeBatch is: function executeBatch(address[] calldata dest, uint256[] calldata val, bytes[] calldata data)\n\n // Let me use a simpler but correct encoding:\n // Head section: 3 offsets (32 bytes each) = 96 bytes\n // Then each array follows at those offsets\n\n const headSize = 96; // 3 * 32\n const toArrOffset2 = 0x20; // first array starts at offset 32 (after first 32 bytes which is the offset)\n const valuesArrOffset2 = headSize + toArraySize; // values array starts after to array\n // Hmm this is getting complex. Let me use a cleaner approach.\n\n // Actually for executeBatch, the selector is the first 4 bytes of keccak256(\"executeBatch(address[],uint256[],bytes[])\")\n // The ABI encoding for 3 dynamic arrays:\n // offset_to[] (32 bytes) = 0x60 (start of to array data after all 3 offsets)\n // offset_values[] (32 bytes) = 0x60 + to_array_size\n // offset_datas[] (32 bytes) = 0x60 + to_array_size + values_array_size\n\n return `${selector}${encodeExecuteBatchCalls(calls)}` as Hex;\n}\n\nfunction encodeExecuteBatchCalls(calls: Call[]): string {\n const n = calls.length;\n const nWord = n.toString(16).padStart(64, \"0\");\n\n // Each array: [length(32B)] + [n elements padded to 32B each]\n const toArray =\n nWord +\n calls\n .map((c) => c.to.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\"))\n .join(\"\");\n const valuesArray =\n nWord + calls.map((c) => c.value.toString(16).padStart(64, \"0\")).join(\"\");\n // Datas: dynamic bytes array\n const datDatas = calls\n .map((c) => {\n const rawData = c.data.replace(\"0x\", \"\");\n const dataLen = rawData.length / 2;\n return dataLen.toString(16).padStart(64, \"0\") + rawData;\n })\n .join(\"\");\n const datasArray = nWord + datDatas;\n\n const toArrayLen = 32 + n * 32;\n const valuesArrayLen = 32 + n * 32;\n const datasArrayLen = 32 + datDatas.length / 2;\n\n const toOffset = (96).toString(16).padStart(64, \"0\"); // after 3 head words\n const valuesOffset = (96 + toArrayLen).toString(16).padStart(64, \"0\");\n const datasOffset = (96 + toArrayLen + valuesArrayLen)\n .toString(16)\n .padStart(64, \"0\");\n\n return (\n toOffset + valuesOffset + datasOffset + toArray + valuesArray + datasArray\n );\n}\n\n/**\n * Check if a contract is deployed at the given address.\n */\nasync function isContractDeployed(\n rpcUrl: string,\n address: Address,\n): Promise<boolean> {\n const code = await rpcCall<string>(rpcUrl, \"eth_getCode\", [\n address,\n \"latest\",\n ]);\n return code !== \"0x\";\n}\n\n/**\n * Make a JSON-RPC call.\n */\nasync function rpcCall<T>(\n rpcUrl: string,\n method: string,\n params: unknown[],\n): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method,\n params,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new AccountAbstractionError(\n \"aa_rpc_error\",\n `RPC returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: T;\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new AccountAbstractionError(\"aa_rpc_error\", json.error.message, {\n code: json.error.code,\n });\n }\n\n return json.result as T;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n// ─── SmartAccountManager ───────────────────────────────────────────────\n\nexport interface SmartAccountManagerConfig {\n /** RPC URL for the target chain */\n rpcUrl: string;\n /** Bundler client configuration */\n bundlerClient: BundlerClient;\n /** Optional paymaster service */\n paymaster?: PaymasterService;\n /** Default paymaster configuration (used if no paymaster instance provided) */\n defaultPaymasterConfig?: PaymasterConfig;\n /** Chain ID in CAIP-2 format */\n chainId: string;\n}\n\nexport class SmartAccountManager {\n private config: SmartAccountManagerConfig;\n\n constructor(config: SmartAccountManagerConfig) {\n this.config = config;\n }\n\n // ── Public API ──────────────────────────────────────────────────\n\n /**\n * Check if ERC-4337 is supported on the configured chain.\n */\n isAASupported(chainId?: string): boolean {\n const id = chainId ?? this.config.chainId;\n return id in AA_SUPPORTED_CHAINS;\n }\n\n /**\n * Compute the counterfactual address for a smart account.\n * The account does not need to be deployed yet.\n *\n * Uses the factory's createAccount to compute the address via eth_call.\n *\n * @param config - Smart account configuration\n * @returns The deterministic smart account address\n */\n async getAccountAddress(config: SmartAccountConfig): Promise<Address> {\n const chainId = config.chainId ?? this.config.chainId;\n const entryPoint = config.entryPoint ?? this.getEntryPoint(chainId);\n const factory = this.getFactory(chainId, config.accountType);\n\n const salt = config.salt ?? 0n;\n const callData = encodeCreateAccount(config.owner, salt);\n\n // eth_call the factory to get the deterministic address\n const result = await rpcCall<string>(this.config.rpcUrl, \"eth_call\", [\n {\n to: factory,\n data: callData,\n },\n \"latest\",\n ]);\n\n // The factory returns the account address (20 bytes, padded to 32)\n const raw = result.startsWith(\"0x\") ? result.slice(2) : result;\n const addressHex = `0x${raw.slice(raw.length - 40)}` as Address;\n return addressHex;\n }\n\n /**\n * Create a SmartAccountManager instance for a given smart account.\n * Computes the address but does not deploy.\n *\n * @param config - Smart account configuration\n * @returns Smart account info\n */\n async createAccount(config: SmartAccountConfig): Promise<SmartAccountInfo> {\n if (\n !config.owner ||\n !config.owner.startsWith(\"0x\") ||\n config.owner.length !== 42\n ) {\n throw new AccountAbstractionError(\"aa_invalid_owner\");\n }\n\n const chainId = config.chainId ?? this.config.chainId;\n const address = await this.getAccountAddress(config);\n const isDeployed = await isContractDeployed(this.config.rpcUrl, address);\n\n return {\n address,\n isDeployed,\n accountType: config.accountType,\n owner: config.owner,\n };\n }\n\n /**\n * Deploy a smart account to the blockchain.\n *\n * Sends a raw transaction to the factory contract with the createAccount call.\n *\n * @param config - Smart account configuration\n * @returns Transaction hash\n */\n async deployAccount(config: SmartAccountConfig): Promise<Hex> {\n const chainId = config.chainId ?? this.config.chainId;\n const address = await this.getAccountAddress(config);\n const deployed = await isContractDeployed(this.config.rpcUrl, address);\n if (deployed) {\n return address;\n }\n\n // Deployment requires a signed tx to the factory.\n // getDeployCallData returns the payload needed for deployment.\n // The caller must sign and broadcast this tx.\n throw new AccountAbstractionError(\n \"aa_account_not_deployed\",\n `Account ${address} is not deployed. Use getDeployCallData() to obtain the deploy transaction payload, sign it, and send it to the factory.`,\n );\n }\n\n /**\n * Deploy using a minimal deployment transaction.\n * For self-custodial setups, the deploy is a simple eth_call via the factory.\n */\n async getDeployCallData(config: SmartAccountConfig): Promise<{\n to: Address;\n data: Hex;\n value: bigint;\n }> {\n const chainId = config.chainId ?? this.config.chainId;\n const factory = this.getFactory(chainId, config.accountType);\n const salt = config.salt ?? 0n;\n\n return {\n to: factory,\n data: encodeCreateAccount(config.owner, salt),\n value: 0n,\n };\n }\n\n // ── UserOperation Methods ───────────────────────────────────────\n\n /**\n * Send a UserOperation to the bundler.\n *\n * @param config - Smart account config\n * @param calls - Array of calls to execute\n * @param options - Optional overrides (gas, paymaster)\n * @returns UserOperation response\n */\n async sendUserOperation(\n config: SmartAccountConfig,\n calls: Call[],\n options?: SendUserOpOptions,\n ): Promise<UserOperationResponse> {\n if (!calls.length) {\n throw new AccountAbstractionError(\"aa_no_calls\");\n }\n\n const chainId = config.chainId ?? this.config.chainId;\n const address = await this.getAccountAddress(config);\n\n // Determine initCode (deploy if not deployed and not skipped)\n let initCode: Hex = \"0x\";\n if (!options?.skipDeploy) {\n const deployed = await isContractDeployed(this.config.rpcUrl, address);\n if (!deployed) {\n const deployData = await this.getDeployCallData(config);\n const factory = this.getFactory(chainId, config.accountType);\n // initCode = factory address (20 bytes) + createAccount calldata\n initCode = `${factory}${deployData.data.replace(\"0x\", \"\")}` as Hex;\n }\n }\n\n // Read nonce from entry point\n const entryPoint = config.entryPoint ?? this.getEntryPoint(chainId);\n const nonce = await this.getNonce(entryPoint, address);\n\n // Encode call data (batch if multiple calls)\n const callData =\n calls.length === 1\n ? encodeExecute(calls[0].to, calls[0].value, calls[0].data)\n : encodeExecuteBatch(calls);\n\n // Estimate gas\n let gasEstimate: UserOperationGasEstimate;\n try {\n gasEstimate = await this.estimateUserOperationGas(entryPoint, {\n sender: address,\n nonce,\n initCode,\n callData,\n paymasterAndData: \"0x\",\n signature: \"0x\",\n });\n } catch {\n // Fall back to defaults if estimation fails\n gasEstimate = {\n callGasLimit: DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: DEFAULT_PRE_VERIFICATION_GAS,\n };\n }\n\n // Apply gas overrides\n const callGasLimit =\n options?.gasOverrides?.callGasLimit ?? gasEstimate.callGasLimit;\n const verificationGasLimit =\n options?.gasOverrides?.verificationGasLimit ??\n gasEstimate.verificationGasLimit;\n const preVerificationGas =\n options?.gasOverrides?.preVerificationGas ??\n gasEstimate.preVerificationGas;\n\n // Get fee data\n let maxFeePerGas: bigint;\n let maxPriorityFeePerGas: bigint;\n if (options?.gasOverrides?.maxFeePerGas) {\n maxFeePerGas = options.gasOverrides.maxFeePerGas;\n maxPriorityFeePerGas =\n options.gasOverrides.maxPriorityFeePerGas ??\n (await this.getPriorityFee());\n } else {\n const baseFee = await this.getBaseFee();\n const priorityFee = await this.getPriorityFee();\n maxFeePerGas = baseFee * 2n + priorityFee;\n maxPriorityFeePerGas = priorityFee;\n }\n\n // Build the v0.7 accountGasLimits\n const accountGasLimits = encodeGasLimits(\n verificationGasLimit,\n callGasLimit,\n );\n\n // Build partial UserOperation\n let userOp = buildUserOperation({\n sender: address,\n nonce,\n initCode,\n callData,\n accountGasLimits,\n preVerificationGas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n paymasterAndData: \"0x\",\n signature: \"0x\",\n });\n\n // Paymaster\n const paymasterConfig =\n options?.paymaster ?? this.config.defaultPaymasterConfig;\n if (paymasterConfig) {\n const paymasterService =\n this.config.paymaster ??\n new PaymasterService({\n url: paymasterConfig.url,\n type: paymasterConfig.type,\n policy: paymasterConfig.policy,\n });\n const paymasterData = await paymasterService.getPaymasterData(userOp);\n userOp = { ...userOp, paymasterAndData: paymasterData.paymasterAndData };\n }\n\n return {\n userOpHash: \"0x\", // Will be set after sending\n sender: address,\n nonce,\n };\n }\n\n /**\n * Get the nonce for a smart account from the EntryPoint.\n */\n async getNonce(entryPoint: Address, sender: Address): Promise<bigint> {\n const key = \"0x\" + \"0\".repeat(64); // default key (0)\n const data =\n `0x35567e1a${sender.replace(\"0x\", \"\").padStart(64, \"0\")}${key.replace(\"0x\", \"\")}` as Hex;\n // Actually the getNonce function selector = 0x35567e1a\n // getNonce(address sender, uint192 key)\n const selector = \"0x35567e1a\";\n const senderArg = sender.toLowerCase().replace(\"0x\", \"\").padStart(64, \"0\");\n const keyArg = key.replace(\"0x\", \"\").padStart(48, \"0\"); // uint192 = 24 bytes\n const callData = `${selector}${senderArg}${keyArg}` as Hex;\n\n // Ensure keyArg is padded to 32 bytes for ABI encoding - uint192 is 24 bytes padded to 32\n const keyArg32 = key.replace(\"0x\", \"\").padStart(64, \"0\");\n\n const result = await rpcCall<string>(this.config.rpcUrl, \"eth_call\", [\n { to: entryPoint, data: `${selector}${senderArg}${keyArg32}` },\n \"latest\",\n ]);\n\n return BigInt(result);\n }\n\n /**\n * Estimate gas for a UserOperation via the bundler's eth_estimateUserOperationGas.\n */\n async estimateUserOperationGas(\n entryPoint: Address,\n partialUserOp: Partial<UserOperation>,\n ): Promise<UserOperationGasEstimate> {\n const bundlerUrl = this.config.bundlerClient.url;\n const params = {\n ...partialUserOp,\n sender: partialUserOp.sender ?? \"0x\",\n nonce: partialUserOp.nonce ?? 0n,\n initCode: partialUserOp.initCode ?? \"0x\",\n callData: partialUserOp.callData ?? \"0x\",\n accountGasLimits: partialUserOp.accountGasLimits ?? \"0x\",\n preVerificationGas: partialUserOp.preVerificationGas ?? 0n,\n maxFeePerGas: partialUserOp.maxFeePerGas ?? 0n,\n maxPriorityFeePerGas: partialUserOp.maxPriorityFeePerGas ?? 0n,\n paymasterAndData: partialUserOp.paymasterAndData ?? \"0x\",\n signature: partialUserOp.signature ?? \"0x\",\n };\n\n const result = await rpcCall<{\n callGasLimit?: string;\n verificationGasLimit?: string;\n preVerificationGas?: string;\n accountGasLimits?: string;\n }>(bundlerUrl, \"eth_estimateUserOperationGas\", [params, entryPoint]);\n\n return {\n callGasLimit: result.callGasLimit\n ? BigInt(result.callGasLimit)\n : DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit: result.verificationGasLimit\n ? BigInt(result.verificationGasLimit)\n : DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas: result.preVerificationGas\n ? BigInt(result.preVerificationGas)\n : DEFAULT_PRE_VERIFICATION_GAS,\n accountGasLimits: result.accountGasLimits as Hex | undefined,\n };\n }\n\n /**\n * Send a signed UserOperation to the bundler.\n * Returns the userOpHash which can be used to track the operation.\n */\n async sendUserOpToBundler(userOp: UserOperation): Promise<Hex> {\n const bundlerUrl = this.config.bundlerClient.url;\n\n if (!bundlerUrl) {\n throw new AccountAbstractionError(\"aa_no_bundler\");\n }\n\n // Serialize UserOperation for RPC: bigint → hex string (even-length, per Ethereum JSON-RPC convention)\n const bigintToEvenHex = (n: bigint): string => {\n const hex = n.toString(16);\n return hex.length % 2 === 0 ? `0x${hex}` : `0x0${hex}`;\n };\n const serializedOp = {\n sender: userOp.sender,\n nonce: bigintToEvenHex(userOp.nonce),\n initCode: userOp.initCode,\n callData: userOp.callData,\n accountGasLimits: userOp.accountGasLimits,\n preVerificationGas: bigintToEvenHex(userOp.preVerificationGas),\n maxFeePerGas: bigintToEvenHex(userOp.maxFeePerGas),\n maxPriorityFeePerGas: bigintToEvenHex(userOp.maxPriorityFeePerGas),\n paymasterAndData: userOp.paymasterAndData,\n signature: userOp.signature,\n };\n\n const userOpHash = await rpcCall<Hex>(\n bundlerUrl,\n \"eth_sendUserOperation\",\n [serializedOp, userOp.sender], // EntryPoint may be needed here\n );\n\n return userOpHash;\n }\n\n /**\n * Poll for a UserOperation receipt.\n */\n async getUserOperationReceipt(\n userOpHash: Hex,\n maxRetries = 10,\n intervalMs = 2000,\n ): Promise<UserOperationReceipt | null> {\n const bundlerUrl = this.config.bundlerClient.url;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const result = await rpcCall<{\n userOpHash: Hex;\n entryPoint: Address;\n sender: Address;\n nonce: string;\n paymaster?: Address;\n actualGasUsed: string;\n actualGasCost: string;\n success: boolean;\n transactionHash: Hex;\n logs: Array<{ address: Address; topics: Hex[]; data: Hex }>;\n } | null>(bundlerUrl, \"eth_getUserOperationReceipt\", [userOpHash]);\n\n if (result) {\n return {\n userOpHash: result.userOpHash,\n entryPoint: result.entryPoint,\n sender: result.sender,\n nonce: BigInt(result.nonce),\n paymaster: result.paymaster,\n actualGasUsed: BigInt(result.actualGasUsed),\n actualGasCost: BigInt(result.actualGasCost),\n success: result.success,\n transactionHash: result.transactionHash,\n logs: result.logs,\n };\n }\n } catch {\n // Continue polling\n }\n\n if (i < maxRetries - 1) {\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n\n throw new AccountAbstractionError(\n \"aa_receipt_timeout\",\n \"UserOperation receipt not found after maximum retries\",\n );\n }\n\n /**\n * Send a batch of calls in a single UserOperation.\n *\n * @param config - Smart account config\n * @param calls - Array of calls to batch\n * @param options - Optional overrides\n * @returns UserOperation response\n */\n async sendBatch(\n config: SmartAccountConfig,\n calls: Call[],\n options?: SendUserOpOptions,\n ): Promise<UserOperationResponse> {\n return this.sendUserOperation(config, calls, options);\n }\n\n // ── Gas / Fee Helpers ───────────────────────────────────────────\n\n /**\n * Get the latest base fee per gas.\n */\n async getBaseFee(): Promise<bigint> {\n try {\n const block = await rpcCall<{ baseFeePerGas?: string }>(\n this.config.rpcUrl,\n \"eth_getBlockByNumber\",\n [\"latest\", false],\n );\n if (block?.baseFeePerGas) {\n return BigInt(block.baseFeePerGas);\n }\n } catch {\n // RPC failed — use fallback\n }\n return 10_000_000_000n; // 10 gwei fallback\n }\n\n /**\n * Get the recommended priority fee.\n */\n async getPriorityFee(): Promise<bigint> {\n try {\n const result = await rpcCall<string>(\n this.config.rpcUrl,\n \"eth_maxPriorityFeePerGas\",\n [],\n );\n return BigInt(result);\n } catch {\n return 1_000_000_000n; // 1 gwei fallback\n }\n }\n\n // ── Private Helpers ─────────────────────────────────────────────\n\n private getEntryPoint(chainId: string): Address {\n const ep = getEntryPointForChain(chainId);\n if (!ep) {\n throw new AccountAbstractionError(\"aa_no_entry_point\");\n }\n return ep;\n }\n\n private getFactory(chainId: string, accountType: AccountType): Address {\n const factory = getFactoryAddress(chainId, accountType);\n if (!factory) {\n throw new AccountAbstractionError(\"aa_no_factory\");\n }\n return factory;\n }\n}\n\n// ─── Utility ───────────────────────────────────────────────────────────\n\n/**\n * Encode account gas limits as a packed 32-byte value (v0.7).\n * High 16 bytes = verificationGasLimit\n * Low 16 bytes = callGasLimit\n */\nexport function encodeGasLimits(\n verificationGasLimit: bigint,\n callGasLimit: bigint,\n): Hex {\n const vglHex = verificationGasLimit.toString(16).padStart(32, \"0\");\n const cglHex = callGasLimit.toString(16).padStart(32, \"0\");\n return `0x${vglHex}${cglHex}` as Hex;\n}\n\n/**\n * Decode account gas limits from packed 32-byte value (v0.7).\n */\nexport function decodeGasLimits(accountGasLimits: Hex): {\n verificationGasLimit: bigint;\n callGasLimit: bigint;\n} {\n const raw = accountGasLimits.startsWith(\"0x\")\n ? accountGasLimits.slice(2)\n : accountGasLimits;\n const verificationGasLimit = BigInt(`0x${raw.slice(0, 32)}`);\n const callGasLimit = BigInt(`0x${raw.slice(32, 64)}`);\n return { verificationGasLimit, callGasLimit };\n}\n","/**\n * Address validation helpers.\n *\n * Minimal set — enough to prevent blackhole transfers.\n */\n\nconst BURN_PREFIXES = [\"dead\", \"deaf\", \"deed\", \"deec\", \"deed\"];\nconst ZERO_ADDR = \"0x0000000000000000000000000000000000000000\";\nconst EVM_ADDR_RE = /^0x[a-fA-F0-9]{40}$/;\n\n/** True for `0x0000…0000` (zero/burn address on all EVM chains) */\nexport function isZeroAddress(address: string): boolean {\n return address.toLowerCase() === ZERO_ADDR;\n}\n\n/** True if the address contains known burn-indicating hex prefixes */\nexport function isBurnAddress(address: string): boolean {\n const clean = address.toLowerCase().replace(/^0x/, \"\");\n return BURN_PREFIXES.some((p) => clean.startsWith(p)) || clean === \"0000000000000000000000000000000000000000\";\n}\n\n/**\n * Returns true if the string is a valid address for the given chain namespace.\n * For EVM chains: 0x + 40 hex chars (checksum optional).\n * Solana / XRPL: basic format check (length & prefix).\n */\nexport function isValidAddress(address: string, chainNamespace?: string): boolean {\n if (!address || typeof address !== \"string\") return false;\n if (chainNamespace === \"eip155\" || !chainNamespace) return EVM_ADDR_RE.test(address);\n if (chainNamespace === \"solana\") return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);\n if (chainNamespace === \"xrpl\") return /^r[1-9A-HJ-NP-Za-km-z]{24,34}$/.test(address);\n return true; // unknown namespace — accept optimistically\n}\n","/**\n * Auto-Reconnect Manager\n *\n * Handles automatic reconnection to previously connected wallets\n * with configurable retry strategies.\n */\n\nimport type { UniversalWalletSession } from \"./session\";\n\nexport interface AutoReconnectConfig {\n enabled: boolean;\n maxRetries: number;\n retryDelay: number;\n onReconnecting?: () => void;\n onReconnected?: () => void;\n onFailed?: (error: Error) => void;\n}\n\ninterface ReconnectState<T = UniversalWalletSession> {\n lastSession: T | null;\n retryCount: number;\n isReconnecting: boolean;\n}\n\nexport class AutoReconnectManager<T = UniversalWalletSession> {\n private config: AutoReconnectConfig;\n private state: ReconnectState<T> = {\n lastSession: null,\n retryCount: 0,\n isReconnecting: false,\n };\n private retryTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(config: Partial<AutoReconnectConfig> = {}) {\n this.config = {\n enabled: config.enabled ?? true,\n maxRetries: config.maxRetries ?? 3,\n retryDelay: config.retryDelay ?? 2000,\n onReconnecting: config.onReconnecting,\n onReconnected: config.onReconnected,\n onFailed: config.onFailed,\n };\n }\n\n setLastSession(session: T): void {\n this.state.lastSession = session;\n this.state.retryCount = 0;\n }\n\n getState(): ReconnectState<T> {\n return {\n lastSession: this.state.lastSession,\n retryCount: this.state.retryCount,\n isReconnecting: this.state.isReconnecting,\n };\n }\n\n needsReconnect(): boolean {\n return this.config.enabled && this.state.lastSession !== null;\n }\n\n async reconnect(\n reconnectFn: (session: T) => Promise<unknown>,\n ): Promise<boolean> {\n if (!this.config.enabled || !this.state.lastSession) {\n return false;\n }\n\n if (this.state.isReconnecting) {\n return false;\n }\n\n this.state.isReconnecting = true;\n this.config.onReconnecting?.();\n\n try {\n await reconnectFn(this.state.lastSession);\n this.state.isReconnecting = false;\n this.state.retryCount = 0;\n this.config.onReconnected?.();\n return true;\n } catch (error) {\n this.state.isReconnecting = false;\n return this.handleReconnectError(error as Error, reconnectFn);\n }\n }\n\n private async handleReconnectError(\n error: Error,\n reconnectFn: (session: T) => Promise<unknown>,\n ): Promise<boolean> {\n if (this.state.retryCount >= this.config.maxRetries) {\n this.config.onFailed?.(error);\n this.clearSession();\n return false;\n }\n\n this.state.retryCount++;\n\n const delay = Math.min(\n this.config.retryDelay * this.state.retryCount,\n 2147483647,\n );\n\n return new Promise<boolean>((resolve) => {\n this.retryTimeout = setTimeout(async () => {\n try {\n const success = await this.reconnect(reconnectFn);\n resolve(success);\n } catch {\n resolve(false);\n }\n }, delay);\n });\n }\n\n cancel(): void {\n if (this.retryTimeout) {\n clearTimeout(this.retryTimeout);\n this.retryTimeout = null;\n }\n this.state.isReconnecting = false;\n }\n\n clearSession(): void {\n this.state.lastSession = null;\n this.state.retryCount = 0;\n this.state.isReconnecting = false;\n this.cancel();\n }\n\n updateConfig(config: Partial<AutoReconnectConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n reset(): void {\n this.clearSession();\n this.config.onFailed = undefined;\n this.config.onReconnected = undefined;\n this.config.onReconnecting = undefined;\n }\n}\n\nexport function createAutoReconnectManager<T = UniversalWalletSession>(\n config?: Partial<AutoReconnectConfig>,\n): AutoReconnectManager<T> {\n return new AutoReconnectManager<T>(config);\n}\n","/**\n * Configurable Logger\n *\n * Replaces raw `console.*` calls across the SDK with a logger that can\n * be silenced, namespaced, or have custom sinks injected.\n *\n * Usage:\n * import { logger } from \"@naculus/connect-core\";\n * logger.warn(\"core/session\", \"Failed to save\", err);\n *\n * At app level:\n * import { setLogLevel, setLogSink } from \"@naculus/connect-core\";\n * setLogLevel(\"error\"); // suppress debug/info/warn\n * setLogSink((level, ns, args) => myLogger(level, ns, args));\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 999,\n};\n\nlet currentLevel: LogLevel = \"warn\";\nlet currentSink:\n | ((level: LogLevel, ns: string, ...args: unknown[]) => void)\n | null = null;\n\n/** Set the minimum log level. Messages below this threshold are suppressed. */\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\n/** Replace the default console-based sink with a custom handler. */\nexport function setLogSink(\n sink: ((level: LogLevel, ns: string, ...args: unknown[]) => void) | null,\n): void {\n currentSink = sink;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVELS[level] >= LEVELS[currentLevel];\n}\n\nfunction log(level: LogLevel, ns: string, ...args: unknown[]): void {\n if (!shouldLog(level)) return;\n\n if (currentSink) {\n currentSink(level, ns, ...args);\n return;\n }\n\n const prefix = `[${ns}]`;\n switch (level) {\n case \"debug\":\n console.debug(prefix, ...args);\n break;\n case \"info\":\n console.info(prefix, ...args);\n break;\n case \"warn\":\n console.warn(prefix, ...args);\n break;\n case \"error\":\n console.error(prefix, ...args);\n break;\n }\n}\n\n/** Namespace-bound convenience wrapper returned by `logger.for(ns)`. */\nexport interface LoggerNamespace {\n debug(...args: unknown[]): void;\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nfunction createNamespace(ns: string): LoggerNamespace {\n return {\n debug: (...args: unknown[]) => log(\"debug\", ns, ...args),\n info: (...args: unknown[]) => log(\"info\", ns, ...args),\n warn: (...args: unknown[]) => log(\"warn\", ns, ...args),\n error: (...args: unknown[]) => log(\"error\", ns, ...args),\n };\n}\n\n/**\n * Global logger object.\n * logger.warn(\"my-ns\", \"message\", err);\n * const l = logger.for(\"my-ns\"); l.warn(\"message\", err);\n */\nexport const logger = {\n debug: (ns: string, ...args: unknown[]) => log(\"debug\", ns, ...args),\n info: (ns: string, ...args: unknown[]) => log(\"info\", ns, ...args),\n warn: (ns: string, ...args: unknown[]) => log(\"warn\", ns, ...args),\n error: (ns: string, ...args: unknown[]) => log(\"error\", ns, ...args),\n for: createNamespace,\n setLogLevel,\n setLogSink,\n /** Current effective level (for tests / introspection). */\n getLogLevel: () => currentLevel,\n};\n","/**\n * AxelarProvider — Axelar GMP integration for cross-chain transfers.\n *\n * Integrates with the Axelar network for General Message Passing (GMP),\n * enabling cross-chain token transfers and arbitrary contract calls.\n *\n * When configured with a backend URL, proxies through senderpay backend.\n * Otherwise attempts direct Axelar API interaction.\n *\n * @see https://docs.axelar.dev/dev/general-message-passing\n */\n\nimport { logger } from \"../../logger\";\nimport type {\n BridgeProvider,\n BridgeProviderId,\n ProviderTransaction,\n Route,\n RouteStatus,\n} from \"../types\";\n\n// ─── Axelar chain mapping ──────────────────────────────────────────────\n\nconst AXELAR_CHAIN_MAP: Record<string, string> = {\n \"eip155:1\": \"ethereum\",\n \"eip155:137\": \"polygon\",\n \"eip155:10\": \"optimism\",\n \"eip155:42161\": \"arbitrum\",\n \"eip155:8453\": \"base\",\n \"eip155:43114\": \"avalanche\",\n \"eip155:56\": \"binance\",\n \"eip155:250\": \"fantom\",\n \"eip155:100\": \"gnosis\",\n \"eip155:1101\": \"polygon-zkevm\",\n};\n\nconst REVERSE_AXELAR_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(AXELAR_CHAIN_MAP).map(([k, v]) => [v, k]),\n);\n\nfunction toAxelarChain(chainId: string): string | undefined {\n return (\n AXELAR_CHAIN_MAP[chainId] ??\n (chainId.startsWith(\"eip155:\") ? chainId.slice(7) : chainId)\n );\n}\n\nconst SUPPORTED_AXELAR_CHAINS = new Set(Object.keys(AXELAR_CHAIN_MAP));\n\n// ─── Known token addresses for Axelar-supported tokens ─────────────────\n\nconst KNOWN_TOKENS: Record<string, Record<string, string>> = {\n \"eip155:1\": {\n USDC: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n USDT: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n DAI: \"0x6B175474E89094C44Da98b954EedeAC495271d0F\",\n WETH: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n aUSDC: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n },\n \"eip155:137\": {\n USDC: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n USDT: \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\",\n aUSDC: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n },\n \"eip155:10\": {\n USDC: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n aUSDC: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n },\n};\n\nfunction resolveTokenAddress(chain: string, token: string): string {\n const chainTokens = KNOWN_TOKENS[chain];\n if (!chainTokens) return token;\n if (token.startsWith(\"0x\") && token.length === 42) return token;\n return chainTokens[token.toUpperCase()] ?? token;\n}\n\n// ─── AxelarProvider ────────────────────────────────────────────────────\n\nexport interface AxelarProviderConfig {\n /** Axelar API base URL */\n apiUrl?: string;\n /** Backend proxy URL (alternative to direct API) */\n backendUrl?: string;\n}\n\nexport class AxelarProvider implements BridgeProvider {\n readonly id: BridgeProviderId = \"axelar\";\n readonly name = \"Axelar\";\n private config: Required<Pick<AxelarProviderConfig, \"apiUrl\">> &\n AxelarProviderConfig;\n\n constructor(config?: AxelarProviderConfig) {\n this.config = {\n apiUrl: config?.apiUrl ?? \"https://api.axelarscan.io\",\n backendUrl: config?.backendUrl,\n };\n }\n\n async getRoutes(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]> {\n if (!this.supportsChainPair(fromChain, toChain)) {\n return [];\n }\n\n const resolvedFromToken = resolveTokenAddress(fromChain, fromToken);\n const resolvedToToken = resolveTokenAddress(toChain, toToken);\n\n // Try backend proxy first\n if (this.config.backendUrl) {\n try {\n const routes = await this.getRoutesViaBackend(\n fromChain,\n toChain,\n resolvedFromToken,\n resolvedToToken,\n amount,\n );\n if (routes.length > 0) return routes;\n } catch (error) {\n logger.warn(\"axelar-provider\", \"Backend proxy unavailable\", error);\n }\n }\n\n // Attempt direct Axelar API for GMP fee estimation\n try {\n const directRoutes = await this.getRoutesViaDirectAPI(\n fromChain,\n toChain,\n resolvedFromToken,\n resolvedToToken,\n amount,\n );\n return directRoutes;\n } catch (error) {\n logger.warn(\"axelar-provider\", \"Direct API call failed\", error);\n return [];\n }\n }\n\n private async getRoutesViaBackend(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]> {\n if (!this.config.backendUrl) return [];\n\n const response = await fetch(`${this.config.backendUrl}/api/routes`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n fromChain,\n toChain,\n fromToken,\n toToken,\n amount,\n provider: \"axelar\",\n }),\n });\n\n if (!response.ok) throw new Error(`Backend returned ${response.status}`);\n const data = (await response.json()) as { routes?: Route[] };\n return data.routes ?? [];\n }\n\n private async getRoutesViaDirectAPI(\n fromChain: string,\n toChain: string,\n _fromToken: string,\n _toToken: string,\n amount: string,\n ): Promise<Route[]> {\n const axelarFrom = toAxelarChain(fromChain);\n const axelarTo = toAxelarChain(toChain);\n if (!axelarFrom || !axelarTo) return [];\n\n try {\n // Estimate GMP fee via Axelar API\n const gmpResponse = await fetch(`${this.config.apiUrl}/GMP/gmpFee`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n sourceChain: axelarFrom,\n destinationChain: axelarTo,\n amount,\n sourceContractAddress: _fromToken,\n }),\n });\n\n if (!gmpResponse.ok) {\n logger.warn(\n \"axelar-provider\",\n `GMP fee API returned ${gmpResponse.status}`,\n );\n return [];\n }\n\n const gmpData = (await gmpResponse.json()) as {\n baseFee?: string;\n sourceGasFee?: string;\n destinationGasFee?: string;\n };\n\n const baseFee = gmpData.baseFee ?? \"0\";\n const destGasFee = gmpData.destinationGasFee ?? \"0\";\n\n return [\n {\n id: `axelar_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,\n provider: \"axelar\",\n fromChain,\n toChain,\n fromToken: _fromToken,\n toToken: _toToken,\n fromAmount: amount,\n toAmount: amount, // Axelar typically sends the same amount minus fees\n toAmountMin: (\n BigInt(amount) -\n BigInt(baseFee) -\n BigInt(destGasFee)\n ).toString(),\n gasCosts: {\n fromChain: {\n maxFeePerGas: \"0\",\n maxPriorityFeePerGas: \"0\",\n gasLimit: \"250000\",\n totalCostWei: \"0\",\n totalCostUsd: \"0\",\n },\n toChain: {\n maxFeePerGas: \"0\",\n maxPriorityFeePerGas: \"0\",\n gasLimit: destGasFee,\n totalCostWei: destGasFee,\n totalCostUsd: \"0\",\n },\n totalUsd: \"0\",\n },\n estimatedTime: 120, // Axelar GMP typically takes 1-2 minutes\n steps: [\n {\n type: \"approve\",\n chain: fromChain,\n token: _fromToken,\n contractAddress: this.getAxelarGateway(fromChain),\n estimatedGas: \"150000\",\n },\n {\n type: \"cross-chain\",\n chain: fromChain,\n token: _fromToken,\n contractAddress: this.getAxelarGateway(fromChain),\n estimatedGas: \"250000\",\n },\n ],\n fee: {\n protocolFee: baseFee,\n integrationFee: destGasFee,\n },\n summary: `Deposit via Axelar GMP: ${fromChain} → ${toChain}`,\n },\n ];\n } catch (error) {\n logger.warn(\"axelar-provider\", \"Failed to estimate GMP fee\", error);\n return [];\n }\n }\n\n async getTransactionParams(\n _route: Route,\n _sender: string,\n _recipient: string,\n ): Promise<ProviderTransaction[]> {\n // Build approve + deposit transactions for Axelar GMP\n return [\n {\n type: \"approve\",\n chainId: _route.fromChain,\n to: _route.fromToken,\n data: \"0x\",\n value: \"0\",\n },\n {\n type: \"cross-chain\",\n chainId: _route.fromChain,\n to: this.getAxelarGateway(_route.fromChain),\n data: this.buildGMPData(_route, _recipient),\n value: _route.fromAmount,\n },\n ];\n }\n\n async getRouteStatus(bridgeReference: string): Promise<RouteStatus> {\n try {\n const response = await fetch(\n `${this.config.apiUrl}/GMP/search?txHash=${bridgeReference}`,\n );\n\n if (!response.ok) {\n return { status: \"pending\" };\n }\n\n const data = (await response.json()) as {\n status?: string;\n toTxHash?: string;\n };\n\n const axelarStatus = data.status ?? \"pending\";\n\n return {\n status: this.mapAxelarStatus(axelarStatus),\n toTxHash: data.toTxHash,\n currentStep: axelarStatus,\n };\n } catch {\n return { status: \"pending\" };\n }\n }\n\n supportsChainPair(fromChain: string, toChain: string): boolean {\n return (\n SUPPORTED_AXELAR_CHAINS.has(fromChain) &&\n SUPPORTED_AXELAR_CHAINS.has(toChain)\n );\n }\n\n supportsToken(chain: string, token: string): boolean {\n const chainTokens = KNOWN_TOKENS[chain];\n if (!chainTokens) return false;\n if (token.startsWith(\"0x\") && token.length === 42) {\n return Object.values(chainTokens).includes(token.toLowerCase());\n }\n return Object.keys(chainTokens).includes(token.toUpperCase());\n }\n\n private getAxelarGateway(chainId: string): string {\n // Known Axelar gateway contract addresses per chain\n const GATEWAYS: Record<string, string> = {\n \"eip155:1\": \"0x4F449524383f30E6fEeE5e11e6E65C89CDc3df8D\",\n \"eip155:137\": \"0x6f015F16De3fC12C9b5F8E1072e80E8Af7C5B0c4\",\n \"eip155:10\": \"0x7f0a0C7149a46Bf943cCd412da687144b49C8274\",\n \"eip155:42161\": \"0xe432150cce91c13a887f7D836923b4F32401c4DC\",\n \"eip155:8453\": \"0x5a913e3e5dAb48c1B0A5Bf1a31290f2d7eA3C0d4\",\n };\n return GATEWAYS[chainId] ?? \"0x0000000000000000000000000000000000000000\";\n }\n\n private buildGMPData(route: Route, recipient: string): string {\n // Build Axelar GMP deposit data\n // In production, this would encode the full GMP payload\n // For now, return a minimal ABI-encoded representation\n const axelarTo = toAxelarChain(route.toChain) ?? route.toChain;\n const recipientPadded = recipient.padStart(66, \"0x\").slice(0, 66);\n\n // Simplified encoding: just encode the destination chain and recipient\n return `0x${Buffer.from(axelarTo).toString(\"hex\")}${recipientPadded.slice(2)}`;\n }\n\n private mapAxelarStatus(\n axelarStatus: string,\n ): \"pending\" | \"bridging\" | \"completed\" | \"failed\" {\n switch (axelarStatus) {\n case \"executed\":\n case \"confirmed\":\n return \"completed\";\n case \"failed\":\n return \"failed\";\n case \"approved\":\n case \"gateway_call\":\n return \"bridging\";\n default:\n return \"pending\";\n }\n }\n}\n","/**\n * LiFiProvider — LI.FI SDK integration for cross-chain swaps.\n *\n * Integrates with the LI.FI API to discover routes and build\n * transaction data for hop-based cross-chain transfers.\n *\n * When a LI.FI API key is configured, queries the LI.FI API directly.\n * Otherwise falls back to a senderpay backend proxy if configured.\n *\n * @see https://apidocs.li.fi/reference\n */\n\nimport { logger } from \"../../logger\";\nimport type {\n BridgeProvider,\n BridgeProviderId,\n GasEstimate,\n ProviderTransaction,\n Route,\n RouteStatus,\n RouteStep,\n} from \"../types\";\n\n// ─── Known chain ID mapping (LI.FI chain names → CAIP-2) ──────────────\n\nconst LIFI_CHAIN_MAP: Record<string, string> = {\n \"1\": \"eip155:1\", // Ethereum\n \"137\": \"eip155:137\", // Polygon\n \"10\": \"eip155:10\", // Optimism\n \"42161\": \"eip155:42161\", // Arbitrum\n \"8453\": \"eip155:8453\", // Base\n \"43114\": \"eip155:43114\", // Avalanche\n \"56\": \"eip155:56\", // BNB Chain\n \"250\": \"eip155:250\", // Fantom\n \"324\": \"eip155:324\", // zkSync Era\n \"59144\": \"eip155:59144\", // Linea\n \"534352\": \"eip155:534352\", // Scroll\n \"100\": \"eip155:100\", // Gnosis\n \"1101\": \"eip155:1101\", // Polygon zkEVM\n};\n\nconst REVERSE_LIFI_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(LIFI_CHAIN_MAP).map(([k, v]) => [v, k]),\n);\n\nfunction toLiFiChainId(chainId: string): string {\n // Accept CAIP-2 or raw numeric\n const match = REVERSE_LIFI_MAP[chainId];\n if (match) return match;\n if (chainId.startsWith(\"eip155:\")) return chainId.slice(7);\n return chainId;\n}\n\nfunction fromLiFiChainId(chainId: string): string {\n return LIFI_CHAIN_MAP[chainId] ?? `eip155:${chainId}`;\n}\n\n// ─── Default supported chain pairs (EVM ↔ EVM) ────────────────────────\n\nconst SUPPORTED_CHAINS = new Set([\n \"eip155:1\",\n \"eip155:137\",\n \"eip155:10\",\n \"eip155:42161\",\n \"eip155:8453\",\n \"eip155:43114\",\n \"eip155:56\",\n \"eip155:250\",\n \"eip155:324\",\n \"eip155:59144\",\n \"eip155:534352\",\n \"eip155:100\",\n \"eip155:1101\",\n]);\n\n// ─── Known token addresses on Ethereum mainnet (short list) ────────────\n\nconst KNOWN_TOKENS: Record<string, Record<string, string>> = {\n \"eip155:1\": {\n USDC: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n USDT: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n DAI: \"0x6B175474E89094C44Da98b954EedeAC495271d0F\",\n WETH: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n ETH: \"0x0000000000000000000000000000000000000000\",\n },\n \"eip155:137\": {\n USDC: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n USDT: \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\",\n DAI: \"0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063\",\n WMATIC: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\",\n MATIC: \"0x0000000000000000000000000000000000000000\",\n },\n \"eip155:10\": {\n USDC: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n USDT: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n DAI: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n WETH: \"0x4200000000000000000000000000000000000006\",\n ETH: \"0x0000000000000000000000000000000000000000\",\n },\n \"eip155:42161\": {\n USDC: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n USDT: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n DAI: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n WETH: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\",\n ETH: \"0x0000000000000000000000000000000000000000\",\n },\n \"eip155:8453\": {\n USDC: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n WETH: \"0x4200000000000000000000000000000000000006\",\n ETH: \"0x0000000000000000000000000000000000000000\",\n },\n};\n\nfunction resolveTokenAddress(chain: string, token: string): string {\n const chainTokens = KNOWN_TOKENS[chain];\n if (!chainTokens) return token;\n // If it's already an address, return as-is\n if (token.startsWith(\"0x\") && token.length === 42) return token;\n // Look up by symbol\n return chainTokens[token.toUpperCase()] ?? token;\n}\n\n// ─── LiFiProvider ──────────────────────────────────────────────────────\n\nexport interface LiFiProviderConfig {\n /** LI.FI API key (optional) */\n apiKey?: string;\n /** LI.FI API base URL */\n apiUrl?: string;\n /** Backend proxy URL (alternative to direct API) */\n backendUrl?: string;\n}\n\nexport class LiFiProvider implements BridgeProvider {\n readonly id: BridgeProviderId = \"lifi\";\n readonly name = \"LI.FI\";\n private config: Required<Pick<LiFiProviderConfig, \"apiUrl\">> &\n LiFiProviderConfig;\n\n constructor(config?: LiFiProviderConfig) {\n this.config = {\n apiUrl: config?.apiUrl ?? \"https://li.quest/v1\",\n apiKey: config?.apiKey,\n backendUrl: config?.backendUrl,\n };\n }\n\n async getRoutes(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]> {\n if (!this.supportsChainPair(fromChain, toChain)) {\n return [];\n }\n\n const lifiFromChain = toLiFiChainId(fromChain);\n const lifiToChain = toLiFiChainId(toChain);\n const resolvedFromToken = resolveTokenAddress(fromChain, fromToken);\n const resolvedToToken = resolveTokenAddress(toChain, toToken);\n\n // Try backend proxy first\n if (this.config.backendUrl) {\n try {\n const routes = await this.getRoutesViaBackend(\n fromChain,\n toChain,\n resolvedFromToken,\n resolvedToToken,\n amount,\n );\n if (routes.length > 0) return routes;\n } catch (error) {\n logger.warn(\n \"lifi-provider\",\n \"Backend proxy unavailable, falling back to direct API\",\n error,\n );\n }\n }\n\n // Fall through to direct LI.FI API\n try {\n const directRoutes = await this.getRoutesViaDirectAPI(\n lifiFromChain,\n lifiToChain,\n resolvedFromToken,\n resolvedToToken,\n amount,\n );\n return directRoutes;\n } catch (error) {\n logger.warn(\"lifi-provider\", \"Direct LI.FI API call failed\", error);\n return [];\n }\n }\n\n private async getRoutesViaBackend(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]> {\n if (!this.config.backendUrl) return [];\n\n const response = await fetch(`${this.config.backendUrl}/api/routes`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n fromChain,\n toChain,\n fromToken,\n toToken,\n amount,\n provider: \"lifi\",\n }),\n });\n\n if (!response.ok) throw new Error(`Backend returned ${response.status}`);\n\n const data = (await response.json()) as { routes?: Route[] };\n return data.routes ?? [];\n }\n\n private async getRoutesViaDirectAPI(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.config.apiKey) {\n headers[\"x-lifi-api-key\"] = this.config.apiKey;\n }\n\n const params = new URLSearchParams({\n fromChain: fromChain.toString(),\n toChain: toChain.toString(),\n fromToken,\n toToken,\n fromAmount: amount,\n slippage: \"0.5\",\n });\n\n const response = await fetch(\n `${this.config.apiUrl}/advanced/stepTransaction?${params}`,\n { headers },\n );\n\n if (!response.ok) {\n logger.warn(\"lifi-provider\", `LI.FI API returned ${response.status}`);\n return [];\n }\n\n const data = (await response.json()) as {\n transactionRequest?: {\n data: string;\n to: string;\n value: string;\n chainId: number;\n gasLimit: string;\n };\n estimate?: {\n fromAmount: string;\n toAmount: string;\n toAmountMin: string;\n approvalAddress: string;\n fees?: Array<{ amount: string; token: string }>;\n };\n id?: string;\n };\n\n if (!data.transactionRequest || !data.estimate) {\n return [];\n }\n\n // Map LI.FI response to our Route format\n const routes: Route[] = [\n {\n id:\n data.id ??\n `lifi_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,\n provider: \"lifi\",\n fromChain,\n toChain,\n fromToken,\n toToken,\n fromAmount: amount,\n toAmount: data.estimate.toAmount,\n toAmountMin: data.estimate.toAmountMin,\n gasCosts: {\n fromChain: {\n maxFeePerGas: \"0\",\n maxPriorityFeePerGas: \"0\",\n gasLimit: data.transactionRequest.gasLimit ?? \"0\",\n totalCostWei: \"0\",\n totalCostUsd: \"0\",\n },\n toChain: {\n maxFeePerGas: \"0\",\n maxPriorityFeePerGas: \"0\",\n gasLimit: \"0\",\n totalCostWei: \"0\",\n totalCostUsd: \"0\",\n },\n totalUsd: \"0\",\n },\n estimatedTime: 30,\n steps: [\n {\n type: \"approve\",\n chain: fromChain,\n token: fromToken,\n contractAddress: data.transactionRequest.to,\n estimatedGas: data.transactionRequest.gasLimit ?? \"0\",\n },\n {\n type: \"cross-chain\",\n chain: fromChain,\n token: fromToken,\n contractAddress: data.transactionRequest.to,\n data: data.transactionRequest.data,\n estimatedGas: data.transactionRequest.gasLimit ?? \"0\",\n },\n ],\n fee: {\n protocolFee: \"0\",\n },\n summary: `Bridge via LI.FI: ${fromChain} → ${toChain}`,\n },\n ];\n\n return routes;\n }\n\n async getTransactionParams(\n route: Route,\n sender: string,\n recipient: string,\n ): Promise<ProviderTransaction[]> {\n // Build from the route steps\n const txs: ProviderTransaction[] = [];\n const crossChainStep = route.steps.find((s) => s.type === \"cross-chain\");\n\n // Add approve transaction if needed\n const approveStep = route.steps.find((s) => s.type === \"approve\");\n if (approveStep) {\n txs.push({\n type: \"approve\",\n chainId: route.fromChain,\n to: route.fromToken,\n data: approveStep.data ?? \"0x\",\n value: \"0\",\n });\n }\n\n if (crossChainStep?.data) {\n txs.push({\n type: \"cross-chain\",\n chainId: route.fromChain,\n to: crossChainStep.contractAddress,\n data: crossChainStep.data,\n value: route.fromAmount,\n });\n }\n\n // If no explicit data is available, we need the API to build it\n if (txs.length === 0) {\n try {\n const params = new URLSearchParams({\n fromChain: toLiFiChainId(route.fromChain),\n toChain: toLiFiChainId(route.toChain),\n fromToken: route.fromToken,\n toToken: route.toToken,\n fromAmount: route.fromAmount,\n fromAddress: sender,\n toAddress: recipient,\n slippage: \"0.5\",\n });\n\n const response = await fetch(\n `${this.config.apiUrl}/advanced/stepTransaction?${params}`,\n {\n headers: this.config.apiKey\n ? { \"x-lifi-api-key\": this.config.apiKey }\n : {},\n },\n );\n\n if (response.ok) {\n const data = (await response.json()) as {\n transactionRequest?: {\n data: string;\n to: string;\n value: string;\n chainId: number;\n };\n };\n if (data.transactionRequest) {\n txs.push({\n type: \"cross-chain\",\n chainId: route.fromChain,\n to: data.transactionRequest.to,\n data: data.transactionRequest.data,\n value: data.transactionRequest.value,\n });\n }\n }\n } catch (error) {\n logger.warn(\n \"lifi-provider\",\n \"Failed to fetch transaction params from API\",\n error,\n );\n throw new Error(\n \"Unable to build transaction parameters for LI.FI route\",\n );\n }\n }\n\n return txs;\n }\n\n async getRouteStatus(bridgeReference: string): Promise<RouteStatus> {\n try {\n const headers: Record<string, string> = {};\n if (this.config.apiKey) {\n headers[\"x-lifi-api-key\"] = this.config.apiKey;\n }\n\n const response = await fetch(\n `${this.config.apiUrl}/status?txHash=${bridgeReference}`,\n { headers },\n );\n\n if (!response.ok) {\n return { status: \"pending\" };\n }\n\n const data = (await response.json()) as {\n status?: string;\n receiving?: { txHash?: string };\n };\n\n const lifiStatus = data.status ?? \"pending\";\n\n return {\n status: this.mapLiFiStatus(lifiStatus),\n toTxHash: data.receiving?.txHash,\n currentStep: lifiStatus,\n };\n } catch {\n return { status: \"pending\" };\n }\n }\n\n supportsChainPair(fromChain: string, toChain: string): boolean {\n return SUPPORTED_CHAINS.has(fromChain) && SUPPORTED_CHAINS.has(toChain);\n }\n\n supportsToken(chain: string, token: string): boolean {\n const chainTokens = KNOWN_TOKENS[chain];\n if (!chainTokens) return false;\n if (token.startsWith(\"0x\") && token.length === 42) {\n const normalized = token.toLowerCase();\n return Object.values(chainTokens).some(\n (v) => v.toLowerCase() === normalized,\n );\n }\n return Object.keys(chainTokens).some(\n (k) => k.toUpperCase() === token.toUpperCase(),\n );\n }\n\n private mapLiFiStatus(\n lifiStatus: string,\n ): \"pending\" | \"bridging\" | \"completed\" | \"failed\" {\n switch (lifiStatus) {\n case \"DONE\":\n case \"COMPLETED\":\n return \"completed\";\n case \"FAILED\":\n return \"failed\";\n case \"BRIDGE\":\n case \"RECEIVED\":\n return \"bridging\";\n default:\n return \"pending\";\n }\n }\n}\n","/**\n * Chain Route Engine\n *\n * Core engine for cross-chain intent routing. Discovers routes across\n * multiple bridge providers, aggregates quotes, and handles execution.\n *\n * Supports a pluggable provider registration mechanism so new bridges\n * (Socket, Across, etc.) can be added without modifying this engine.\n *\n * @see docs/features/chain-abstraction.md §3\n */\n\nimport { logger } from \"../logger\";\nimport { formatUnits } from \"../token/units\";\nimport type {\n BridgeProvider,\n BridgeProviderId,\n ChainAbstractionConfig,\n ChainAbstractionErrorCode,\n CostComparison,\n CostComparisonOperation,\n CostComparisonOptions,\n ExecuteOptions,\n ExecuteRouteResult,\n Quote,\n QuoteOptions,\n QuoteSortBy,\n Route,\n RouteStatus,\n} from \"./types\";\nimport { ChainAbstractionError } from \"./types\";\n\n// ─── Default provider configuration ────────────────────────────────────\n\nconst DEFAULT_QUOTE_CACHE_TTL = 30_000; // 30 seconds\nconst DEFAULT_STATUS_POLL_INTERVAL = 2_000; // 2 seconds\nconst DEFAULT_SLIPPAGE = 0.5; // 0.5%\n\n// ─── Known native token symbols per chain ──────────────────────────────\n\nconst NATIVE_TOKEN_SYMBOLS: Record<string, string> = {\n \"eip155:1\": \"ETH\",\n \"eip155:10\": \"ETH\",\n \"eip155:42161\": \"ETH\",\n \"eip155:8453\": \"ETH\",\n \"eip155:137\": \"MATIC\",\n \"eip155:43114\": \"AVAX\",\n \"eip155:56\": \"BNB\",\n \"eip155:250\": \"FTM\",\n \"eip155:324\": \"ETH\",\n \"eip155:59144\": \"ETH\",\n \"eip155:534352\": \"ETH\",\n \"eip155:100\": \"xDai\",\n \"eip155:1101\": \"ETH\",\n};\n\nconst NATIVE_TOKEN_DECIMALS: Record<string, number> = {\n \"eip155:1\": 18,\n \"eip155:10\": 18,\n \"eip155:42161\": 18,\n \"eip155:8453\": 18,\n \"eip155:137\": 18,\n \"eip155:43114\": 18,\n \"eip155:56\": 18,\n \"eip155:250\": 18,\n \"eip155:324\": 18,\n \"eip155:59144\": 18,\n \"eip155:534352\": 18,\n \"eip155:100\": 18,\n \"eip155:1101\": 18,\n};\n\n// ─── Cache entry for quotes ────────────────────────────────────────────\n\ninterface CachedQuote {\n routes: Route[];\n cachedAt: number;\n fromChain: string;\n toChain: string;\n fromToken: string;\n toToken: string;\n amount: string;\n}\n\n// ─── RouteEngine ───────────────────────────────────────────────────────\n\nexport class RouteEngine {\n private providers: Map<BridgeProviderId, BridgeProvider> = new Map();\n private config: Required<\n Pick<\n ChainAbstractionConfig,\n \"quoteCacheTtl\" | \"statusPollInterval\" | \"defaultSlippage\"\n >\n > &\n ChainAbstractionConfig;\n\n /** Simple in-memory quote cache (route-level, before formatting) */\n private quoteCache: Map<string, CachedQuote> = new Map();\n\n /** Route store: maps routeId → Route for execution lookup */\n private routeStore: Map<string, Route> = new Map();\n\n constructor(config?: ChainAbstractionConfig) {\n this.config = {\n quoteCacheTtl: config?.quoteCacheTtl ?? DEFAULT_QUOTE_CACHE_TTL,\n statusPollInterval:\n config?.statusPollInterval ?? DEFAULT_STATUS_POLL_INTERVAL,\n defaultSlippage: config?.defaultSlippage ?? DEFAULT_SLIPPAGE,\n backendUrl: config?.backendUrl,\n lifiApiKey: config?.lifiApiKey,\n axelarConfig: config?.axelarConfig,\n };\n }\n\n // ── Provider Registration ───────────────────────────────────────────\n\n /**\n * Register a bridge provider with the route engine.\n * Providers can be added at any time; they are discovered\n * on each getQuote() call.\n */\n registerProvider(provider: BridgeProvider): void {\n if (this.providers.has(provider.id)) {\n logger.warn(\n \"route-engine\",\n `Overwriting existing provider: ${provider.id}`,\n );\n }\n this.providers.set(provider.id, provider);\n logger.debug(\"route-engine\", `Registered provider: ${provider.id}`);\n }\n\n /**\n * Unregister a previously registered provider.\n */\n unregisterProvider(providerId: BridgeProviderId): void {\n this.providers.delete(providerId);\n }\n\n /**\n * Get a registered provider by ID.\n */\n getProvider(providerId: BridgeProviderId): BridgeProvider | undefined {\n return this.providers.get(providerId);\n }\n\n /**\n * List all registered providers.\n */\n listProviders(): BridgeProvider[] {\n return Array.from(this.providers.values());\n }\n\n // ── Quote Discovery ─────────────────────────────────────────────────\n\n /**\n * Get cross-chain quotes for a given transfer.\n *\n * Discovers routes from all registered providers that support the\n * requested chain pair and token, then formats them into unified\n * Quote objects sorted by the specified strategy.\n *\n * @param fromChain - Source chain CAIP-2 (e.g. \"eip155:1\" for Ethereum)\n * @param toChain - Destination chain CAIP-2\n * @param token - Token to transfer (symbol or contract address)\n * @param amount - Amount in raw form (smallest unit)\n * @param options - Optional quote options (slippage, sort, provider filters)\n * @returns Sorted array of Quote objects\n *\n * @throws {ChainAbstractionError} if no routes are found or providers\n * are unavailable\n */\n async getQuote(\n fromChain: string,\n toChain: string,\n token: string,\n amount: string,\n options?: QuoteOptions,\n ): Promise<Quote[]> {\n if (BigInt(amount) <= 0n) {\n throw new ChainAbstractionError(\n \"invalid_config\",\n \"Amount must be positive\",\n );\n }\n\n // Check cache\n const cacheKey = this.buildCacheKey(fromChain, toChain, token, amount);\n const cached = this.quoteCache.get(cacheKey);\n if (cached && Date.now() - cached.cachedAt < this.config.quoteCacheTtl) {\n logger.debug(\"route-engine\", \"Returning cached quotes\");\n return this.formatAndSortQuotes(cached.routes, options);\n }\n\n // Discover routes from all registered providers that support this pair\n const allRoutes: Route[] = [];\n const errors: Array<{ provider: BridgeProviderId; error: string }> = [];\n\n const activeProviders = this.getActiveProviders(\n fromChain,\n toChain,\n token,\n options,\n );\n\n if (activeProviders.length === 0) {\n throw new ChainAbstractionError(\n \"no_routes_available\",\n `No providers available for chain pair ${fromChain} → ${toChain} with token ${token}`,\n );\n }\n\n // Query all providers in parallel\n const results = await Promise.allSettled(\n activeProviders.map((provider) =>\n provider\n .getRoutes(fromChain, toChain, token, token, amount)\n .catch((err: Error) => {\n errors.push({ provider: provider.id, error: err.message });\n return [] as Route[];\n }),\n ),\n );\n\n for (const result of results) {\n if (result.status === \"fulfilled\") {\n allRoutes.push(...result.value);\n }\n }\n\n if (allRoutes.length === 0) {\n // If there were errors, throw with details\n if (errors.length > 0) {\n throw new ChainAbstractionError(\n \"no_routes_available\",\n `No routes found from ${fromChain} to ${toChain}. Provider errors: ${errors.map((e) => `${e.provider}: ${e.error}`).join(\"; \")}`,\n { errors },\n );\n }\n throw new ChainAbstractionError(\n \"no_routes_available\",\n `No routes available from ${fromChain} to ${toChain} for token ${token}`,\n );\n }\n\n // Store in route store and cache the raw routes\n for (const route of allRoutes) {\n this.routeStore.set(route.id, route);\n }\n\n this.quoteCache.set(cacheKey, {\n routes: allRoutes,\n cachedAt: Date.now(),\n fromChain,\n toChain,\n fromToken: token,\n toToken: token,\n amount,\n });\n\n // Clean stale cache entries\n this.cleanCache();\n\n return this.formatAndSortQuotes(allRoutes, options);\n }\n\n // ── Route Execution ─────────────────────────────────────────────────\n\n /**\n * Execute a cross-chain route from a selected quote.\n *\n * Returns transaction hashes and a bridge reference for status tracking.\n * Actual transaction sending is handled by the caller (e.g., ConnectorManager).\n *\n * @param quote - The selected Quote to execute\n * @param recipient - Recipient address on the destination chain\n * @param options - Execution options (autoApprove, recipient)\n * @returns ExecuteRouteResult with transaction tracking info\n *\n * @throws {ChainAbstractionError} if the route is expired, provider\n * is unavailable, or execution fails\n */\n async executeRoute(\n quote: Quote,\n recipient: string,\n options?: ExecuteOptions,\n ): Promise<ExecuteRouteResult> {\n // Validate quote expiry\n if (Date.now() > quote.expiresAt) {\n throw new ChainAbstractionError(\n \"route_expired\",\n \"This quote has expired. Please fetch a new quote.\",\n );\n }\n\n // Find the route from route store\n const route = this.routeStore.get(quote.routeId);\n if (!route) {\n throw new ChainAbstractionError(\n \"no_routes_available\",\n `Route ${quote.routeId} not found. It may have expired.`,\n );\n }\n\n const provider = this.providers.get(quote.provider);\n if (!provider) {\n throw new ChainAbstractionError(\n \"provider_unavailable\",\n `Provider ${quote.provider} is not registered`,\n );\n }\n\n const resolvedRecipient = options?.recipient ?? recipient;\n\n try {\n // Get transaction parameters from the provider\n const txParams = await provider.getTransactionParams(\n route,\n \"sender\",\n resolvedRecipient,\n );\n\n // Check if approve is needed\n const approveTx = txParams.find((tx) => tx.type === \"approve\");\n const crossChainTx = txParams.find((tx) => tx.type === \"cross-chain\");\n\n if (!crossChainTx) {\n throw new ChainAbstractionError(\n \"execution_failed\",\n \"No cross-chain transaction parameters returned by provider\",\n );\n }\n\n if (approveTx && options?.autoApprove !== false) {\n // Signal that approve is needed\n throw new ChainAbstractionError(\n \"approve_needed\",\n `Token approval required for ${quote.fromTokenSymbol} on ${quote.fromChain}`,\n {\n approveParams: approveTx,\n },\n );\n }\n\n return {\n fromTxHash: \"pending\", // Will be populated after actual sending\n fromChain: quote.fromChain,\n toChain: quote.toChain,\n status: \"pending\",\n bridgeReference: quote.routeId,\n estimatedCompletionAt:\n Date.now() + quote.estimatedArrivalSeconds * 1000,\n };\n } catch (error) {\n if (error instanceof ChainAbstractionError) throw error;\n throw new ChainAbstractionError(\n \"execution_failed\",\n `Failed to execute route: ${(error as Error).message}`,\n );\n }\n }\n\n // ── Cost Comparison ─────────────────────────────────────────────────\n\n /**\n * Compare costs of performing an operation across multiple chains.\n *\n * Useful for helping users decide which chain is cheapest for\n * a given operation (send, swap, cross-chain transfer).\n *\n * @param operation - The operation type to compare\n * @param chains - Array of CAIP-2 chain IDs to compare\n * @param options - Optional comparison parameters\n * @returns Array of CostComparison sorted by total cost ascending\n */\n async compareCosts(\n operation: CostComparisonOperation,\n chains: string[],\n options?: CostComparisonOptions,\n ): Promise<CostComparison[]> {\n if (chains.length === 0) {\n return [];\n }\n\n const results: CostComparison[] = [];\n const errors: Array<{ chain: string; error: string }> = [];\n\n const comparisons = await Promise.allSettled(\n chains.map(async (chain) => {\n return this.evaluateChainCost(chain, operation, options);\n }),\n );\n\n for (let i = 0; i < comparisons.length; i++) {\n const result = comparisons[i];\n const chain = chains[i];\n if (result.status === \"fulfilled\") {\n results.push(result.value);\n } else {\n errors.push({\n chain,\n error: result.reason?.message ?? \"Unknown error\",\n });\n }\n }\n\n if (results.length === 0 && errors.length > 0) {\n throw new ChainAbstractionError(\n \"backend_unavailable\",\n `Failed to evaluate costs for any chain: ${errors.map((e) => `${e.chain}: ${e.error}`).join(\"; \")}`,\n );\n }\n\n // Sort by total cost ascending\n return results.sort(\n (a, b) => parseFloat(a.totalCost) - parseFloat(b.totalCost),\n );\n }\n\n // ── Route Status ────────────────────────────────────────────────────\n\n /**\n * Poll the current status of a cross-chain route execution.\n *\n * @param bridgeReference - The reference ID returned from executeRoute\n * @returns Current RouteStatus\n */\n async getRouteStatus(bridgeReference: string): Promise<RouteStatus> {\n // Try to find the provider by scanning route IDs\n // In production, store the provider mapping at execution time\n for (const [, provider] of this.providers) {\n try {\n const status = await provider.getRouteStatus(bridgeReference);\n return status;\n } catch {}\n }\n\n return { status: \"pending\" };\n }\n\n // ── Internal Helpers ────────────────────────────────────────────────\n\n /**\n * Get the subset of providers that support the given chain pair and token.\n * Filters by preferred/excluded bridges if configured.\n */\n private getActiveProviders(\n fromChain: string,\n toChain: string,\n token: string,\n options?: QuoteOptions,\n ): BridgeProvider[] {\n let candidates = Array.from(this.providers.values());\n\n // Filter by provider support\n candidates = candidates.filter((p) =>\n p.supportsChainPair(fromChain, toChain),\n );\n\n // Apply preferred bridges filter\n if (options?.preferredBridges && options.preferredBridges.length > 0) {\n const preferredSet = new Set(options.preferredBridges);\n candidates = candidates.filter((p) => preferredSet.has(p.id));\n }\n\n // Apply exclude bridges filter\n if (options?.excludeBridges && options.excludeBridges.length > 0) {\n const excludeSet = new Set(options.excludeBridges);\n candidates = candidates.filter((p) => !excludeSet.has(p.id));\n }\n\n return candidates;\n }\n\n /**\n * Format raw routes into display-ready Quote objects and sort them.\n */\n private formatAndSortQuotes(\n routes: Route[],\n options?: QuoteOptions,\n ): Quote[] {\n const fromDecimals =\n NATIVE_TOKEN_DECIMALS[routes[0]?.fromChain ?? \"eip155:1\"] ?? 18;\n const toDecimals =\n NATIVE_TOKEN_DECIMALS[routes[0]?.toChain ?? \"eip155:1\"] ?? 18;\n\n const quotes: Quote[] = routes.map((route) => {\n const toAmount = BigInt(route.toAmount);\n const toAmountMin = BigInt(route.toAmountMin);\n const fromAmount = BigInt(route.fromAmount);\n\n const expiry = this.config.quoteCacheTtl;\n\n let exchangeRate = \"0\";\n if (fromAmount > 0n) {\n // Calculate exchange rate: toAmount / fromAmount\n // Scale to fixed precision using bigint arithmetic to avoid precision loss\n const scaled = (toAmount * 10_000n) / fromAmount;\n const whole = scaled / 10_000n;\n const remainder = scaled % 10_000n;\n exchangeRate = `${whole}.${remainder.toString().padStart(4, \"0\")}`;\n }\n\n const priceImpact = \"0\";\n const fromFormatted = formatUnits(fromAmount, fromDecimals);\n const toFormatted = formatUnits(toAmount, toDecimals);\n const toMinFormatted = formatUnits(toAmountMin, toDecimals);\n\n return {\n routeId: route.id,\n provider: route.provider,\n fromChain: route.fromChain,\n toChain: route.toChain,\n fromTokenSymbol: this.resolveTokenSymbol(\n route.fromChain,\n route.fromToken,\n ),\n toTokenSymbol: this.resolveTokenSymbol(route.toChain, route.toToken),\n fromAmountFormatted: fromFormatted,\n toAmountFormatted: toFormatted,\n toAmountMinFormatted: toMinFormatted,\n exchangeRate,\n priceImpact,\n totalGasCostUsd: route.gasCosts.totalUsd,\n totalFeeUsd: this.formatFeeUsd(route),\n netReceiveFormatted: toFormatted,\n estimatedArrival: this.formatEstimatedTime(route.estimatedTime),\n estimatedArrivalSeconds: route.estimatedTime,\n summary: route.summary,\n needsApprove: route.steps.some((s) => s.type === \"approve\"),\n expiresAt: Date.now() + expiry,\n };\n });\n\n // Sort by the requested strategy\n const sortBy = options?.sortBy ?? \"netReceive\";\n return this.sortQuotes(quotes, sortBy);\n }\n\n /**\n * Sort quotes by the specified strategy.\n */\n private sortQuotes(quotes: Quote[], sortBy: QuoteSortBy): Quote[] {\n const sorted = [...quotes];\n\n switch (sortBy) {\n case \"fastest\":\n sorted.sort(\n (a, b) => a.estimatedArrivalSeconds - b.estimatedArrivalSeconds,\n );\n break;\n case \"cheapest\":\n sorted.sort((a, b) => {\n const gasDiff =\n parseFloat(a.totalGasCostUsd) - parseFloat(b.totalGasCostUsd);\n if (gasDiff !== 0) return gasDiff;\n return parseFloat(a.totalFeeUsd) - parseFloat(b.totalFeeUsd);\n });\n break;\n case \"netReceive\":\n default:\n sorted.sort((a, b) => {\n const aNet = parseFloat(a.netReceiveFormatted);\n const bNet = parseFloat(b.netReceiveFormatted);\n return bNet - aNet; // descending: most received first\n });\n break;\n }\n\n return sorted;\n }\n\n /**\n * Resolve a token symbol from a chain and token address.\n */\n private resolveTokenSymbol(chain: string, token: string): string {\n // Check if it's a native token\n if (token === \"0x0000000000000000000000000000000000000000\") {\n return NATIVE_TOKEN_SYMBOLS[chain] ?? \"UNKNOWN\";\n }\n\n // Check known tokens\n for (const [chainId, tokens] of Object.entries(KNOWN_TOKEN_LIST)) {\n if (chainId === chain) {\n for (const [symbol, address] of Object.entries(tokens)) {\n if (address.toLowerCase() === token.toLowerCase()) {\n return symbol;\n }\n }\n }\n }\n\n // Fall back to the token address abbreviation\n return token.startsWith(\"0x\") ? token.slice(0, 10) : token;\n }\n\n /**\n * Format the total fee (protocol + integration) as a USD string.\n */\n private formatFeeUsd(route: Route): string {\n const protocolFee = BigInt(route.fee.protocolFee);\n const integrationFee = route.fee.integrationFee\n ? BigInt(route.fee.integrationFee)\n : 0n;\n const total = protocolFee + integrationFee;\n\n if (total === 0n) return \"0\";\n return formatUnits(total, 18);\n }\n\n /**\n * Format estimated time as human-readable string.\n */\n private formatEstimatedTime(seconds: number): string {\n if (seconds < 60) {\n return `~${seconds} seconds`;\n } else if (seconds < 3600) {\n return `~${Math.floor(seconds / 60)} minutes`;\n } else {\n return `~${(seconds / 3600).toFixed(1)} hours`;\n }\n }\n\n /**\n * Build a cache key from quote parameters.\n */\n private buildCacheKey(\n fromChain: string,\n toChain: string,\n token: string,\n amount: string,\n ): string {\n return `${fromChain}:${toChain}:${token}:${amount}`;\n }\n\n /**\n * Get cached routes by route ID.\n */\n /**\n * Clean stale cache entries.\n */\n private cleanCache(): void {\n const now = Date.now();\n for (const [key, entry] of this.quoteCache.entries()) {\n if (now - entry.cachedAt > this.config.quoteCacheTtl * 2) {\n this.quoteCache.delete(key);\n }\n }\n }\n\n /**\n * Evaluate the cost of an operation on a single chain.\n */\n private async evaluateChainCost(\n chain: string,\n operation: CostComparisonOperation,\n options?: CostComparisonOptions,\n ): Promise<CostComparison> {\n const chainName = this.getChainName(chain);\n const nativeSymbol = NATIVE_TOKEN_SYMBOLS[chain] ?? \"ETH\";\n\n // Simulate gas cost estimation based on operation type\n const gasUnits = this.getEstimatedGasUnits(operation);\n const GAS_PRICE_WEI = 50_000_000_000n;\n const ETH_DECIMALS = 1_000_000_000_000_000_000n; // 10^18\n const gasCostEthNum = Number((gasUnits * GAS_PRICE_WEI) / ETH_DECIMALS);\n const gasCost = gasCostEthNum.toFixed(6);\n const nativePriceUsd = this.getNativeTokenPriceUsd(chain);\n\n const gasCostUsd = (parseFloat(gasCost) * nativePriceUsd).toFixed(2);\n let fee = \"0\";\n\n if (operation === \"cross_chain_transfer\" && options?.includeCrossChain) {\n // Simulate bridge fee for cross-chain operations\n fee = (0.5 * nativePriceUsd).toFixed(2);\n }\n\n const totalCost = (parseFloat(gasCostUsd) + parseFloat(fee)).toFixed(2);\n\n return {\n chain,\n chainName,\n gasCost: gasCostUsd,\n fee,\n totalCost,\n time: this.getEstimatedTime(chain, operation),\n congestionLevel: this.getCongestionLevel(chain),\n };\n }\n\n /**\n * Get estimated gas units for a given operation type.\n */\n private getEstimatedGasUnits(operation: CostComparisonOperation): bigint {\n switch (operation) {\n case \"send_native\":\n return 21_000n;\n case \"send_erc20\":\n return 65_000n;\n case \"swap\":\n return 150_000n;\n case \"cross_chain_transfer\":\n return 300_000n;\n }\n }\n\n /**\n * Get estimated time in seconds for an operation on a chain.\n */\n private getEstimatedTime(\n chain: string,\n _operation: CostComparisonOperation,\n ): number {\n // Simplified: based on chain block time\n const blockTimes: Record<string, number> = {\n \"eip155:1\": 12,\n \"eip155:10\": 2,\n \"eip155:42161\": 0.25,\n \"eip155:8453\": 2,\n \"eip155:137\": 2,\n };\n\n const blocksNeeded = 2;\n const blockTime = blockTimes[chain] ?? 12;\n return Math.round(blockTime * blocksNeeded);\n }\n\n /**\n * Get a human-readable chain name.\n */\n private getChainName(chain: string): string {\n const names: Record<string, string> = {\n \"eip155:1\": \"Ethereum\",\n \"eip155:137\": \"Polygon\",\n \"eip155:10\": \"Optimism\",\n \"eip155:42161\": \"Arbitrum\",\n \"eip155:8453\": \"Base\",\n \"eip155:43114\": \"Avalanche\",\n \"eip155:56\": \"BNB Chain\",\n \"eip155:250\": \"Fantom\",\n \"eip155:324\": \"zkSync Era\",\n \"eip155:59144\": \"Linea\",\n \"eip155:534352\": \"Scroll\",\n \"eip155:100\": \"Gnosis\",\n \"eip155:1101\": \"Polygon zkEVM\",\n };\n return names[chain] ?? chain;\n }\n\n /**\n * Get native token price in USD (simplified).\n */\n private getNativeTokenPriceUsd(chain: string): number {\n const prices: Record<string, number> = {\n \"eip155:1\": 3500,\n \"eip155:10\": 3500,\n \"eip155:42161\": 3500,\n \"eip155:8453\": 3500,\n \"eip155:137\": 0.7,\n \"eip155:43114\": 35,\n \"eip155:56\": 580,\n \"eip155:250\": 0.5,\n \"eip155:324\": 3500,\n \"eip155:59144\": 3500,\n \"eip155:534352\": 3500,\n \"eip155:100\": 1,\n \"eip155:1101\": 3500,\n };\n return prices[chain] ?? 100;\n }\n\n /**\n * Get congestion level for a chain.\n */\n private getCongestionLevel(chain: string): \"low\" | \"medium\" | \"high\" {\n const congestion: Record<string, \"low\" | \"medium\" | \"high\"> = {\n \"eip155:1\": \"high\",\n \"eip155:10\": \"medium\",\n \"eip155:42161\": \"medium\",\n \"eip155:8453\": \"low\",\n \"eip155:137\": \"medium\",\n };\n return congestion[chain] ?? \"low\";\n }\n}\n\n// ─── Known token list for symbol resolution ────────────────────────────\n\nconst KNOWN_TOKEN_LIST: Record<string, Record<string, string>> = {\n \"eip155:1\": {\n USDC: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n USDT: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n DAI: \"0x6B175474E89094C44Da98b954EedeAC495271d0F\",\n WETH: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n },\n \"eip155:137\": {\n USDC: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n USDT: \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\",\n DAI: \"0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063\",\n WMATIC: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\",\n },\n \"eip155:10\": {\n USDC: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n USDT: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n DAI: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n WETH: \"0x4200000000000000000000000000000000000006\",\n },\n \"eip155:42161\": {\n USDC: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n USDT: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n DAI: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n WETH: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\",\n },\n \"eip155:8453\": {\n USDC: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n WETH: \"0x4200000000000000000000000000000000000006\",\n },\n};\n\n// ─── Factory function ──────────────────────────────────────────────────\n\nexport function createRouteEngine(\n config?: ChainAbstractionConfig,\n): RouteEngine {\n return new RouteEngine(config);\n}\n","/**\n * Chain Abstraction Types\n *\n * Core type definitions for cross-chain intent routing (Chain Abstraction).\n * Defines Quote, RouteExecution, CostComparison, and supporting types\n * for the Route Engine and Bridge Providers.\n *\n * @see docs/features/chain-abstraction.md\n */\n\n// ─── Route Discovery ───────────────────────────────────────────────────\n\n/** Bridge provider identifier */\nexport type BridgeProviderId = \"lifi\" | \"axelar\" | \"socket\" | \"across\";\n\n/**\n * Route step within a cross-chain route.\n * Cross-chain routes typically decompose into:\n * 1. Approve (optional) on source chain\n * 2. Swap on source chain (optional)\n * 3. Cross-chain bridge transfer\n * 4. Swap on destination chain (optional)\n */\nexport interface RouteStep {\n type: \"approve\" | \"swap\" | \"cross-chain\";\n chain: string;\n token: string;\n contractAddress: string;\n data?: string;\n /** EIP-1559 formatted gas estimate (bigint serialized as string) */\n estimatedGas: string;\n}\n\n/** Gas cost estimate for a single chain in a cross-chain route */\nexport interface GasEstimate {\n /** Max fee per gas in wei (serialized bigint) */\n maxFeePerGas: string;\n /** Max priority fee in wei (serialized bigint) */\n maxPriorityFeePerGas: string;\n /** Estimated gas units */\n gasLimit: string;\n /** Total estimated gas cost in wei */\n totalCostWei: string;\n /** Total estimated gas cost in USD string */\n totalCostUsd: string;\n}\n\n/**\n * A discovered cross-chain route returned by a bridge provider.\n */\nexport interface Route {\n /** Unique route identifier */\n id: string;\n /** The bridge provider that discovered this route */\n provider: BridgeProviderId;\n /** Source chain CAIP-2 identifier */\n fromChain: string;\n /** Destination chain CAIP-2 identifier */\n toChain: string;\n /** Source token contract address (or native token symbol for ETH/MATIC/SOL) */\n fromToken: string;\n /** Destination token contract address */\n toToken: string;\n /** Input amount in raw form (smallest unit, e.g. wei) */\n fromAmount: string;\n /** Expected output amount in raw form */\n toAmount: string;\n /** Minimum guaranteed output amount (accounting for slippage) */\n toAmountMin: string;\n /** Gas cost breakdown for each chain involved */\n gasCosts: {\n fromChain: GasEstimate;\n toChain: GasEstimate;\n totalUsd: string;\n };\n /** Estimated time in seconds */\n estimatedTime: number;\n /** Decomposition of this route into individual steps */\n steps: RouteStep[];\n /** Fee breakdown */\n fee: {\n protocolFee: string;\n integrationFee?: string;\n };\n /** Human-readable summary of the route */\n summary: string;\n}\n\n// ─── Quote ─────────────────────────────────────────────────────────────\n\n/** Sorting options for quote aggregation */\nexport type QuoteSortBy = \"netReceive\" | \"fastest\" | \"cheapest\";\n\nexport interface QuoteOptions {\n /** Slippage tolerance in percent (default 0.5) */\n slippage?: number;\n /** Preferred bridge providers */\n preferredBridges?: BridgeProviderId[];\n /** Bridge providers to exclude */\n excludeBridges?: BridgeProviderId[];\n /** Sort order for returned quotes */\n sortBy?: QuoteSortBy;\n}\n\n/**\n * A unified cross-chain quote ready for display and execution.\n * Aggregates data from a Route with formatting and cost metadata.\n */\nexport interface Quote {\n /** Reference to the originating route ID */\n routeId: string;\n /** Bridge provider */\n provider: BridgeProviderId;\n /** Source chain CAIP-2 */\n fromChain: string;\n /** Destination chain CAIP-2 */\n toChain: string;\n /** Source token symbol (e.g. \"USDC\") */\n fromTokenSymbol: string;\n /** Destination token symbol */\n toTokenSymbol: string;\n /** Source amount, formatted for display (e.g. \"100.00\") */\n fromAmountFormatted: string;\n /** Destination amount, formatted for display */\n toAmountFormatted: string;\n /** Minimum guaranteed output, formatted */\n toAmountMinFormatted: string;\n /** Effective exchange rate (1 fromToken = ? toToken) */\n exchangeRate: string;\n /** Price impact percentage */\n priceImpact: string;\n /** Total gas cost in USD */\n totalGasCostUsd: string;\n /** Total protocol and integration fees in USD */\n totalFeeUsd: string;\n /** Net receive amount after gas + fees, formatted */\n netReceiveFormatted: string;\n /** Estimated arrival time as human-readable string */\n estimatedArrival: string;\n /** Estimated arrival in seconds */\n estimatedArrivalSeconds: number;\n /** Human-readable step summary */\n summary: string;\n /** Whether this quote requires an approve transaction before execution */\n needsApprove: boolean;\n /** Approve target address (token contract to approve) */\n approveTarget?: string;\n /** Approve spender address (bridge contract) */\n approveSpender?: string;\n /** Approve amount in raw form */\n approveAmount?: string;\n /** Timestamp when this quote expires (ms) */\n expiresAt: number;\n}\n\n// ─── Route Status ─────────────────────────────────────────────────────\n\nexport type RouteStatusValue = \"pending\" | \"bridging\" | \"completed\" | \"failed\";\n\nexport interface RouteStatus {\n status: RouteStatusValue;\n fromTxHash?: string;\n toTxHash?: string;\n currentStep?: string;\n /** Progress percentage 0-100 */\n progress?: number;\n /** Estimated completion timestamp (epoch ms) */\n estimatedCompletionAt?: number;\n /** Error message if status === \"failed\" */\n error?: string;\n}\n\n// ─── Route Execution ───────────────────────────────────────────────────\n\nexport interface ExecuteOptions {\n /** Recipient address on the destination chain */\n recipient?: string;\n /** Whether to automatically handle approve transactions */\n autoApprove?: boolean;\n /** Custom approve amount in raw form (overrides default) */\n approveAmount?: string;\n}\n\nexport interface ExecuteRouteResult {\n /** Source chain transaction hash */\n fromTxHash: string;\n /** Source chain CAIP-2 */\n fromChain: string;\n /** Destination chain transaction hash (populated once bridging completes) */\n toTxHash?: string;\n /** Destination chain CAIP-2 */\n toChain: string;\n /** Current execution status */\n status: RouteStatusValue;\n /** Bridge provider reference ID (for status polling) */\n bridgeReference?: string;\n /** Estimated completion timestamp (epoch ms) */\n estimatedCompletionAt?: number;\n /** Error message if status === \"failed\" */\n error?: string;\n}\n\n// ─── Cost Comparison ─────────────────────────────────────────────────\n\nexport type CostComparisonOperation =\n | \"send_native\"\n | \"send_erc20\"\n | \"swap\"\n | \"cross_chain_transfer\";\n\nexport interface CostComparisonOptions {\n /** Token contract address relevant to the operation */\n token?: string;\n /** Amount in raw form */\n amount?: string;\n /** Include cross-chain fees in comparison */\n includeCrossChain?: boolean;\n}\n\nexport interface CostComparison {\n /** Chain CAIP-2 identifier */\n chain: string;\n /** Human-readable chain name */\n chainName: string;\n /** Gas cost in USD */\n gasCost: string;\n /** Protocol/bridge fees in USD */\n fee: string;\n /** Total cost (gas + fees) in USD */\n totalCost: string;\n /** Estimated time in seconds */\n time: number;\n /** Congestion level (optional) */\n congestionLevel?: \"low\" | \"medium\" | \"high\";\n}\n\n// ─── Chain Abstraction Config ──────────────────────────────────────────\n\nexport interface ChainAbstractionConfig {\n /** Senderpay backend URL (for proxy-based route discovery) */\n backendUrl?: string;\n /** Quote cache TTL in ms (default 30000) */\n quoteCacheTtl?: number;\n /** Status polling interval in ms (default 2000) */\n statusPollInterval?: number;\n /** Default slippage in percent (default 0.5) */\n defaultSlippage?: number;\n /** LiFi SDK API key (optional, for direct SDK usage) */\n lifiApiKey?: string;\n /** Axelar API key / config (optional, for direct SDK usage) */\n axelarConfig?: {\n apiUrl?: string;\n };\n}\n\n// ─── Bridge Provider Interface ─────────────────────────────────────────\n\n/**\n * Abstract interface for a cross-chain bridge provider.\n * Each provider (LiFi, Axelar, Socket, Across) implements this\n * to be registered with the RouteEngine.\n */\nexport interface BridgeProvider {\n /** Unique provider identifier */\n readonly id: BridgeProviderId;\n /** Human-readable provider name */\n readonly name: string;\n\n /**\n * Discover available routes for a cross-chain transfer.\n *\n * @param fromChain - Source chain CAIP-2\n * @param toChain - Destination chain CAIP-2\n * @param fromToken - Source token address/symbol\n * @param toToken - Destination token address/symbol\n * @param amount - Amount in raw form (smallest unit)\n * @returns Array of discovered routes (empty if no routes found)\n */\n getRoutes(\n fromChain: string,\n toChain: string,\n fromToken: string,\n toToken: string,\n amount: string,\n ): Promise<Route[]>;\n\n /**\n * Build transaction parameters to execute a given route.\n *\n * @param route - The selected route to execute\n * @param sender - Sender address\n * @param recipient - Recipient address on destination chain\n * @returns Transaction parameters for the execution\n */\n getTransactionParams(\n route: Route,\n sender: string,\n recipient: string,\n ): Promise<ProviderTransaction[]>;\n\n /**\n * Query the current execution status of a cross-chain transfer.\n *\n * @param bridgeReference - Reference ID from the provider\n * @returns Current route status\n */\n getRouteStatus(bridgeReference: string): Promise<RouteStatus>;\n\n /**\n * Check whether this provider supports a given chain pair.\n *\n * @param fromChain - Source chain CAIP-2\n * @param toChain - Destination chain CAIP-2\n * @returns true if the chain pair is supported\n */\n supportsChainPair(fromChain: string, toChain: string): boolean;\n\n /**\n * Check whether this provider supports a given token on a chain.\n *\n * @param chain - Chain CAIP-2\n * @param token - Token contract address or symbol\n * @returns true if the token is supported\n */\n supportsToken(chain: string, token: string): boolean;\n}\n\nexport interface ProviderTransaction {\n type: \"approve\" | \"cross-chain\";\n chainId: string;\n to: string;\n data: string;\n value: string;\n}\n\n// ─── Errors ────────────────────────────────────────────────────────────\n\nexport type ChainAbstractionErrorCode =\n | \"chain_pair_not_supported\"\n | \"token_not_supported\"\n | \"route_expired\"\n | \"insufficient_balance\"\n | \"approve_needed\"\n | \"approve_rejected\"\n | \"transaction_failed\"\n | \"backend_unavailable\"\n | \"invalid_config\"\n | \"no_routes_available\"\n | \"provider_unavailable\"\n | \"execution_failed\";\n\nexport class ChainAbstractionError extends Error {\n code: ChainAbstractionErrorCode;\n details?: Record<string, unknown>;\n\n constructor(\n code: ChainAbstractionErrorCode,\n message?: string,\n details?: Record<string, unknown>,\n ) {\n super(message ?? code);\n this.name = \"ChainAbstractionError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function isChainAbstractionError(\n e: unknown,\n code?: ChainAbstractionErrorCode,\n): e is ChainAbstractionError {\n if (!e || typeof e !== \"object\") return false;\n const candidate = e as ChainAbstractionError;\n if (\n candidate.name !== \"ChainAbstractionError\" ||\n typeof candidate.code !== \"string\"\n )\n return false;\n return code ? candidate.code === code : true;\n}\n","/**\n * Chain Registry\n *\n * Single source of truth for chain names, token addresses, and provider IDs.\n * Do NOT create new mapping tables elsewhere — use `CHAINS` and `getChainInfo()`.\n */\n\n// ─── ChainInfo Interface ───────────────────────────────────────────────\n\nexport interface ChainInfo {\n name: string;\n caip2Id: string; // e.g. \"eip155:1\"\n nativeCurrency: { symbol: string; decimals: number };\n axelarName?: string; // Axelar GMP name (undefined = not supported by Axelar)\n usdcAddress?: string; // ERC-20 USDC address (undefined = no USDC on this chain)\n usdcDecimals?: number; // USDC decimals (defaults to 6)\n usdtAddress?: string; // ERC-20 USDT address (undefined = no USDT on this chain)\n usdtDecimals?: number; // USDT decimals (defaults to 6)\n entryPoint?: string; // ERC-4337 EntryPoint address (undefined = AA not supported)\n factoryAddress?: string; // Account factory address\n explorerUrl?: string; // Block explorer base URL (undefined = use default)\n chainlinkEthUsdFeed?: string; // Chainlink ETH/USD price feed oracle address\n}\n\n// ─── CHAINS Registry ───────────────────────────────────────────────────\n\nexport const CHAINS: Record<number, ChainInfo> = {\n 1: {\n name: \"Ethereum\",\n caip2Id: \"eip155:1\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n axelarName: \"ethereum\",\n usdcAddress: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n usdtAddress: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n entryPoint: \"0x0000000071727De22E5E9d8BAf0edAc6f37da032\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://etherscan.io\",\n chainlinkEthUsdFeed: \"0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419\",\n },\n 10: {\n name: \"Optimism\",\n caip2Id: \"eip155:10\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n usdcAddress: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n usdtAddress: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n entryPoint: \"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://optimistic.etherscan.io\",\n chainlinkEthUsdFeed: \"0x13e3Ee699D1909E989722E753853AE30b17e08c5\",\n },\n 56: {\n name: \"BNB Chain\",\n caip2Id: \"eip155:56\",\n nativeCurrency: { symbol: \"BNB\", decimals: 18 },\n axelarName: \"binance\",\n usdcAddress: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n usdtAddress: \"0x55d398326f99059fF775485246999027B3197955\",\n usdcDecimals: 18,\n usdtDecimals: 18,\n explorerUrl: \"https://bscscan.com\",\n },\n 100: {\n name: \"Gnosis\",\n caip2Id: \"eip155:100\",\n nativeCurrency: { symbol: \"xDAI\", decimals: 18 },\n axelarName: \"gnosis\",\n usdcAddress: \"0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83\",\n usdtAddress: \"0x4ECaBa5870353805a9F068101A40E0f32ed605C6\",\n explorerUrl: \"https://gnosisscan.io\",\n },\n 137: {\n name: \"Polygon\",\n caip2Id: \"eip155:137\",\n nativeCurrency: { symbol: \"MATIC\", decimals: 18 },\n axelarName: \"polygon\",\n usdcAddress: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n usdtAddress: \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\",\n entryPoint: \"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://polygonscan.com\",\n chainlinkEthUsdFeed: \"0xAB594600376Ec9fD91F8e885dADF0CE036862dE0\",\n },\n 250: {\n name: \"Fantom\",\n caip2Id: \"eip155:250\",\n nativeCurrency: { symbol: \"FTM\", decimals: 18 },\n axelarName: \"fantom\",\n usdcAddress: \"0x04068DA6C83AFCFA0e13ba15A6696662335D5B75\",\n explorerUrl: \"https://ftmscan.com\",\n },\n 324: {\n name: \"zkSync Era\",\n caip2Id: \"eip155:324\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n },\n 1101: {\n name: \"Polygon zkEVM\",\n caip2Id: \"eip155:1101\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n axelarName: \"polygon-zkevm\",\n usdcAddress: \"0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035\",\n explorerUrl: \"https://zkevm.polygonscan.com\",\n },\n 8453: {\n name: \"Base\",\n caip2Id: \"eip155:8453\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n axelarName: \"base\",\n usdcAddress: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n entryPoint: \"0x0000000071727De22E5E9d8BAf0edAc6f37da032\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://basescan.org\",\n },\n 42161: {\n name: \"Arbitrum\",\n caip2Id: \"eip155:42161\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n axelarName: \"arbitrum\",\n usdcAddress: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n usdtAddress: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n entryPoint: \"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://arbiscan.io\",\n },\n 43114: {\n name: \"Avalanche\",\n caip2Id: \"eip155:43114\",\n nativeCurrency: { symbol: \"AVAX\", decimals: 18 },\n axelarName: \"avalanche\",\n usdcAddress: \"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E\",\n explorerUrl: \"https://snowtrace.io\",\n },\n 59144: {\n name: \"Linea\",\n caip2Id: \"eip155:59144\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n usdcAddress: \"0x176211869cA2b568f2A7D4EE941E073a542EEd12\",\n explorerUrl: \"https://lineascan.build\",\n },\n 534352: {\n name: \"Scroll\",\n caip2Id: \"eip155:534352\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n usdcAddress: \"0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4\",\n explorerUrl: \"https://scrollscan.com\",\n },\n 11155111: {\n name: \"Sepolia\",\n caip2Id: \"eip155:11155111\",\n nativeCurrency: { symbol: \"ETH\", decimals: 18 },\n entryPoint: \"0x0000000071727De22E5E9d8BAf0edAc6f37da032\",\n factoryAddress: \"0x9406Cc6185a346906296840746125a0E44976454\",\n explorerUrl: \"https://sepolia.etherscan.io\",\n },\n};\n\n// ─── Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Get chain info for a given chain ID.\n * Throws if the chain is not in the registry.\n */\nexport function getChainInfo(chainId: number): ChainInfo {\n const info = CHAINS[chainId];\n if (!info) {\n throw new Error(\n `Chain ${chainId} not found in registry. Add it to chain-registry.ts`,\n );\n }\n return info;\n}\n","import type {\n Namespace,\n SessionNamespace,\n UniversalWalletSession,\n} from \"./session\";\n\nexport type { Namespace, SessionNamespace, UniversalWalletSession };\n\nexport interface ConnectorSupport {\n desktop: boolean;\n mobile: boolean;\n deepLink: boolean;\n qr: boolean;\n trustedReconnect: boolean;\n}\n\nexport interface BatchCall {\n to: `0x${string}`;\n value?: string;\n data?: `0x${string}`;\n}\n\nexport interface WalletCapabilities {\n atomicBatch: { supported: boolean; maxBatchSize?: number };\n paymasterService?: { supported: boolean };\n [key: string]: unknown;\n}\n\n/** EIP-5792: getCallsStatus response */\nexport interface CallsStatus {\n status: \"PENDING\" | \"CONFIRMED\";\n receipts?: Array<{\n logs: Array<{\n address: string;\n data: string;\n topics: string[];\n }>;\n status: \"0x1\" | \"0x0\";\n blockHash: string;\n blockNumber: string;\n gasUsed: string;\n transactionHash: string;\n }>;\n}\n\nexport interface UniversalConnector {\n id: string;\n name: string;\n kind: string;\n namespaces: string[];\n supports: ConnectorSupport;\n connect(input?: unknown): Promise<UniversalWalletSession>;\n reconnect?(session: UniversalWalletSession): Promise<UniversalWalletSession>;\n disconnect(session: UniversalWalletSession): Promise<void>;\n getAccounts(session: UniversalWalletSession): Promise<string[]>;\n signMessage?(\n session: UniversalWalletSession,\n input: unknown,\n ): Promise<unknown>;\n signTransaction?(\n session: UniversalWalletSession,\n input: unknown,\n ): Promise<unknown>;\n sendTransaction?(\n session: UniversalWalletSession,\n input: unknown,\n ): Promise<unknown>;\n switchChain?(session: UniversalWalletSession, chainId: string): Promise<void>;\n deepLink?(target: string): Promise<void>;\n sendCalls?(\n session: UniversalWalletSession,\n calls: BatchCall[],\n chainId?: string,\n ): Promise<string>;\n getCapabilities?(\n session: UniversalWalletSession,\n ): Promise<Record<string, WalletCapabilities>>;\n getCallsStatus?(\n session: UniversalWalletSession,\n bundleHash: string,\n ): Promise<CallsStatus>;\n request?(request: { method: string; params: unknown[] }): Promise<unknown>;\n getBalance?(chainId?: string): Promise<string>;\n}\n\nexport function extractAccounts(\n namespaces: Record<Namespace, SessionNamespace>,\n): string[] {\n return Object.values(namespaces).flatMap((namespace) => namespace.accounts);\n}\n\nexport function getChainsFromNamespaces(\n namespaces: Record<Namespace, SessionNamespace>,\n): string[] {\n const chains = new Set<string>();\n Object.values(namespaces).forEach((namespace) => {\n namespace.chains.forEach((chain) => chains.add(chain));\n });\n return Array.from(chains);\n}\n\nexport function getMethodsFromNamespaces(\n namespaces: Record<Namespace, SessionNamespace>,\n): string[] {\n const methods = new Set<string>();\n Object.values(namespaces).forEach((namespace) => {\n namespace.methods.forEach((method) => methods.add(method));\n });\n return Array.from(methods);\n}\n\nexport function getEventsFromNamespaces(\n namespaces: Record<Namespace, SessionNamespace>,\n): string[] {\n const events = new Set<string>();\n Object.values(namespaces).forEach((namespace) => {\n namespace.events.forEach((event) => events.add(event));\n });\n return Array.from(events);\n}\n","export const CONNECTOR_ERROR_MESSAGES = {\n SESSION_EXPIRED: \"Session expired. Please reconnect your wallet.\",\n NO_ACCOUNT_SIGNING:\n \"No account found for signing. Please reconnect your wallet.\",\n NO_ACCOUNT_TX:\n \"No account found for transaction. Please reconnect your wallet.\",\n NO_ACCOUNTS: \"No accounts available. Please reconnect your wallet.\",\n INVALID_INPUT: \"Invalid input.\",\n MISSING_TX: \"Missing transaction.\",\n MISSING_MESSAGE: \"Missing message parameter.\",\n USER_REJECTED: \"Operation rejected by user.\",\n TX_FAILED: \"Transaction failed.\",\n CHAIN_UNSUPPORTED: \"Chain not supported.\",\n METHOD_NOT_ALLOWED: \"Method not allowed.\",\n WALLET_UNAVAILABLE: \"Wallet not available.\",\n} as const;\n\nexport type WalletErrorCode =\n | \"wallet_unavailable\"\n | \"user_rejected\"\n | \"deeplink_timeout\"\n | \"session_expired\"\n | \"intent_expired\"\n | \"namespace_mismatch\"\n | \"chain_unsupported\"\n | \"method_not_allowed\"\n | \"method_unsupported\"\n | \"signature_rejected\"\n | \"tx_failed\"\n | \"invalid_proposal\"\n | \"invalid_input\"\n | \"siwx_error\"\n | \"no_active_session\"\n | \"chain_switch_rejected\"\n | \"invalid_chain\"\n | \"no_solana_session\"\n | \"unsupported_chain\"\n | \"fee_rpc_error\";\n\nexport class WalletError extends Error {\n code: WalletErrorCode;\n details?: unknown;\n\n constructor(code: WalletErrorCode, message?: string, details?: unknown) {\n super(message ?? code);\n this.name = \"WalletError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function isWalletError(\n e: unknown,\n code?: WalletErrorCode,\n): e is WalletError {\n if (!e || typeof e !== \"object\") {\n return false;\n }\n\n const candidate = e as WalletError;\n if (candidate.name !== \"WalletError\" || typeof candidate.code !== \"string\") {\n return false;\n }\n\n return code ? candidate.code === code : true;\n}\n","export type Platform = \"desktop-web\" | \"mobile-web\" | \"in-app-browser\";\n\nexport function detectPlatform(): Platform {\n if (typeof navigator === \"undefined\") {\n return \"desktop-web\";\n }\n\n const ua = navigator.userAgent.toLowerCase();\n const mobilePattern = /(iphone|ipad|ipod|android|mobile)/i;\n\n if (mobilePattern.test(ua)) {\n return \"mobile-web\";\n }\n\n return \"desktop-web\";\n}\n\nexport function isMobileBrowser(): boolean {\n if (typeof navigator === \"undefined\") {\n return false;\n }\n\n const ua = navigator.userAgent.toLowerCase();\n return /(iphone|ipad|ipod|android|mobile)/i.test(ua);\n}\n","/**\n * Connector Manager\n *\n * Manages multiple wallet connectors and provides a unified interface\n * for connecting, disconnecting, and managing wallet connections.\n */\n\nimport type {\n BatchCall,\n ConnectorSupport,\n UniversalConnector,\n WalletCapabilities,\n} from \"./connector\";\nimport { WalletError } from \"./errors\";\nimport { isMobileBrowser } from \"./platform\";\nimport type { UniversalWalletSession } from \"./session\";\n\nexport type ConnectorId = string;\n\nexport interface ConnectorEntry {\n id: ConnectorId;\n connector: UniversalConnector;\n priority: number;\n}\n\nexport interface ConnectorManagerConfig {\n autoSelect?: boolean;\n preferOrder?: ConnectorId[];\n}\n\nexport class ConnectorManager {\n private connectors: Map<ConnectorId, UniversalConnector> = new Map();\n private entries: Map<ConnectorId, ConnectorEntry> = new Map();\n private activeConnectorId: ConnectorId | null = null;\n private activeSession: UniversalWalletSession | null = null;\n private config: ConnectorManagerConfig;\n\n /** Prevent concurrent connect() calls from overwriting sessions */\n private _connecting = false;\n\n constructor(config: ConnectorManagerConfig = {}) {\n this.config = {\n autoSelect: config.autoSelect ?? true,\n preferOrder: config.preferOrder ?? [],\n };\n }\n\n register(id: ConnectorId, connector: UniversalConnector, priority = 0): void {\n this.connectors.set(id, connector);\n this.entries.set(id, { id, connector, priority });\n }\n\n unregister(id: ConnectorId): void {\n this.connectors.delete(id);\n this.entries.delete(id);\n if (this.activeConnectorId === id) {\n this.activeConnectorId = null;\n }\n }\n\n get(id: ConnectorId): UniversalConnector | undefined {\n return this.connectors.get(id);\n }\n\n getActive(): UniversalConnector | undefined {\n if (!this.activeConnectorId) return undefined;\n return this.connectors.get(this.activeConnectorId);\n }\n\n getActiveSession(): UniversalWalletSession | null {\n return this.activeSession;\n }\n\n list(): ConnectorEntry[] {\n return Array.from(this.entries.values()).sort(\n (a, b) => b.priority - a.priority,\n );\n }\n\n listBySupport(support: keyof ConnectorSupport): UniversalConnector[] {\n return this.list()\n .map((entry) => entry.connector)\n .filter((connector) => connector.supports[support]);\n }\n\n async connect(\n id?: ConnectorId,\n input?: unknown,\n ): Promise<UniversalWalletSession> {\n if (this._connecting) {\n throw new Error(\"Connection already in progress\");\n }\n this._connecting = true;\n\n try {\n let connector: UniversalConnector | undefined;\n\n if (id) {\n connector = this.connectors.get(id);\n if (!connector) {\n throw new Error(`Connector \"${id}\" not found`);\n }\n } else if (this.config.autoSelect) {\n connector = this.selectBestConnector();\n if (!connector) {\n throw new Error(\"No connectors available\");\n }\n } else {\n throw new Error(\"No connector specified and autoSelect is disabled\");\n }\n\n const session = await connector.connect(input);\n this.activeConnectorId = connector.id;\n this.activeSession = session;\n return session;\n } finally {\n this._connecting = false;\n }\n }\n\n async reconnect(\n session: UniversalWalletSession,\n ): Promise<UniversalWalletSession> {\n if (this._connecting) {\n throw new Error(\"Connection already in progress\");\n }\n this._connecting = true;\n\n try {\n if (!session.topic) {\n throw new Error(\"Reconnection not supported for this session type\");\n }\n\n const connectorId =\n this.activeConnectorId ?? this.connectors.keys().next().value;\n const connector = connectorId ? this.get(connectorId) : null;\n\n if (connector?.reconnect) {\n const newSession = await connector.reconnect(session);\n this.activeConnectorId = connectorId!;\n this.activeSession = newSession;\n return newSession;\n }\n\n throw new Error(\n `Reconnection not supported by connector \"${connectorId ?? \"unknown\"}\"`,\n );\n } finally {\n this._connecting = false;\n }\n }\n\n async disconnect(): Promise<void> {\n if (!this.activeConnectorId || !this.activeSession) {\n return;\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (connector) {\n await connector.disconnect(this.activeSession);\n }\n\n this.activeConnectorId = null;\n this.activeSession = null;\n }\n\n async getAccounts(): Promise<string[]> {\n if (!this.activeConnectorId || !this.activeSession) {\n return [];\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector) {\n return [];\n }\n\n return connector.getAccounts(this.activeSession);\n }\n\n async signMessage(input: {\n message: string;\n account?: string;\n }): Promise<unknown> {\n if (!this.activeConnectorId || !this.activeSession) {\n throw new Error(\"No active session\");\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector?.signMessage) {\n throw new Error(\"signMessage not supported by this connector\");\n }\n\n return connector.signMessage(this.activeSession, input);\n }\n\n async sendTransaction(input: unknown): Promise<unknown> {\n if (!this.activeConnectorId || !this.activeSession) {\n throw new Error(\"No active session\");\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector?.sendTransaction) {\n throw new Error(\"sendTransaction not supported by this connector\");\n }\n\n return connector.sendTransaction(this.activeSession, input);\n }\n\n async switchChain(chainId: string): Promise<void> {\n if (!this.activeConnectorId || !this.activeSession) {\n throw new Error(\"No active session\");\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector?.switchChain) {\n throw new Error(\"switchChain not supported by this connector\");\n }\n\n await connector.switchChain(this.activeSession, chainId);\n }\n\n async request(request: {\n method: string;\n params: unknown[];\n }): Promise<unknown> {\n const connector = this.getActive();\n if (!connector?.request)\n throw new WalletError(\n \"method_not_allowed\",\n \"RPC requests not supported by active connector\",\n );\n return connector.request(request);\n }\n\n async getBalance(chainId?: string): Promise<string> {\n const connector = this.getActive();\n if (!connector?.getBalance)\n throw new WalletError(\n \"method_not_allowed\",\n \"Balance queries not supported by active connector\",\n );\n return connector.getBalance(chainId);\n }\n\n async sendCalls(\n session: UniversalWalletSession,\n calls: BatchCall[],\n chainId?: string,\n ): Promise<string> {\n if (!this.activeConnectorId || !this.activeSession) {\n throw new Error(\"No active session\");\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector?.sendCalls) {\n throw new Error(\"sendCalls not supported by this connector\");\n }\n\n return connector.sendCalls(session, calls, chainId);\n }\n\n async getCapabilities(\n session: UniversalWalletSession,\n ): Promise<Record<string, WalletCapabilities>> {\n if (!this.activeConnectorId || !this.activeSession) {\n throw new Error(\"No active session\");\n }\n\n const connector = this.connectors.get(this.activeConnectorId);\n if (!connector?.getCapabilities) {\n throw new Error(\"getCapabilities not supported by this connector\");\n }\n\n return connector.getCapabilities(session);\n }\n\n clear(): void {\n this.connectors.clear();\n this.entries.clear();\n this.activeConnectorId = null;\n this.activeSession = null;\n }\n\n private selectBestConnector(): UniversalConnector | undefined {\n const available = this.list();\n\n if (this.config.preferOrder && this.config.preferOrder.length > 0) {\n for (const preferredId of this.config.preferOrder) {\n const entry = this.entries.get(preferredId);\n if (entry) {\n return entry.connector;\n }\n }\n }\n\n const isMobile = isMobileBrowser();\n\n for (const entry of available) {\n const support = entry.connector.supports;\n if (isMobile && support.mobile) {\n return entry.connector;\n }\n if (!isMobile && support.desktop) {\n return entry.connector;\n }\n }\n\n return available[0]?.connector;\n }\n}\n\nexport function createConnectorManager(\n config?: ConnectorManagerConfig,\n): ConnectorManager {\n return new ConnectorManager(config);\n}\n","/**\n * CAIP-2 Chain Namespace Identifiers\n *\n * References:\n * - CAIP-2: https://namespaces.chainagnostic.org/CAIP-2\n */\nexport const NAMESPACE_EIP155 = \"eip155\" as const;\nexport const NAMESPACE_SOLANA = \"solana\" as const;\nexport const NAMESPACE_XRPL = \"xrpl\" as const;\n\nexport const SUPPORTED_NAMESPACES = [\n NAMESPACE_EIP155,\n NAMESPACE_SOLANA,\n NAMESPACE_XRPL,\n] as const;\n\n/**\n * Common EVM Chain IDs (CAIP-2 format)\n */\nexport const EIP155_MAINNET = \"eip155:1\";\nexport const EIP155_GOERLI = \"eip155:5\";\nexport const EIP155_SEPOLIA = \"eip155:11155111\";\nexport const EIP155_POLYGON = \"eip155:137\";\nexport const EIP155_MUMBAI = \"eip155:80001\";\nexport const EIP155_ARBITRUM = \"eip155:42161\";\nexport const EIP155_ARBITRUM_GOERLI = \"eip155:421613\";\nexport const EIP155_OPTIMISM = \"eip155:10\";\nexport const EIP155_OPTIMISM_GOERLI = \"eip155:420\";\nexport const EIP155_BASE = \"eip155:8453\";\n\n/**\n * Common Solana Cluster IDs (CAIP-2 format)\n */\nexport const SOLANA_MAINNET = \"solana:0\";\nexport const SOLANA_DEVNET = \"solana:1\";\nexport const SOLANA_TESTNET = \"solana:2\";\n\n/**\n * Common XRPL Network IDs (CAIP-2 format)\n */\nexport const XRPL_MAINNET = \"xrpl:0\";\nexport const XRPL_TESTNET = \"xrpl:1\";\nexport const XRPL_DEVNET = \"xrpl:2\";\n\n/**\n * Default EVM chain (Ethereum Mainnet)\n */\nexport const DEFAULT_EVM_CHAIN = EIP155_MAINNET;\n\n/**\n * Default Solana cluster (Mainnet)\n */\nexport const DEFAULT_SOLANA_CLUSTER = SOLANA_MAINNET;\n\n/**\n * Default XRPL network (Mainnet)\n */\nexport const DEFAULT_XRPL_NETWORK = XRPL_MAINNET;\n\n/**\n * WalletConnect v2 Disconnect Reason Codes\n *\n * Reference: WalletConnect v2 Protocol Specification\n */\nexport const WC_DISCONNECT_USER = 6000;\nexport const WC_DISCONNECT_TIMEOUT = 6001;\nexport const WC_DISCONNECT_SESSION_EXPIRED = 6002;\n\n/**\n * Storage keys used across connectors\n */\nexport const STORAGE_KEYS = {\n SESSION: \"naculus_web3_session\",\n POCKET: \"naculus_pocket\",\n PASSKEYS_CREDENTIAL: \"naculus_passkeys_credential\",\n} as const;\n\n/**\n * Nonce configuration\n */\nexport const DEFAULT_NONCE_LENGTH = 16;\n\n/**\n * Session timeout values (in milliseconds)\n */\nexport const SESSION_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nexport const AUTO_RECONNECT_TIMEOUT_MS = 30 * 1000; // 30 seconds\n","/**\n * BigInt ↔ String Conversion Utilities\n *\n * Provides safe conversion between bigint and string representations\n * for fee values, integrating with wallet-engine and UI layers.\n *\n * @see SRS-001 §6.3\n */\n\n/**\n * Convert a bigint fee value to its decimal string representation.\n *\n * @param value - Fee value in wei as bigint\n * @returns Decimal string (e.g., \"15000000000\" for 15 gwei)\n *\n * @example\n * ```ts\n * toDecString(15000000000n) // \"15000000000\"\n * toDecString(0n) // \"0\"\n * ```\n */\nexport function toDecString(value: bigint): string {\n return value.toString();\n}\n\n/**\n * Parse a decimal string into a bigint.\n *\n * @param value - Decimal string (e.g., \"15000000000\")\n * @returns bigint representation\n *\n * @example\n * ```ts\n * parseBigInt(\"15000000000\") // 15000000000n\n * parseBigInt(\"0\") // 0n\n * ```\n */\nexport function parseBigInt(value: string): bigint {\n return BigInt(value);\n}\n\n/**\n * Convert a bigint to a human-readable string with a label (e.g., \"25 gwei\").\n *\n * @param wei - Value in wei as bigint\n * @param decimals - Number of decimals for the display unit (default: 9 for gwei)\n * @param unit - Unit label (default: \"gwei\")\n * @returns Human-readable string\n *\n * @example\n * ```ts\n * toHumanReadable(25000000000n) // \"25 gwei\"\n * toHumanReadable(15000000000n, 9, \"gwei\") // \"15 gwei\"\n * toHumanReadable(1000000000000000000n, 18, \"ETH\") // \"1 ETH\"\n * ```\n */\nexport function toHumanReadable(\n wei: bigint,\n decimals: number = 9,\n unit: string = \"gwei\",\n): string {\n if (wei === 0n) return `0 ${unit}`;\n\n const divisor = 10n ** BigInt(decimals);\n const whole = wei / divisor;\n const remainder = wei % divisor;\n\n if (remainder === 0n) {\n return `${whole.toString()} ${unit}`;\n }\n\n const remainderStr = remainder.toString().padStart(decimals, \"0\");\n const trimmed = remainderStr.replace(/0+$/, \"\");\n return `${whole.toString()}.${trimmed} ${unit}`;\n}\n","/**\n * Fee Estimation Error\n *\n * Thrown when all fee estimation strategies have failed.\n */\n\nexport type FeeEstimationErrorCode =\n | \"fee_estimation_failed\"\n | \"fee_chain_not_supported\"\n | \"fee_rpc_error\";\n\nexport class FeeEstimationError extends Error {\n code: FeeEstimationErrorCode;\n details?: unknown;\n\n constructor(\n code: FeeEstimationErrorCode,\n message?: string,\n details?: unknown,\n ) {\n super(message ?? code);\n this.name = \"FeeEstimationError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function isFeeEstimationError(\n e: unknown,\n code?: FeeEstimationErrorCode,\n): e is FeeEstimationError {\n if (!e || typeof e !== \"object\") {\n return false;\n }\n\n const candidate = e as FeeEstimationError;\n if (\n candidate.name !== \"FeeEstimationError\" ||\n typeof candidate.code !== \"string\"\n ) {\n return false;\n }\n\n return code ? candidate.code === code : true;\n}\n\n/** Error message constants */\nexport const FEE_ERROR_MESSAGES = {\n ESTIMATION_FAILED: \"Fee estimation failed after all strategies exhausted.\",\n CHAIN_NOT_SUPPORTED: \"Chain not supported for fee estimation.\",\n RPC_ERROR: \"RPC call failed during fee estimation.\",\n} as const;\n","/**\n * EIP-1559 Fee Estimation Module\n *\n * Provides fee estimation for EVM chains with automatic support detection,\n * fallback to legacy gas price, and chain-specific estimator registration.\n *\n * @see SRS-001 §6.1\n */\n\nimport { logger } from \"../logger\";\nimport { FEE_ERROR_MESSAGES, FeeEstimationError } from \"./errors\";\nimport type {\n ChainFeeEstimator,\n ChainFeeSupport,\n FeeEstimationConfig,\n FeeValues,\n FeeValuesEIP1559,\n FeeValuesLegacy,\n} from \"./types\";\n\n// ─── Registry for chain-specific estimators ────────────────────────────\n\nconst chainEstimators = new Map<string, ChainFeeEstimator>();\n\n/**\n * Register a chain-specific fee estimator.\n * Registered estimators take priority over the built-in heuristic logic.\n */\nexport function registerChainFeeEstimator(estimator: ChainFeeEstimator): void {\n chainEstimators.set(estimator.chainId, estimator);\n}\n\n/**\n * Remove a previously registered chain-specific estimator.\n */\nexport function unregisterChainFeeEstimator(chainId: string): void {\n chainEstimators.delete(chainId);\n}\n\n/**\n * Clear all registered chain-specific estimators.\n */\nexport function clearChainFeeEstimators(): void {\n chainEstimators.clear();\n}\n\n// ─── Internal RPC helpers (exported for testing) ───────────────────────\n\n/**\n * Make a JSON-RPC call to the given endpoint with a 10-second timeout.\n */\nasync function rpcCall<T>(\n rpcUrl: string,\n method: string,\n params: unknown[],\n): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n try {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method,\n params,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new FeeEstimationError(\n \"fee_rpc_error\",\n `RPC returned status ${response.status}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: T;\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new FeeEstimationError(\"fee_rpc_error\", json.error.message, {\n code: json.error.code,\n });\n }\n\n return json.result as T;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Fetch the suggested max priority fee via eth_maxPriorityFeePerGas.\n *\n * @param rpcUrl - RPC endpoint\n * @returns The suggested priority fee (in wei), or throws if the method is not supported\n */\nexport async function estimateMaxPriorityFeePerGas(\n rpcUrl: string,\n): Promise<bigint> {\n const result = await rpcCall<string>(rpcUrl, \"eth_maxPriorityFeePerGas\", []);\n return BigInt(result);\n}\n\n/**\n * Fetch the base fee per gas from the latest block.\n *\n * @param rpcUrl - RPC endpoint\n * @returns Base fee per gas in wei, or null if not available (pre-London fork)\n */\nexport async function getLatestBaseFee(rpcUrl: string): Promise<bigint | null> {\n const block = await rpcCall<{ baseFeePerGas?: string }>(\n rpcUrl,\n \"eth_getBlockByNumber\",\n [\"latest\", false],\n );\n\n if (block && typeof block.baseFeePerGas === \"string\") {\n return BigInt(block.baseFeePerGas);\n }\n\n return null;\n}\n\n/**\n * Fetch legacy gas price via eth_gasPrice.\n *\n * @param rpcUrl - RPC endpoint\n * @returns Current gas price in wei\n */\nexport async function getGasPrice(rpcUrl: string): Promise<bigint> {\n const result = await rpcCall<string>(rpcUrl, \"eth_gasPrice\", []);\n return BigInt(result);\n}\n\n/**\n * Fetch chain ID via eth_chainId.\n *\n * @param rpcUrl - RPC endpoint\n * @returns Chain ID as a bigint (supports values beyond Number.MAX_SAFE_INTEGER)\n */\nexport async function getChainId(rpcUrl: string): Promise<bigint> {\n const result = await rpcCall<string>(rpcUrl, \"eth_chainId\", []);\n return BigInt(result);\n}\n\n// ─── Chain Support Detection ───────────────────────────────────────────\n\n/**\n * Query the chain's EIP-1559 support status and recent base fee.\n *\n * Strategy:\n * 1. Fetch the latest block to check for baseFeePerGas\n * 2. If present, the chain supports EIP-1559\n * 3. If absent, the chain uses legacy gas model\n *\n * @param rpcUrl - RPC endpoint\n * @returns ChainFeeSupport with EIP-1559 support status and data\n */\nexport async function getFeeData(rpcUrl: string): Promise<ChainFeeSupport> {\n const baseFee = await getLatestBaseFee(rpcUrl);\n\n if (baseFee !== null) {\n try {\n const recommendedPriorityFee = await estimateMaxPriorityFeePerGas(rpcUrl);\n return {\n eip1559: true,\n latestBaseFee: baseFee,\n recommendedPriorityFee,\n };\n } catch {\n // eth_maxPriorityFeePerGas is not supported; EIP-1559 still works\n return {\n eip1559: true,\n latestBaseFee: baseFee,\n };\n }\n }\n\n return { eip1559: false };\n}\n\n// ─── Main Fee Estimation ───────────────────────────────────────────────\n\n/**\n * Helper to check if a chain has a registered custom estimator.\n */\nfunction findRegisteredEstimator(\n chainId?: string,\n): ChainFeeEstimator | undefined {\n if (!chainId) return undefined;\n return chainEstimators.get(chainId);\n}\n\n/**\n * Determine the transaction type from config.\n * Returns \"auto\", \"eip1559\", or \"legacy\".\n */\nfunction resolveType(\n config: FeeEstimationConfig,\n): \"auto\" | \"eip1559\" | \"legacy\" {\n if (config.type === \"eip1559\" || config.type === \"legacy\") {\n return config.type;\n }\n // Default to auto-detection\n return \"auto\";\n}\n\n/**\n * Build EIP-1559 fee values from base fee and config.\n */\nfunction buildEIP1559Fees(\n baseFee: bigint,\n priorityFee: bigint,\n config: FeeEstimationConfig,\n): FeeValuesEIP1559 {\n const multiplier = config.baseFeeMultiplier ?? 2n;\n const maxPriorityFeePerGas = config.maxPriorityFeePerGas ?? priorityFee;\n const maxFeePerGas = baseFee * multiplier + maxPriorityFeePerGas;\n\n return {\n type: \"eip1559\",\n maxFeePerGas,\n maxPriorityFeePerGas,\n };\n}\n\n/**\n * Estimate fees for a transaction on the given chain.\n *\n * The function follows this fallback strategy:\n * 1. If a chain-specific estimator is registered, use it\n * 2. Try EIP-1559 flow (eth_maxPriorityFeePerGas + base fee)\n * 3. Fall back to legacy gas price\n * 4. All strategies fail → throw FeeEstimationError\n *\n * @param config - Fee estimation configuration\n * @returns FeeValues (eip1559 | legacy)\n *\n * @example\n * ```ts\n * const fees = await estimateFees({\n * rpcUrl: \"https://eth.llamarpc.com\",\n * chainId: \"eip155:1\",\n * });\n * // => { type: \"eip1559\", maxFeePerGas: 15000000000n, maxPriorityFeePerGas: 1000000000n }\n * ```\n */\nexport async function estimateFees(\n config: FeeEstimationConfig,\n): Promise<FeeValues> {\n const { rpcUrl, chainId } = config;\n\n // Step 1: Use chain-specific estimator if available\n const estimator = findRegisteredEstimator(chainId);\n if (estimator) {\n try {\n return await estimator.estimateFees(rpcUrl, config);\n } catch (error) {\n logger.warn(\n \"fee-estimation\",\n `Chain estimator failed for ${chainId}, falling back`,\n error,\n );\n // Fall through to built-in logic\n }\n }\n\n // Step 2: Try EIP-1559\n const resolvedType = resolveType(config);\n\n if (resolvedType === \"eip1559\") {\n // User explicitly wants EIP-1559\n const priorityFee =\n config.maxPriorityFeePerGas ??\n (await estimateMaxPriorityFeePerGas(rpcUrl));\n const baseFee = await getLatestBaseFee(rpcUrl);\n\n if (baseFee === null) {\n throw new FeeEstimationError(\n \"fee_estimation_failed\",\n \"EIP-1559 forced but chain does not support base fee\",\n );\n }\n\n return buildEIP1559Fees(baseFee, priorityFee, config);\n }\n\n // Default \"auto\" mode: detect and fall back\n try {\n const priorityFee = await estimateMaxPriorityFeePerGas(rpcUrl);\n const baseFee = await getLatestBaseFee(rpcUrl);\n\n if (baseFee !== null) {\n return buildEIP1559Fees(baseFee, priorityFee, config);\n }\n\n // eth_maxPriorityFeePerGas succeeded but no base fee\n // This is unusual but fall back to legacy\n logger.warn(\n \"fee-estimation\",\n \"No base fee found despite priority fee support, falling back to legacy\",\n );\n } catch {\n // eth_maxPriorityFeePerGas not supported → legacy chain\n logger.debug(\n \"fee-estimation\",\n \"eth_maxPriorityFeePerGas not available, using legacy\",\n );\n }\n\n // Step 3: Legacy fallback\n try {\n const gasPrice = await getGasPrice(rpcUrl);\n return { type: \"legacy\", gasPrice };\n } catch (error) {\n throw new FeeEstimationError(\n \"fee_estimation_failed\",\n FEE_ERROR_MESSAGES.ESTIMATION_FAILED,\n { error },\n );\n }\n}\n","/**\n * Notification Channel Adapters.\n *\n * Provides the `NotificationChannel` interface plus built-in adapters:\n * - `InAppChannel` — in-memory / localStorage-backed notification list\n * - `TelegramChannel` — adapter stub (actual bot token provided externally)\n *\n * @see docs/features/push-notification.md §4.4\n */\n\nimport type {\n ChannelCapability,\n NotificationChannel,\n NotificationItem,\n NotificationPayload,\n} from \"./types\";\n\n// ─── Storage shape for in-app history ──────────────────────────────────\n\nconst STORAGE_KEY_PREFIX = \"naculus_notif_\";\n\n// ─── InAppChannel ─────────────────────────────────────────────────────\n\nexport interface InAppChannelOptions {\n /** Maximum number of history entries kept in storage (default 200) */\n maxHistory?: number;\n /** Optional storage for persisting notification history */\n storage?: {\n getItem: <T>(key: string) => Promise<T | null>;\n setItem: <T>(key: string, value: T) => Promise<void>;\n removeItem: (key: string) => Promise<void>;\n };\n /** Callback fired when a new notification arrives (used by React hook) */\n onNotification?: (item: NotificationItem) => void;\n}\n\n/**\n * In-app notification channel.\n *\n * Stores notifications in a history buffer and fires a callback for each\n * new notification so React hooks can stay in sync.\n */\nexport class InAppChannel implements NotificationChannel {\n readonly id = \"inapp\";\n readonly name = \"In-App Toast\";\n\n private history: NotificationItem[] = [];\n private maxHistory: number;\n private storage?: InAppChannelOptions[\"storage\"];\n onNotification?: (item: NotificationItem) => void;\n\n constructor(options?: InAppChannelOptions) {\n this.maxHistory = options?.maxHistory ?? 200;\n this.storage = options?.storage;\n this.onNotification = options?.onNotification;\n }\n\n getCapabilities(): ChannelCapability {\n return {\n supportsRichText: true,\n supportsActionButtons: false,\n supportsMedia: false,\n maxLength: Infinity,\n isBackground: false,\n };\n }\n\n isAvailable(): boolean {\n return true;\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n\n async send(payload: NotificationPayload): Promise<void> {\n const item: NotificationItem = {\n id: payload.id,\n title: payload.title,\n body: payload.body,\n status: payload.status,\n txHash: payload.txHash,\n chainName: payload.chainName,\n valueFormatted: payload.valueFormatted,\n explorerUrl: payload.explorerUrl,\n timestamp: payload.timestamp,\n read: false,\n };\n\n this.history.push(item);\n\n // Trim history to max length\n if (this.history.length > this.maxHistory) {\n this.history = this.history.slice(-this.maxHistory);\n }\n\n // Persist to storage if configured\n if (this.storage) {\n await this.persist();\n }\n\n // Fire callback for React hooks\n this.onNotification?.(item);\n }\n\n // ── History Management ──────────────────────────────────────────────\n\n /** Returns all in-app notifications (newest last). */\n getHistory(): NotificationItem[] {\n return [...this.history];\n }\n\n /** Mark a single notification as read. */\n markAsRead(id: string): void {\n const found = this.history.find((n) => n.id === id);\n if (found) {\n found.read = true;\n }\n }\n\n /** Mark all notifications as read. */\n markAllAsRead(): void {\n for (const n of this.history) {\n n.read = true;\n }\n }\n\n /** Clear all in-app notifications. */\n clear(): void {\n this.history = [];\n if (this.storage) {\n void this.storage.removeItem(STORAGE_KEY_PREFIX + \"history\");\n }\n }\n\n /** Number of unread notifications. */\n get unreadCount(): number {\n return this.history.filter((n) => !n.read).length;\n }\n\n // ── Persistence ─────────────────────────────────────────────────────\n\n private async persist(): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.setItem(STORAGE_KEY_PREFIX + \"history\", this.history);\n } catch {\n // Silently fail — history in memory is still available\n }\n }\n\n /** Restore persisted history (call on initialization). */\n async restore(): Promise<void> {\n if (!this.storage) return;\n try {\n const saved = await this.storage.getItem<NotificationItem[]>(\n STORAGE_KEY_PREFIX + \"history\",\n );\n if (saved && Array.isArray(saved)) {\n this.history = saved.slice(-this.maxHistory);\n }\n } catch {\n // Silently fail\n }\n }\n}\n\n// ─── TelegramChannel ──────────────────────────────────────────────────\n\n/**\n * Telegram notification channel.\n *\n * This is an adapter stub. The actual bot token is provided at runtime via\n * the constructor. The `send` method formats the payload into a Telegram\n * message and sends it through the Telegram Bot API.\n *\n * @remarks\n * Token is accepted but the HTTP call to Telegram's API is left to the\n * integrator's Telegram infrastructure (e.g., OpenClaw delivery channel).\n * The `send` implementation here is a placeholder that logs the formatted\n * message — the real transport should be injected or overridden.\n */\nexport class TelegramChannel implements NotificationChannel {\n readonly id = \"telegram\";\n readonly name = \"Telegram\";\n\n private botToken: string;\n private chatId: string;\n private transport?: (\n payload: NotificationPayload,\n formatted: string,\n ) => Promise<void>;\n\n constructor(config: {\n botToken: string;\n chatId: string;\n /** Optional transport override. Defaults to console.log. */\n transport?: (\n payload: NotificationPayload,\n formatted: string,\n ) => Promise<void>;\n }) {\n this.botToken = config.botToken;\n this.chatId = config.chatId;\n this.transport = config.transport;\n }\n\n getCapabilities(): ChannelCapability {\n return {\n supportsRichText: true,\n supportsActionButtons: true,\n supportsMedia: false,\n maxLength: 4096,\n isBackground: true,\n };\n }\n\n isAvailable(): boolean {\n return this.botToken.length > 0;\n }\n\n async healthCheck(): Promise<boolean> {\n return this.isAvailable();\n }\n\n async send(payload: NotificationPayload): Promise<void> {\n const formatted = this.formatMessage(payload);\n\n if (this.transport) {\n await this.transport(payload, formatted);\n } else {\n // Default: log to console (real transport should be configured)\n console.log(\n `[TelegramChannel] Would send to ${this.chatId}:\\n${formatted}`,\n );\n }\n }\n\n private formatMessage(payload: NotificationPayload): string {\n const emoji = this.statusEmoji(payload.status);\n\n const lines = [\n `${emoji} *Transaction ${payload.status}*`,\n \"\",\n `\\`${this.shortenHash(payload.txHash)}\\``,\n `Chain: ${payload.chainName}`,\n payload.valueFormatted ? `Value: ${payload.valueFormatted}` : \"\",\n payload.confirmations ? `Confirm: ${payload.confirmations}` : \"\",\n \"\",\n payload.explorerUrl\n ? `🔗 [View on Explorer](${payload.explorerUrl})`\n : \"\",\n ];\n\n return lines.filter(Boolean).join(\"\\n\");\n }\n\n private shortenHash(hash: string): string {\n if (hash.length <= 12) return hash;\n return `${hash.slice(0, 8)}...${hash.slice(-4)}`;\n }\n\n private statusEmoji(status: string): string {\n switch (status) {\n case \"confirmed\":\n return \"✅\";\n case \"failed\":\n return \"❌\";\n case \"pending\":\n return \"⏳\";\n case \"reorg\":\n return \"⚠️\";\n case \"speedup\":\n return \"⏩\";\n case \"cancel\":\n return \"🚫\";\n default:\n return \"ℹ️\";\n }\n }\n}\n\n// ─── NoopChannel ──────────────────────────────────────────────────────\n\n/**\n * No-op channel for testing or disabling notifications entirely.\n */\nexport class NoopChannel implements NotificationChannel {\n readonly id = \"noop\";\n readonly name = \"No-op\";\n\n getCapabilities(): ChannelCapability {\n return {\n supportsRichText: false,\n supportsActionButtons: false,\n supportsMedia: false,\n maxLength: 0,\n isBackground: false,\n };\n }\n\n isAvailable(): boolean {\n return true;\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n\n async send(_payload: NotificationPayload): Promise<void> {\n // Nothing\n }\n}\n","/**\n * Notifier — Push Notification Core.\n *\n * Central orchestrator for transaction lifecycle push notifications.\n * Manages watch registrations, channel adapters, user preferences,\n * mute rules, and event-driven status dispatch.\n *\n * @see docs/features/push-notification.md\n */\n\nimport type {\n MuteRule,\n NotificationChannel,\n NotificationFrequency,\n NotificationPayload,\n NotificationWatch,\n NotifierOptions,\n TxMetadata,\n TxStatus,\n TxStatusCallback,\n UserNotificationPreferences,\n} from \"./types\";\n\n// ─── Helpers ───────────────────────────────────────────────────────────\n\nlet _notifIdCounter = 0;\n\nfunction generateId(): string {\n _notifIdCounter++;\n return `notif_${Date.now()}_${_notifIdCounter}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nconst STORAGE_KEY_PREFS = \"naculus_notif_prefs\";\nconst STORAGE_KEY_WATCHES = \"naculus_notif_watches\";\nconst STORAGE_KEY_MUTE_RULES = \"naculus_notif_mute_rules\";\n\n// ─── Default Preferences ──────────────────────────────────────────────\n\nconst DEFAULT_PREFERENCES: UserNotificationPreferences = {\n channels: [\"inapp\"],\n frequency: \"final-only\",\n confirmInterval: 6,\n pendingTimeout: 300,\n};\n\n// ─── Notifier ─────────────────────────────────────────────────────────\n\nexport class Notifier {\n private channels: Map<string, NotificationChannel> = new Map();\n private watches: Map<string, NotificationWatch> = new Map(); // txHash -> watch\n private preferences: Map<string, UserNotificationPreferences> = new Map(); // userId -> prefs\n private muteRules: Map<string, MuteRule[]> = new Map(); // userId -> rules\n private statusCallbacks: Map<string, Set<TxStatusCallback>> = new Map(); // txHash -> callbacks\n private defaultPreferences: UserNotificationPreferences;\n private storage?: NotifierOptions[\"storage\"];\n\n constructor(options?: NotifierOptions) {\n this.defaultPreferences = {\n ...DEFAULT_PREFERENCES,\n ...options?.defaultPreferences,\n };\n this.storage = options?.storage;\n }\n\n // ── Channel Management ─────────────────────────────────────────────\n\n registerChannel(channel: NotificationChannel): void {\n this.channels.set(channel.id, channel);\n }\n\n unregisterChannel(channelId: string): void {\n this.channels.delete(channelId);\n }\n\n getChannel(channelId: string): NotificationChannel | undefined {\n return this.channels.get(channelId);\n }\n\n getActiveChannels(): string[] {\n return Array.from(this.channels.values())\n .filter((c) => c.isAvailable())\n .map((c) => c.id);\n }\n\n // ── Watch Management ───────────────────────────────────────────────\n\n /**\n * Start watching a transaction for notifications.\n *\n * When the tx status changes, notifications will be dispatched\n * to all registered channels based on the watch configuration\n * and the user's preferences + mute rules.\n */\n watchTx(\n hash: string,\n chainId: string,\n options?: {\n userId?: string;\n channels?: string[];\n frequency?: NotificationFrequency;\n txMetadata?: Partial<TxMetadata>;\n },\n ): void {\n const userId = options?.userId ?? \"default\";\n const prefs = this.getPreferences(userId);\n\n const watch: NotificationWatch = {\n txHash: hash,\n userId,\n channels: options?.channels ?? prefs.channels,\n frequency: options?.frequency ?? prefs.frequency,\n confirmInterval: prefs.confirmInterval,\n txMetadata: {\n chainId,\n value: options?.txMetadata?.value,\n to: options?.txMetadata?.to,\n txType: options?.txMetadata?.txType ?? \"custom\",\n },\n createdAt: Date.now(),\n };\n\n this.watches.set(hash, watch);\n void this.persistWatches();\n }\n\n /**\n * Stop watching a transaction.\n */\n unregisterTxWatch(hash: string): void {\n const watch = this.watches.get(hash);\n if (watch) {\n watch.resolvedAt = Date.now();\n }\n this.watches.delete(hash);\n this.statusCallbacks.delete(hash);\n void this.persistWatches();\n }\n\n getWatch(hash: string): NotificationWatch | undefined {\n return this.watches.get(hash);\n }\n\n getAllWatches(): NotificationWatch[] {\n return Array.from(this.watches.values());\n }\n\n // ── Status Callbacks ───────────────────────────────────────────────\n\n /**\n * Subscribe to status changes for a specific transaction.\n *\n * Returns an unsubscribe function.\n */\n onTxStatus(hash: string, callback: TxStatusCallback): () => void {\n if (!this.statusCallbacks.has(hash)) {\n this.statusCallbacks.set(hash, new Set());\n }\n this.statusCallbacks.get(hash)!.add(callback);\n\n return () => {\n this.statusCallbacks.get(hash)?.delete(callback);\n };\n }\n\n // ── Status Dispatch ────────────────────────────────────────────────\n\n /**\n * Called when a transaction's status changes.\n *\n * This is the main entry point from TxMonitor integration.\n * It evaluates mute rules, determines whether to fire based on\n * the frequency preference, and dispatches to all channels.\n */\n async handleTxStatus(\n hash: string,\n status: TxStatus,\n receipt?: {\n confirmations?: number;\n value?: bigint;\n gasUsed?: bigint;\n gasCostUsd?: number;\n },\n ): Promise<void> {\n const watch = this.watches.get(hash);\n if (!watch) return;\n\n // Check mute rules\n const userMuteRules = this.getMuteRules(watch.userId);\n if (this.isMuted(watch.txMetadata, userMuteRules)) {\n return;\n }\n\n // Check whether this status change should produce a notification\n const shouldNotify = this.shouldNotify(\n watch.frequency,\n status,\n receipt?.confirmations,\n );\n\n if (shouldNotify) {\n const payload = this.buildPayload(watch, status, receipt);\n await this.dispatchToChannels(payload, watch.channels);\n }\n\n // Fire callbacks regardless (for in-app state, not channel dispatch)\n const callbacks = this.statusCallbacks.get(hash);\n if (callbacks) {\n const callbackPayload = receipt\n ? {\n confirmations: receipt.confirmations,\n value: receipt.value,\n gasUsed: receipt.gasUsed,\n }\n : undefined;\n for (const cb of callbacks) {\n try {\n cb(status, callbackPayload);\n } catch {\n // Silently handle callback errors\n }\n }\n }\n\n // Clean up if terminal status\n if (status === \"confirmed\" || status === \"failed\") {\n this.unregisterTxWatch(hash);\n }\n }\n\n // ── Direct Notify ──────────────────────────────────────────────────\n\n /**\n * Send a notification directly (bypasses watch and frequency checks).\n */\n async notify(\n payload: Omit<NotificationPayload, \"id\" | \"timestamp\">,\n channels?: string[],\n ): Promise<void> {\n const fullPayload: NotificationPayload = {\n ...payload,\n id: generateId(),\n timestamp: Date.now(),\n };\n\n const targetChannels = channels ?? this.getActiveChannels();\n await this.dispatchToChannels(fullPayload, targetChannels);\n }\n\n // ── Preferences ────────────────────────────────────────────────────\n\n setPreferences(\n userId: string,\n prefs: Partial<UserNotificationPreferences>,\n ): void {\n const current = this.preferences.get(userId) ?? {\n ...this.defaultPreferences,\n };\n this.preferences.set(userId, { ...current, ...prefs });\n void this.persistPreferences();\n }\n\n getPreferences(userId: string): UserNotificationPreferences {\n return { ...(this.preferences.get(userId) ?? this.defaultPreferences) };\n }\n\n getDefaultPreferences(): UserNotificationPreferences {\n return { ...this.defaultPreferences };\n }\n\n // ── Mute Rules ─────────────────────────────────────────────────────\n\n addMuteRule(userId: string, rule: MuteRule): void {\n const rules = this.muteRules.get(userId) ?? [];\n rules.push(rule);\n this.muteRules.set(userId, rules);\n void this.persistMuteRules();\n }\n\n removeMuteRule(userId: string, ruleId: string): void {\n const rules = this.muteRules.get(userId);\n if (!rules) return;\n this.muteRules.set(\n userId,\n rules.filter((r) => r.id !== ruleId),\n );\n void this.persistMuteRules();\n }\n\n getMuteRules(userId: string): MuteRule[] {\n return [...(this.muteRules.get(userId) ?? [])];\n }\n\n /**\n * Evaluate whether a transaction should be muted based on active rules.\n */\n isMuted(metadata: TxMetadata, rules: MuteRule[]): boolean {\n const now = Date.now();\n for (const rule of rules) {\n // Skip expired rules\n if (rule.until && rule.until <= now) continue;\n\n // Chain match\n if (rule.chainId && rule.chainId !== metadata.chainId) continue;\n\n // Tx type match\n if (rule.txType && rule.txType !== metadata.txType) continue;\n\n // Value threshold (only if minValueUsd set and value is defined)\n if (rule.minValueUsd !== undefined && metadata.value !== undefined) {\n // Note: metadata.value is bigint; we skip mute if value is 0 (can't convert)\n // Real USD conversion requires an oracle; for now only match on explicit 0-value\n if (metadata.value === BigInt(0)) {\n return true; // 0-value tx is below any positive threshold\n }\n }\n\n // Contract address match\n if (rule.contractAddress && metadata.to) {\n if (rule.contractAddress.toLowerCase() === metadata.to.toLowerCase()) {\n return true;\n }\n continue; // if contractAddress specified but doesn't match, skip this rule\n }\n\n // If we got here without being skipped, the rule matched\n return true;\n }\n return false;\n }\n\n // ── Persistence ────────────────────────────────────────────────────\n\n /** Restore persisted state (call on initialization). */\n async restore(): Promise<void> {\n if (!this.storage) return;\n\n const prefs =\n await this.storage.getItem<Record<string, UserNotificationPreferences>>(\n STORAGE_KEY_PREFS,\n );\n if (prefs) {\n for (const [userId, p] of Object.entries(prefs)) {\n this.preferences.set(userId, p);\n }\n }\n\n const watches =\n await this.storage.getItem<NotificationWatch[]>(STORAGE_KEY_WATCHES);\n if (watches) {\n for (const w of watches) {\n if (!w.resolvedAt) {\n this.watches.set(w.txHash, w);\n }\n }\n }\n\n const muteRules = await this.storage.getItem<Record<string, MuteRule[]>>(\n STORAGE_KEY_MUTE_RULES,\n );\n if (muteRules) {\n for (const [userId, rules] of Object.entries(muteRules)) {\n this.muteRules.set(userId, rules);\n }\n }\n }\n\n private async persistPreferences(): Promise<void> {\n if (!this.storage) return;\n const obj: Record<string, UserNotificationPreferences> = {};\n for (const [userId, prefs] of this.preferences) {\n obj[userId] = prefs;\n }\n await this.storage.setItem(STORAGE_KEY_PREFS, obj);\n }\n\n private async persistWatches(): Promise<void> {\n if (!this.storage) return;\n await this.storage.setItem(STORAGE_KEY_WATCHES, this.getAllWatches());\n }\n\n private async persistMuteRules(): Promise<void> {\n if (!this.storage) return;\n const obj: Record<string, MuteRule[]> = {};\n for (const [userId, rules] of this.muteRules) {\n obj[userId] = rules;\n }\n await this.storage.setItem(STORAGE_KEY_MUTE_RULES, obj);\n }\n\n // ── Internal ───────────────────────────────────────────────────────\n\n private shouldNotify(\n frequency: NotificationFrequency,\n status: TxStatus,\n confirmations?: number,\n ): boolean {\n if (frequency === \"muted\") return false;\n\n // Terminal states always fire in per-tx and final-only\n if (status === \"confirmed\" || status === \"failed\") return true;\n\n // Error/reorg/speedup/cancel always fire (important events)\n if (status === \"reorg\" || status === \"speedup\" || status === \"cancel\")\n return true;\n\n // Pending only fires in per-tx mode\n if (status === \"pending\") {\n return frequency === \"per-tx\";\n }\n\n return false;\n }\n\n private buildPayload(\n watch: NotificationWatch,\n status: TxStatus,\n receipt?: {\n confirmations?: number;\n value?: bigint;\n gasUsed?: bigint;\n gasCostUsd?: number;\n },\n ): NotificationPayload {\n const labels: Record<TxStatus, { title: string; body: string }> = {\n pending: {\n title: \"Transaction Pending\",\n body: \"Your transaction has been broadcast and is waiting for confirmation.\",\n },\n confirmed: {\n title: \"Transaction Confirmed\",\n body: \"Your transaction has been confirmed on-chain.\",\n },\n failed: {\n title: \"Transaction Failed\",\n body: \"The transaction reverted or failed. Check the block explorer for details.\",\n },\n reorg: {\n title: \"Chain Reorg Detected\",\n body: \"A chain reorganization affected your transaction.\",\n },\n speedup: {\n title: \"Transaction Accelerated\",\n body: \"Your transaction has been sped up with a higher gas price.\",\n },\n cancel: {\n title: \"Transaction Cancelled\",\n body: \"Your transaction has been cancelled.\",\n },\n };\n\n const label = labels[status] ?? { title: status, body: \"\" };\n\n return {\n id: generateId(),\n userId: watch.userId,\n txHash: watch.txHash,\n chainId: watch.txMetadata.chainId,\n chainName: watch.txMetadata.chainId, // Real chain name resolution would happen in integration\n status,\n title: label.title,\n body: label.body,\n value: receipt?.value ?? watch.txMetadata.value,\n gasUsed: receipt?.gasUsed,\n gasCostUsd: receipt?.gasCostUsd,\n confirmations: receipt?.confirmations,\n timestamp: Date.now(),\n };\n }\n\n private async dispatchToChannels(\n payload: NotificationPayload,\n channelIds: string[],\n ): Promise<void> {\n const results = await Promise.allSettled(\n channelIds.map(async (channelId) => {\n const channel = this.channels.get(channelId);\n if (!channel || !channel.isAvailable()) return;\n await channel.send(payload);\n }),\n );\n\n // Log failures silently (don't crash the notifier for one broken channel)\n for (const result of results) {\n if (result.status === \"rejected\") {\n console.error(\"[Notifier] Channel dispatch failed:\", result.reason);\n }\n }\n }\n}\n","export interface WalletPermission {\n parentCapability: string;\n invoker: string;\n date?: number;\n caveats?: { type: string; value: unknown }[];\n}\n\nexport interface PermissionsRequest {\n eth_accounts: Record<string, never>;\n}\n\nexport async function getPermissions(provider: {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n}): Promise<WalletPermission[] | null> {\n try {\n const result = (await provider.request({\n method: \"wallet_getPermissions\",\n })) as WalletPermission[];\n return result?.length > 0 ? result : null;\n } catch {\n return null;\n }\n}\n\nexport async function requestPermissions(provider: {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n}): Promise<WalletPermission[]> {\n const result = (await provider.request({\n method: \"wallet_requestPermissions\",\n params: [{ eth_accounts: {} }],\n })) as WalletPermission[];\n return result;\n}\n\nexport function extractAccountsFromPermissions(\n permissions: WalletPermission[],\n): string[] {\n const ethAccountsPerm = permissions.find(\n (p) => p.parentCapability === \"eth_accounts\",\n );\n if (!ethAccountsPerm) return [];\n\n const caveat = ethAccountsPerm.caveats?.find(\n (c) => c.type === \"restrictReturnedAccounts\",\n );\n if (caveat && Array.isArray(caveat.value)) {\n return caveat.value as string[];\n }\n\n return [];\n}\n\nexport function hasPermission(\n permissions: WalletPermission[] | null,\n capability: string,\n): boolean {\n if (!permissions) return false;\n return permissions.some((p) => p.parentCapability === capability);\n}\n","export const DEFAULT_RPC_URLS: Record<string, string> = {\n \"eip155:1\": \"https://eth.llamarpc.com\",\n \"eip155:5\": \"https://goerli.llamarpc.com\",\n \"eip155:11155111\": \"https://sepolia.llamarpc.com\",\n \"eip155:137\": \"https://polygon.llamarpc.com\",\n \"eip155:10\": \"https://optimism.llamarpc.com\",\n \"eip155:42161\": \"https://arbitrum.llamarpc.com\",\n \"eip155:8453\": \"https://base.llamarpc.com\",\n \"solana:0\": \"https://api.mainnet-beta.solana.com\",\n \"solana:1\": \"https://api.devnet.solana.com\",\n \"solana:2\": \"https://api.testnet.solana.com\",\n};\n\n/**\n * Get the default RPC URL for a given CAIP-2 chainId.\n * Returns undefined if no default is configured.\n */\nexport function getRpcUrl(\n chainId: string,\n fallback?: string,\n): string | undefined {\n return DEFAULT_RPC_URLS[chainId] ?? fallback;\n}\n","import { keccak_256 } from \"@noble/hashes/sha3\";\nimport { bytesToHex, concatBytes, hexToBytes } from \"@noble/hashes/utils\";\n\nconst textEncoder = new TextEncoder();\nfunction stringToBytes(str: string): Uint8Array {\n return textEncoder.encode(str);\n}\n\nimport type { AddressResult, NameResult, ResolverProvider } from \"../types\";\nimport { ResolutionError } from \"../types\";\n\n// ── Constants ────────────────────────────────────────────────────\n\n/** ENS Registry (Ethereum Mainnet). */\nexport const ENS_REGISTRY_ADDRESS =\n \"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\" as const;\n\n/** Reverse Registrar. */\nexport const ENS_REVERSE_REGISTRAR =\n \"0x084b1c3C81545dD370363A3AaE2416F0D5Ee5c0\" as const;\n\n/** ENS Registry ABI (minimal — only the functions we need). */\nconst ENS_REGISTRY_ABI = [\n {\n name: \"resolver\",\n type: \"function\",\n inputs: [{ name: \"node\", type: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"owner\",\n type: \"function\",\n inputs: [{ name: \"node\", type: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n] as const;\n\n/** Resolver ABI (minimal). */\nconst RESOLVER_ABI = [\n {\n name: \"addr\",\n type: \"function\",\n inputs: [{ name: \"node\", type: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"name\",\n type: \"function\",\n inputs: [{ name: \"node\", type: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"string\" }],\n },\n] as const;\n\nconst EMPTY_ADDR = `0x${\"00\".repeat(20)}` as const;\n\n/**\n * ENS namehash algorithm.\n * Converts a domain like \"vitalik.eth\" into a 32-byte node hash.\n */\nfunction namehash(name: string): `0x${string}` {\n let node: Uint8Array = new Uint8Array(32).fill(0);\n\n if (name) {\n const labels = name.split(\".\");\n for (let i = labels.length - 1; i >= 0; i--) {\n const labelHash = keccak_256(stringToBytes(labels[i].toLowerCase()));\n node = keccak_256(concatBytes(node, labelHash));\n }\n }\n\n return `0x${bytesToHex(node)}`;\n}\n\n/**\n * Labelhash for a single label (used in reverse lookup).\n */\nfunction labelhash(label: string): `0x${string}` {\n return `0x${bytesToHex(keccak_256(stringToBytes(label.toLowerCase())))}`;\n}\n\n// ── ABI Encoding ─────────────────────────────────────────────────\n\n/**\n * Encode a function call for eth_call.\n * Minimal ABI encoder — no dependency on ethers.js.\n */\nfunction encodeFunctionCall(\n abi: readonly { name: string; inputs: readonly { type: string }[] }[],\n fnName: string,\n args: (`0x${string}` | string)[],\n): `0x${string}` {\n const abiEntry = abi.find((f) => f.name === fnName);\n if (!abiEntry) throw new Error(`Function ${fnName} not found in ABI`);\n\n // Compute function selector (first 4 bytes of keccak256 of signature)\n const inputs = abiEntry.inputs.map((i) => i.type).join(\",\");\n const signature = `${fnName}(${inputs})`;\n const selector = keccak_256(stringToBytes(signature)).slice(0, 4);\n\n // Encode arguments\n const encodedArgs = args.map((arg) => {\n if (typeof arg === \"string\" && arg.startsWith(\"0x\")) {\n // bytes32 or address — pad to 32 bytes\n const hex = arg.slice(2).padStart(64, \"0\");\n return hexToBytes(hex);\n }\n // string — dynamic encoding\n const bytes = stringToBytes(arg);\n // Offset (currently at position 0 as first dynamic arg)\n const offset = new Uint8Array(32);\n // Length\n const lengthBytes = new Uint8Array(32);\n const lenView = new DataView(lengthBytes.buffer);\n lenView.setBigUint64(24, BigInt(bytes.length), false);\n // Data padded to 32 bytes\n const paddedLen = Math.ceil(bytes.length / 32) * 32;\n const padded = new Uint8Array(paddedLen);\n padded.set(bytes);\n return concatBytes(offset, lengthBytes, padded);\n });\n\n const encoded = concatBytes(selector, ...encodedArgs);\n return `0x${bytesToHex(encoded)}`;\n}\n\n/**\n * Decode an address (first 12 bytes zero-padded address).\n */\nfunction decodeAddress(data: `0x${string}`): `0x${string}` {\n const bytes = hexToBytes(data.slice(2));\n // Address is bytes12 padding + bytes20 address\n if (bytes.length < 32) {\n throw new ResolutionError(\n \"INVALID_ADDRESS\",\n \"Invalid response length for address decode\",\n );\n }\n const addrBytes = bytes.slice(12, 32);\n return `0x${bytesToHex(addrBytes)}`;\n}\n\n/**\n * Decode a string from ABI-encoded data.\n */\nfunction decodeString(data: `0x${string}`): string {\n const bytes = hexToBytes(data.slice(2));\n if (bytes.length < 32)\n throw new ResolutionError(\n \"INVALID_ADDRESS\",\n \"Invalid response for string decode\",\n );\n\n // offset (first 32 bytes)\n // length (second 32 bytes)\n const lengthBytes = bytes.slice(32, 64);\n const len = Number(new DataView(lengthBytes.buffer).getBigUint64(24, false));\n // string data starts at byte 64\n const strBytes = bytes.slice(64, 64 + len);\n return new TextDecoder().decode(strBytes);\n}\n\n// ── RPC Helper ───────────────────────────────────────────────────\n\ninterface EthCallParams {\n to: `0x${string}`;\n data: `0x${string}`;\n}\n\nasync function ethCall(\n rpcUrl: string,\n params: EthCallParams,\n): Promise<`0x${string}`> {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"eth_call\",\n params: [params, \"latest\"],\n }),\n });\n\n if (!response.ok) {\n throw new ResolutionError(\n \"PROVIDER_UNAVAILABLE\",\n `ENS RPC call failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: `0x${string}`;\n error?: { message: string };\n };\n\n if (json.error) {\n throw new ResolutionError(\n \"NAME_NOT_FOUND\",\n `ENS lookup failed: ${json.error.message}`,\n );\n }\n\n return json.result ?? \"0x\";\n}\n\n// ── Provider ─────────────────────────────────────────────────────\n\n/**\n * ENS name resolution provider.\n *\n * Resolves `.eth` names via direct eth_call to ENS contracts.\n * Does NOT depend on ethers.js or web3.js — uses plain fetch + minimal\n * ABI encoding.\n */\nexport class ENSProvider implements ResolverProvider {\n readonly chainType = \"eip155\" as const;\n private readonly rpcUrl: string;\n\n constructor(rpcUrl: string) {\n this.rpcUrl = rpcUrl;\n }\n\n supportsName(name: string): boolean {\n return name.toLowerCase().endsWith(\".eth\");\n }\n\n async resolveName(name: string): Promise<AddressResult | null> {\n const cleanName = name.toLowerCase();\n if (!cleanName.endsWith(\".eth\")) return null;\n\n const node = namehash(cleanName);\n\n // 1. Get resolver address from ENS Registry\n const resolverAddr = await this.getResolver(node);\n if (\n !resolverAddr ||\n resolverAddr === \"0x0000000000000000000000000000000000000000\"\n ) {\n return null;\n }\n\n // 2. Call resolver.addr(node)\n const addrData = encodeFunctionCall(RESOLVER_ABI, \"addr\", [node]);\n const result = await ethCall(this.rpcUrl, {\n to: resolverAddr,\n data: addrData,\n });\n\n if (\n !result ||\n result === \"0x\" ||\n result ===\n \"0x0000000000000000000000000000000000000000000000000000000000000000\"\n ) {\n return null;\n }\n\n const address = decodeAddress(result);\n\n return {\n address,\n chainType: \"eip155\",\n name: cleanName,\n };\n }\n\n async lookupAddress(address: string): Promise<NameResult | null> {\n const cleanAddr = address.startsWith(\"0x\")\n ? (address.toLowerCase() as `0x${string}`)\n : `0x${address.toLowerCase()}`;\n\n // Reverse lookup: addr.reverse node\n const reverseNode = namehash(\n `${cleanAddr.slice(2).toLowerCase()}.addr.reverse`,\n );\n\n // 1. Get resolver from reverse registrar\n const resolverAddr = await this.getResolver(reverseNode);\n if (\n !resolverAddr ||\n resolverAddr === \"0x0000000000000000000000000000000000000000\"\n ) {\n return null;\n }\n\n // 2. Call resolver.name(node)\n const nameData = encodeFunctionCall(RESOLVER_ABI, \"name\", [reverseNode]);\n const result = await ethCall(this.rpcUrl, {\n to: resolverAddr,\n data: nameData,\n });\n\n if (!result || result === \"0x\") return null;\n\n try {\n const name = decodeString(result);\n if (!name) return null;\n\n return {\n name,\n chainType: \"eip155\",\n isPrimary: true,\n };\n } catch {\n return null;\n }\n }\n\n private async getResolver(\n node: `0x${string}`,\n ): Promise<`0x${string}` | null> {\n const data = encodeFunctionCall(ENS_REGISTRY_ABI, \"resolver\", [node]);\n try {\n const result = await ethCall(this.rpcUrl, {\n to: ENS_REGISTRY_ADDRESS,\n data,\n });\n if (!result || result === \"0x\") return null;\n return decodeAddress(result);\n } catch {\n return null;\n }\n }\n}\n","import type {\n NAMESPACE_EIP155,\n NAMESPACE_SOLANA,\n NAMESPACE_XRPL,\n} from \"../constants\";\n\n/**\n * Result of a forward name resolution (name → address).\n */\nexport interface AddressResult {\n /** Resolved address (without CAIP-10 prefix). */\n address: string;\n /** Chain type that this address belongs to. */\n chainType: \"eip155\" | \"solana\" | \"xrpl\";\n /** The original name that was resolved. */\n name: string;\n /** Optional chain ID (CAIP-2 format) that the name was resolved on. */\n chainId?: string;\n}\n\n/**\n * Result of a reverse lookup (address → name).\n */\nexport interface NameResult {\n /** Resolved name (e.g. \"vitalik.eth\", \"vitalik.sol\"). */\n name: string;\n /** Chain type that this name belongs to. */\n chainType: \"eip155\" | \"solana\" | \"xrpl\";\n /** Whether the result is a primary / canonical name. */\n isPrimary: boolean;\n}\n\n/**\n * Provider interface for a specific name service (ENS, SNS, etc.).\n */\nexport interface ResolverProvider {\n /** The chain type this provider handles. */\n chainType: \"eip155\" | \"solana\" | \"xrpl\";\n /** Resolve a name to an address. Returns null if name is not found. */\n resolveName(name: string): Promise<AddressResult | null>;\n /** Reverse-lookup an address to a name. Returns null if no name is found. */\n lookupAddress(address: string): Promise<NameResult | null>;\n /** Check if this provider can handle a given name (by suffix or format). */\n supportsName(name: string): boolean;\n}\n\n/**\n * Error codes for name resolution failures.\n */\nexport type ResolutionErrorCode =\n | \"NAME_NOT_FOUND\"\n | \"PROVIDER_UNAVAILABLE\"\n | \"UNSUPPORTED_NAME_SERVICE\"\n | \"RESOLUTION_TIMEOUT\"\n | \"INVALID_NAME\"\n | \"INVALID_ADDRESS\";\n\n/**\n * Error class for name resolution failures.\n */\nexport class ResolutionError extends Error {\n readonly code: ResolutionErrorCode;\n\n constructor(code: ResolutionErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = \"ResolutionError\";\n this.code = code;\n if (cause instanceof Error) {\n this.cause = cause;\n }\n }\n}\n\n/**\n * Configuration for the name resolver.\n */\nexport interface NameResolverConfig {\n providers?: {\n ens?: { rpcUrl: string };\n sns?: { rpcUrl: string };\n };\n cache?: {\n /** TTL in milliseconds (default: 5 minutes). */\n ttlMs: number;\n };\n /** Default timeout for resolution requests in ms. */\n timeoutMs?: number;\n}\n\n/**\n * Internal cache entry with expiry.\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Simple in-memory cache with TTL.\n */\nexport class ResolverCache {\n private cache = new Map<string, CacheEntry<unknown>>();\n private readonly ttlMs: number;\n\n constructor(ttlMs: number = 300_000) {\n this.ttlMs = ttlMs;\n }\n\n get<T>(key: string): T | null {\n const entry = this.cache.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T): void {\n this.cache.set(key, {\n value,\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n /** Remove stale entries. */\n prune(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n","/**\n * Internal Merkle-Damgard hash utils.\n * @module\n */\nimport { type Input, Hash, abytes, aexists, aoutput, clean, createView, toBytes } from './utils.ts';\n\n/** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */\nexport function setBigUint64(\n view: DataView,\n byteOffset: number,\n value: bigint,\n isLE: boolean\n): void {\n if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\n\n/** Choice: a ? b : c */\nexport function Chi(a: number, b: number, c: number): number {\n return (a & b) ^ (~a & c);\n}\n\n/** Majority function, true if any two inputs is true. */\nexport function Maj(a: number, b: number, c: number): number {\n return (a & b) ^ (a & c) ^ (b & c);\n}\n\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n */\nexport abstract class HashMD<T extends HashMD<T>> extends Hash<T> {\n protected abstract process(buf: DataView, offset: number): void;\n protected abstract get(): number[];\n protected abstract set(...args: number[]): void;\n abstract destroy(): void;\n protected abstract roundClean(): void;\n\n readonly blockLen: number;\n readonly outputLen: number;\n readonly padOffset: number;\n readonly isLE: boolean;\n\n // For partial updates less than block size\n protected buffer: Uint8Array;\n protected view: DataView;\n protected finished = false;\n protected length = 0;\n protected pos = 0;\n protected destroyed = false;\n\n constructor(blockLen: number, outputLen: number, padOffset: number, isLE: boolean) {\n super();\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data: Input): this {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { view, buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len; ) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input, cast it to view and process\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n clean(this.buffer.subarray(pos));\n // we have less than padOffset left in buffer, so we cannot put length in\n // current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++) buffer[i] = 0;\n // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n // So we just write lowest 64 bits of that value.\n setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);\n }\n digest(): Uint8Array {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to?: T): T {\n to ||= new (this.constructor as any)() as T;\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.destroyed = destroyed;\n to.finished = finished;\n to.length = length;\n to.pos = pos;\n if (length % blockLen) to.buffer.set(buffer);\n return to;\n }\n clone(): T {\n return this._cloneInto();\n }\n}\n\n/**\n * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.\n * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.\n */\n\n/** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */\nexport const SHA256_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n\n/** Initial SHA224 state. Bits 32..64 of frac part of sqrt of primes 23..53 */\nexport const SHA224_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,\n]);\n\n/** Initial SHA384 state. Bits 0..64 of frac part of sqrt of primes 23..53 */\nexport const SHA384_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,\n 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,\n]);\n\n/** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */\nexport const SHA512_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,\n]);\n","/**\n * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.\n * SHA256 is the fastest hash implementable in JS, even faster than Blake3.\n * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and\n * [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).\n * @module\n */\nimport { Chi, HashMD, Maj, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from './_md.ts';\nimport * as u64 from './_u64.ts';\nimport { type CHash, clean, createHasher, rotr } from './utils.ts';\n\n/**\n * Round constants:\n * First 32 bits of fractional parts of the cube roots of the first 64 primes 2..311)\n */\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n\n/** Reusable temporary buffer. \"W\" comes straight from spec. */\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\nexport class SHA256 extends HashMD<SHA256> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n protected A: number = SHA256_IV[0] | 0;\n protected B: number = SHA256_IV[1] | 0;\n protected C: number = SHA256_IV[2] | 0;\n protected D: number = SHA256_IV[3] | 0;\n protected E: number = SHA256_IV[4] | 0;\n protected F: number = SHA256_IV[5] | 0;\n protected G: number = SHA256_IV[6] | 0;\n protected H: number = SHA256_IV[7] | 0;\n\n constructor(outputLen: number = 32) {\n super(64, outputLen, 8, false);\n }\n protected get(): [number, number, number, number, number, number, number, number] {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n protected set(\n A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number\n ): void {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n protected roundClean(): void {\n clean(SHA256_W);\n }\n destroy(): void {\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n\nexport class SHA224 extends SHA256 {\n protected A: number = SHA224_IV[0] | 0;\n protected B: number = SHA224_IV[1] | 0;\n protected C: number = SHA224_IV[2] | 0;\n protected D: number = SHA224_IV[3] | 0;\n protected E: number = SHA224_IV[4] | 0;\n protected F: number = SHA224_IV[5] | 0;\n protected G: number = SHA224_IV[6] | 0;\n protected H: number = SHA224_IV[7] | 0;\n constructor() {\n super(28);\n }\n}\n\n// SHA2-512 is slower than sha256 in js because u64 operations are slow.\n\n// Round contants\n// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409\n// prettier-ignore\nconst K512 = /* @__PURE__ */ (() => u64.split([\n '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',\n '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',\n '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',\n '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',\n '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',\n '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',\n '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',\n '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',\n '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',\n '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',\n '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',\n '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',\n '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',\n '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',\n '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',\n '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',\n '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',\n '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',\n '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',\n '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'\n].map(n => BigInt(n))))();\nconst SHA512_Kh = /* @__PURE__ */ (() => K512[0])();\nconst SHA512_Kl = /* @__PURE__ */ (() => K512[1])();\n\n// Reusable temporary buffers\nconst SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);\nconst SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);\n\nexport class SHA512 extends HashMD<SHA512> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n // h -- high 32 bits, l -- low 32 bits\n protected Ah: number = SHA512_IV[0] | 0;\n protected Al: number = SHA512_IV[1] | 0;\n protected Bh: number = SHA512_IV[2] | 0;\n protected Bl: number = SHA512_IV[3] | 0;\n protected Ch: number = SHA512_IV[4] | 0;\n protected Cl: number = SHA512_IV[5] | 0;\n protected Dh: number = SHA512_IV[6] | 0;\n protected Dl: number = SHA512_IV[7] | 0;\n protected Eh: number = SHA512_IV[8] | 0;\n protected El: number = SHA512_IV[9] | 0;\n protected Fh: number = SHA512_IV[10] | 0;\n protected Fl: number = SHA512_IV[11] | 0;\n protected Gh: number = SHA512_IV[12] | 0;\n protected Gl: number = SHA512_IV[13] | 0;\n protected Hh: number = SHA512_IV[14] | 0;\n protected Hl: number = SHA512_IV[15] | 0;\n\n constructor(outputLen: number = 64) {\n super(128, outputLen, 16, false);\n }\n // prettier-ignore\n protected get(): [\n number, number, number, number, number, number, number, number,\n number, number, number, number, number, number, number, number\n ] {\n const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];\n }\n // prettier-ignore\n protected set(\n Ah: number, Al: number, Bh: number, Bl: number, Ch: number, Cl: number, Dh: number, Dl: number,\n Eh: number, El: number, Fh: number, Fl: number, Gh: number, Gl: number, Hh: number, Hl: number\n ): void {\n this.Ah = Ah | 0;\n this.Al = Al | 0;\n this.Bh = Bh | 0;\n this.Bl = Bl | 0;\n this.Ch = Ch | 0;\n this.Cl = Cl | 0;\n this.Dh = Dh | 0;\n this.Dl = Dl | 0;\n this.Eh = Eh | 0;\n this.El = El | 0;\n this.Fh = Fh | 0;\n this.Fl = Fl | 0;\n this.Gh = Gh | 0;\n this.Gl = Gl | 0;\n this.Hh = Hh | 0;\n this.Hl = Hl | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) {\n SHA512_W_H[i] = view.getUint32(offset);\n SHA512_W_L[i] = view.getUint32((offset += 4));\n }\n for (let i = 16; i < 80; i++) {\n // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)\n const W15h = SHA512_W_H[i - 15] | 0;\n const W15l = SHA512_W_L[i - 15] | 0;\n const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);\n const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);\n // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)\n const W2h = SHA512_W_H[i - 2] | 0;\n const W2l = SHA512_W_L[i - 2] | 0;\n const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);\n const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);\n // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];\n const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);\n const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);\n SHA512_W_H[i] = SUMh | 0;\n SHA512_W_L[i] = SUMl | 0;\n }\n let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n // Compression function main loop, 80 rounds\n for (let i = 0; i < 80; i++) {\n // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)\n const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);\n const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);\n //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const CHIh = (Eh & Fh) ^ (~Eh & Gh);\n const CHIl = (El & Fl) ^ (~El & Gl);\n // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]\n // prettier-ignore\n const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);\n const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);\n const T1l = T1ll | 0;\n // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)\n const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);\n const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);\n const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);\n const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);\n Hh = Gh | 0;\n Hl = Gl | 0;\n Gh = Fh | 0;\n Gl = Fl | 0;\n Fh = Eh | 0;\n Fl = El | 0;\n ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));\n Dh = Ch | 0;\n Dl = Cl | 0;\n Ch = Bh | 0;\n Cl = Bl | 0;\n Bh = Ah | 0;\n Bl = Al | 0;\n const All = u64.add3L(T1l, sigma0l, MAJl);\n Ah = u64.add3H(All, T1h, sigma0h, MAJh);\n Al = All | 0;\n }\n // Add the compressed chunk to the current hash value\n ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));\n ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));\n ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));\n ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));\n ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));\n ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));\n ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));\n ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));\n this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);\n }\n protected roundClean(): void {\n clean(SHA512_W_H, SHA512_W_L);\n }\n destroy(): void {\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n }\n}\n\nexport class SHA384 extends SHA512 {\n protected Ah: number = SHA384_IV[0] | 0;\n protected Al: number = SHA384_IV[1] | 0;\n protected Bh: number = SHA384_IV[2] | 0;\n protected Bl: number = SHA384_IV[3] | 0;\n protected Ch: number = SHA384_IV[4] | 0;\n protected Cl: number = SHA384_IV[5] | 0;\n protected Dh: number = SHA384_IV[6] | 0;\n protected Dl: number = SHA384_IV[7] | 0;\n protected Eh: number = SHA384_IV[8] | 0;\n protected El: number = SHA384_IV[9] | 0;\n protected Fh: number = SHA384_IV[10] | 0;\n protected Fl: number = SHA384_IV[11] | 0;\n protected Gh: number = SHA384_IV[12] | 0;\n protected Gl: number = SHA384_IV[13] | 0;\n protected Hh: number = SHA384_IV[14] | 0;\n protected Hl: number = SHA384_IV[15] | 0;\n\n constructor() {\n super(48);\n }\n}\n\n/**\n * Truncated SHA512/256 and SHA512/224.\n * SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as \"intermediary\" IV of SHA512/t.\n * Then t hashes string to produce result IV.\n * See `test/misc/sha2-gen-iv.js`.\n */\n\n/** SHA512/224 IV */\nconst T224_IV = /* @__PURE__ */ Uint32Array.from([\n 0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,\n 0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,\n]);\n\n/** SHA512/256 IV */\nconst T256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,\n 0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,\n]);\n\nexport class SHA512_224 extends SHA512 {\n protected Ah: number = T224_IV[0] | 0;\n protected Al: number = T224_IV[1] | 0;\n protected Bh: number = T224_IV[2] | 0;\n protected Bl: number = T224_IV[3] | 0;\n protected Ch: number = T224_IV[4] | 0;\n protected Cl: number = T224_IV[5] | 0;\n protected Dh: number = T224_IV[6] | 0;\n protected Dl: number = T224_IV[7] | 0;\n protected Eh: number = T224_IV[8] | 0;\n protected El: number = T224_IV[9] | 0;\n protected Fh: number = T224_IV[10] | 0;\n protected Fl: number = T224_IV[11] | 0;\n protected Gh: number = T224_IV[12] | 0;\n protected Gl: number = T224_IV[13] | 0;\n protected Hh: number = T224_IV[14] | 0;\n protected Hl: number = T224_IV[15] | 0;\n\n constructor() {\n super(28);\n }\n}\n\nexport class SHA512_256 extends SHA512 {\n protected Ah: number = T256_IV[0] | 0;\n protected Al: number = T256_IV[1] | 0;\n protected Bh: number = T256_IV[2] | 0;\n protected Bl: number = T256_IV[3] | 0;\n protected Ch: number = T256_IV[4] | 0;\n protected Cl: number = T256_IV[5] | 0;\n protected Dh: number = T256_IV[6] | 0;\n protected Dl: number = T256_IV[7] | 0;\n protected Eh: number = T256_IV[8] | 0;\n protected El: number = T256_IV[9] | 0;\n protected Fh: number = T256_IV[10] | 0;\n protected Fl: number = T256_IV[11] | 0;\n protected Gh: number = T256_IV[12] | 0;\n protected Gl: number = T256_IV[13] | 0;\n protected Hh: number = T256_IV[14] | 0;\n protected Hl: number = T256_IV[15] | 0;\n\n constructor() {\n super(32);\n }\n}\n\n/**\n * SHA2-256 hash function from RFC 4634.\n *\n * It is the fastest JS hash, even faster than Blake3.\n * To break sha256 using birthday attack, attackers need to try 2^128 hashes.\n * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n */\nexport const sha256: CHash = /* @__PURE__ */ createHasher(() => new SHA256());\n/** SHA2-224 hash function from RFC 4634 */\nexport const sha224: CHash = /* @__PURE__ */ createHasher(() => new SHA224());\n\n/** SHA2-512 hash function from RFC 4634. */\nexport const sha512: CHash = /* @__PURE__ */ createHasher(() => new SHA512());\n/** SHA2-384 hash function from RFC 4634. */\nexport const sha384: CHash = /* @__PURE__ */ createHasher(() => new SHA384());\n\n/**\n * SHA2-512/256 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_256: CHash = /* @__PURE__ */ createHasher(() => new SHA512_256());\n/**\n * SHA2-512/224 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_224: CHash = /* @__PURE__ */ createHasher(() => new SHA512_224());\n","/**\n * SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.\n *\n * To break sha256 using birthday attack, attackers need to try 2^128 hashes.\n * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n *\n * Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).\n * @module\n * @deprecated\n */\nimport {\n SHA224 as SHA224n,\n sha224 as sha224n,\n SHA256 as SHA256n,\n sha256 as sha256n,\n} from './sha2.ts';\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA256: typeof SHA256n = SHA256n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha256: typeof sha256n = sha256n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA224: typeof SHA224n = SHA224n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha224: typeof sha224n = sha224n;\n","import { keccak_256 } from \"@noble/hashes/sha3\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex, concatBytes, hexToBytes } from \"@noble/hashes/utils\";\n\nconst textEncoder = new TextEncoder();\nfunction stringToBytes(str: string): Uint8Array {\n return textEncoder.encode(str);\n}\n\nimport type { AddressResult, NameResult, ResolverProvider } from \"../types\";\nimport { ResolutionError } from \"../types\";\n\n// ── Constants ────────────────────────────────────────────────────\n\n/** Bonfida SNS Program ID (mainnet). */\nexport const SNS_PROGRAM_ID = \"namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX\";\n\n/** .sol TLD domain key (PDA). Derived from seeds [\"domain\", \"sol\"]. */\nexport const SOL_TLD_DOMAIN = \"58P1RCHjMiN1eS6LGpmmNvbTYGWCoh2vMGN4JmSScWdT\";\n\n/** The SNS \"name record\" prefix seed. */\nconst NAME_RECORD_SEED = \"name_record\";\n\n/** Central Bank account (SNS owner). */\nconst SNS_CENTRAL_BANK = \"FzU4e4qMA1aCiq3YBoe8ByKK5ubQi9a5kYzP4jcfprh6\";\n\n// ── Helper Constants ────────────────────────────────────────────\n\n/** BASE58 alphabet for decoding Solana addresses. */\nconst ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nconst BASE = BigInt(58);\n\n/** Max retries for RPC calls. */\nconst MAX_RETRIES = 2;\n\n// ── Base58 Decode ────────────────────────────────────────────────\n\n/**\n * Decode a Base58-encoded string to bytes.\n */\nfunction base58Decode(input: string): Uint8Array {\n // Convert to BigInt first\n let num = BigInt(0);\n for (const char of input) {\n const idx = ALPHABET.indexOf(char);\n if (idx === -1) throw new Error(`Invalid Base58 character: ${char}`);\n num = num * BASE + BigInt(idx);\n }\n\n // Convert BigInt to bytes\n const hex = num.toString(16);\n const hexPadded = hex.length % 2 === 0 ? hex : `0${hex}`;\n const bytes = hexToBytes(hexPadded);\n\n // Preserve leading zeros (encoded as '1's)\n const leadingZeros = input.match(/^1*/)?.[0]?.length ?? 0;\n const result = new Uint8Array(leadingZeros + bytes.length);\n result.set(bytes, leadingZeros);\n\n return result;\n}\n\n/**\n * Decode Base58 to a hex string.\n */\nfunction base58ToHex(input: string): string {\n return bytesToHex(base58Decode(input));\n}\n\n// ── PDA Derivation ───────────────────────────────────────────────\n\n/**\n * Derive a Solana PDA (Program Derived Address).\n * Returns [address_bytes, bump_seed].\n */\nfunction findProgramAddress(\n seeds: Uint8Array[],\n programId: Uint8Array,\n): [Uint8Array, number] {\n for (let bump = 255; bump >= 0; bump--) {\n const seedsBytes = concatBytes(...seeds, new Uint8Array([bump]), programId);\n const hash = sha256(seedsBytes);\n // Check that the hash is NOT on the ed25519 curve\n // (simplified: check that the first byte is not a valid curve point)\n // For Solana, PDAs are guaranteed by bump search\n if (hash[31] & 0x80) continue; // Try next bump if high bit is set\n return [hash, bump];\n }\n throw new Error(\"Unable to find a valid bump seed\");\n}\n\n/**\n * Parse a Solana account info response.\n */\nfunction parseAccountInfo(rawData: string): Record<string, unknown> {\n // Decode Base58 account data into hex\n const bytes = base58Decode(rawData);\n // For name records, the format is:\n // - header (bytes): tag (1) + parent_name (32) + owner (32) + class (32)\n // - data (remaining)\n const header = {\n tag: bytes[0],\n parentName: bytesToHex(bytes.slice(1, 33)),\n owner: bytesToHex(bytes.slice(33, 65)),\n class: bytesToHex(bytes.slice(65, 97)),\n };\n\n const content = bytes.slice(97);\n\n return {\n header,\n content: bytesToHex(content),\n rawBytes: bytes.length,\n };\n}\n\n// ── RPC Helper ───────────────────────────────────────────────────\n\ninterface AccountInfo {\n data: string[];\n executable: boolean;\n lamports: number;\n owner: string;\n rentEpoch: number;\n space?: number;\n}\n\nasync function getAccountInfo(\n rpcUrl: string,\n pubkey: string,\n): Promise<AccountInfo | null> {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"getAccountInfo\",\n params: [pubkey, { encoding: \"base58\", commitment: \"confirmed\" }],\n }),\n });\n\n if (!response.ok) {\n throw new ResolutionError(\n \"PROVIDER_UNAVAILABLE\",\n `SNS RPC call failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const json = (await response.json()) as {\n result?: { value: AccountInfo | null };\n error?: { message: string };\n };\n\n if (json.error) {\n throw new ResolutionError(\n \"NAME_NOT_FOUND\",\n `SNS lookup failed: ${json.error.message}`,\n );\n }\n\n return json.result?.value ?? null;\n}\n\n/**\n * Derive the domain key for a .sol name.\n */\nfunction deriveDomainKey(name: string): string {\n // Domain key derivation: PDA with seeds [\"name_record\", tld_domain, name_bytes]\n const tldBytes = base58Decode(SOL_TLD_DOMAIN);\n const nameBytes = stringToBytes(name.toLowerCase().replace(\".sol\", \"\"));\n const programBytes = base58Decode(SNS_PROGRAM_ID);\n\n const seeds = [stringToBytes(NAME_RECORD_SEED), tldBytes, nameBytes];\n\n const [address] = findProgramAddress(seeds, programBytes);\n return bytesToHex(address);\n}\n\n// ── Provider ─────────────────────────────────────────────────────\n\n/**\n * SNS (Solana Name Service) provider.\n *\n * Resolves `.sol` names via Solana RPC, querying the Bonfida SNS program.\n * Uses plain fetch + @noble/hashes — no @solana/web3.js dependency.\n */\nexport class SNSProvider implements ResolverProvider {\n readonly chainType = \"solana\" as const;\n private readonly rpcUrl: string;\n\n constructor(rpcUrl: string) {\n this.rpcUrl = rpcUrl;\n }\n\n supportsName(name: string): boolean {\n return name.toLowerCase().endsWith(\".sol\");\n }\n\n async resolveName(name: string): Promise<AddressResult | null> {\n const cleanName = name.toLowerCase().trim();\n if (!cleanName.endsWith(\".sol\")) return null;\n\n // Derive the domain PDA key for this name\n const domainKey = deriveDomainKey(cleanName);\n\n // Fetch account info for the domain record\n try {\n const accountInfo = await getAccountInfo(\n this.rpcUrl,\n domainKey.length === 64 ? domainKey : `0x${domainKey}`,\n );\n\n // The account info returns data as [base58_data, encoding_type]\n if (!accountInfo || !accountInfo.data || accountInfo.data.length === 0) {\n return null;\n }\n\n // Parse the account data to extract the owner address\n const rawData = accountInfo.data[0];\n const parsed = parseAccountInfo(rawData);\n\n // The \"owner\" field in the header is the Solana address that owns this name\n const ownerHex = (parsed.header as Record<string, unknown>)\n .owner as string;\n\n if (\n !ownerHex ||\n ownerHex ===\n \"0000000000000000000000000000000000000000000000000000000000000000\"\n ) {\n return null;\n }\n\n // Convert hex owner to Base58 (Solana address format)\n // For simplicity, return the hex address — consumers can convert if needed\n // In practice, the owner address is stored as a Solana pubkey (32 bytes)\n const solanaAddress = this.hexToBase58(ownerHex);\n\n return {\n address: solanaAddress,\n chainType: \"solana\",\n name: cleanName,\n };\n } catch (err) {\n if (err instanceof ResolutionError) throw err;\n return null;\n }\n }\n\n async lookupAddress(address: string): Promise<NameResult | null> {\n // SNS doesn't have a standard reverse lookup mechanism via RPC.\n // The Bonfida SNS SDK does this via a gRPC backend.\n // For now, we return null — this can be enhanced with a dedicated\n // SNS indexing service in the future.\n return null;\n }\n\n /**\n * Convert a hex string to a Base58 Solana address.\n */\n private hexToBase58(hex: string): string {\n // Pad to 64 hex chars (32 bytes) for a Solana pubkey\n const normalizedHex = hex.replace(/^0x/, \"\").padStart(64, \"0\");\n const bytes = hexToBytes(normalizedHex.slice(0, 64));\n\n // Convert to BigInt\n let num = BigInt(0);\n for (let i = 0; i < bytes.length; i++) {\n num = num * BigInt(256) + BigInt(bytes[i]);\n }\n\n // Convert to Base58\n if (num === BigInt(0)) return \"11111111111111111111111111111111\";\n\n const chars: string[] = [];\n while (num > BigInt(0)) {\n const remainder = Number(num % BASE);\n chars.push(ALPHABET[remainder]);\n num = num / BASE;\n }\n\n // Add leading '1's for leading zero bytes\n let leadingOnes = 0;\n for (const b of bytes) {\n if (b === 0) leadingOnes++;\n else break;\n }\n\n return \"1\".repeat(leadingOnes) + chars.reverse().join(\"\");\n }\n}\n","import { DEFAULT_RPC_URLS } from \"../rpc\";\nimport { ENSProvider } from \"./providers/ens\";\nimport { SNSProvider } from \"./providers/sns\";\nimport type {\n AddressResult,\n NameResolverConfig,\n NameResult,\n ResolverProvider,\n} from \"./types\";\nimport { ResolutionError, ResolverCache } from \"./types\";\n\n// ── Default RPC URLs ─────────────────────────────────────────────\n\nfunction defaultEnsRpc(): string {\n return DEFAULT_RPC_URLS[\"eip155:1\"] ?? \"https://eth.llamarpc.com\";\n}\n\nfunction defaultSnsRpc(): string {\n return DEFAULT_RPC_URLS[\"solana:0\"] ?? \"https://api.mainnet-beta.solana.com\";\n}\n\n// ── Name Detector ────────────────────────────────────────────────\n\n/**\n * Detect which name service a name belongs to based on its suffix.\n */\nfunction detectNameService(name: string): \".eth\" | \".sol\" | null {\n const lower = name.toLowerCase().trim();\n if (lower.endsWith(\".eth\")) return \".eth\";\n if (lower.endsWith(\".sol\")) return \".sol\";\n return null;\n}\n\n/**\n * Validate that a name is syntactically valid for its service.\n */\nfunction isValidName(name: string, suffix: \".eth\" | \".sol\"): boolean {\n const label = name.toLowerCase().trim().slice(0, -suffix.length);\n if (!label) return false;\n\n // Basic validation: at least one character, no empty parts\n // ENS: valid chars include alphanumeric, hyphens, underscores, emoji\n // SNS: similar constraints\n // For now, just check non-empty with basic char constraints\n if (label.length < 1 || label.length > 255) return false;\n\n // .eth must start with alphanumeric (no leading hyphens)\n if (suffix === \".eth\") {\n if (!/^[a-z0-9]/.test(label)) return false;\n // No consecutive hyphens\n if (/--/.test(label)) return false;\n }\n\n // .sol must start with alphanumeric\n if (suffix === \".sol\") {\n if (!/^[a-z0-9]/.test(label)) return false;\n }\n\n return true;\n}\n\n// ── NameResolver ─────────────────────────────────────────────────\n\n/**\n * Unified name resolution service for ENS / SNS / future name systems.\n *\n * Features:\n * - Auto-detection of name service by suffix (.eth → ENS, .sol → SNS)\n * - Forward resolution: name → address\n * - Reverse lookup: address → name\n * - In-memory caching with configurable TTL\n * - Timeout support\n * - Minimal dependencies (plain fetch, no ethers/web3)\n */\nexport class NameResolver {\n private readonly providers: Map<string, ResolverProvider> = new Map();\n private readonly cache: ResolverCache;\n private readonly timeoutMs: number;\n\n constructor(config?: NameResolverConfig) {\n // Set up cache\n this.cache = new ResolverCache(config?.cache?.ttlMs ?? 300_000);\n this.timeoutMs = config?.timeoutMs ?? 10_000;\n\n // Initialize ENS provider\n const ensRpcUrl = config?.providers?.ens?.rpcUrl ?? defaultEnsRpc();\n this.registerProvider(new ENSProvider(ensRpcUrl));\n\n // Initialize SNS provider\n const snsRpcUrl = config?.providers?.sns?.rpcUrl ?? defaultSnsRpc();\n this.registerProvider(new SNSProvider(snsRpcUrl));\n }\n\n /**\n * Register a custom name resolution provider.\n */\n registerProvider(provider: ResolverProvider): void {\n this.providers.set(provider.chainType, provider);\n }\n\n /**\n * Resolve a human-readable name to a blockchain address.\n *\n * @param name - The name to resolve (e.g. \"vitalik.eth\", \"jupiter.sol\").\n * @returns AddressResult with the resolved address, or null if not found.\n * @throws ResolutionError on provider errors, timeout, or unsupported names.\n */\n async resolveName(name: string): Promise<AddressResult | null> {\n const cleanName = name.trim();\n\n if (!cleanName) {\n throw new ResolutionError(\"INVALID_NAME\", \"Name cannot be empty\");\n }\n\n // Check cache first\n const cacheKey = `resolve:${cleanName.toLowerCase()}`;\n const cached = this.cache.get<AddressResult>(cacheKey);\n if (cached !== null) return cached;\n\n // Detect name service\n const suffix = detectNameService(cleanName);\n if (!suffix) {\n throw new ResolutionError(\n \"UNSUPPORTED_NAME_SERVICE\",\n `Unsupported name service for \"${cleanName}\". Supported suffixes: .eth, .sol`,\n );\n }\n\n if (!isValidName(cleanName, suffix)) {\n throw new ResolutionError(\n \"INVALID_NAME\",\n `Invalid name format: \"${cleanName}\"`,\n );\n }\n\n // Find matching provider\n const provider = this.findProviderForName(cleanName);\n if (!provider) {\n throw new ResolutionError(\n \"UNSUPPORTED_NAME_SERVICE\",\n `No provider found for name: \"${cleanName}\"`,\n );\n }\n\n // Execute resolution with timeout\n const result = await this.withTimeout(\n provider.resolveName(cleanName),\n \"resolveName\",\n );\n\n // Cache the result\n if (result) {\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * Reverse-lookup a blockchain address to find its human-readable name.\n *\n * @param address - The blockchain address to look up.\n * @param chainId - Optional CAIP-2 chain ID to hint which provider to use.\n * @returns NameResult with the resolved name, or null if not found.\n */\n async lookupAddress(\n address: string,\n chainId?: string,\n ): Promise<NameResult | null> {\n if (!address) {\n throw new ResolutionError(\"INVALID_ADDRESS\", \"Address cannot be empty\");\n }\n\n const cleanAddr = address.trim();\n\n // Determine chain type from address format or chainId\n const chainType = this.detectChainType(cleanAddr, chainId);\n\n // Check cache\n const cacheKey = `lookup:${cleanAddr.toLowerCase()}:${chainType}`;\n const cached = this.cache.get<NameResult>(cacheKey);\n if (cached !== null) return cached;\n\n // Find provider for chain type\n const provider = this.providers.get(chainType);\n if (!provider) {\n return null;\n }\n\n // Execute with timeout\n const result = await this.withTimeout(\n provider.lookupAddress(cleanAddr),\n \"lookupAddress\",\n );\n\n // Cache the result\n if (result) {\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * Resolve multiple names in a single batch call.\n * Merges requests by provider to minimize RPC calls.\n *\n * @param names - Array of names to resolve.\n * @returns Map of name to AddressResult (or null if not found).\n */\n async resolveNames(\n names: string[],\n ): Promise<Map<string, AddressResult | null>> {\n const results = new Map<string, AddressResult | null>();\n const errors: Array<{ name: string; error: Error }> = [];\n\n await Promise.allSettled(\n names.map(async (name) => {\n try {\n const result = await this.resolveName(name);\n results.set(name, result);\n } catch (err) {\n errors.push({\n name,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }),\n );\n\n return results;\n }\n\n /**\n * Clear the resolution cache.\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n // ── Internal Helpers ──────────────────────────────────────────\n\n private findProviderForName(name: string): ResolverProvider | undefined {\n for (const provider of this.providers.values()) {\n if (provider.supportsName(name)) return provider;\n }\n return undefined;\n }\n\n private detectChainType(address: string, chainId?: string): string {\n // If chainId is provided, derive from it\n if (chainId) {\n const ns = chainId.split(\":\")[0];\n if (ns === \"eip155\") return \"eip155\";\n if (ns === \"solana\") return \"solana\";\n if (ns === \"xrpl\") return \"xrpl\";\n }\n\n // Auto-detect from address format\n // EVM: starts with 0x, 40 hex chars\n if (/^0x[a-fA-F0-9]{40}$/.test(address)) return \"eip155\";\n // Solana: Base58, 32-44 chars, no 0x prefix\n if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address)) return \"solana\";\n\n // Default to eip155\n return \"eip155\";\n }\n\n private async withTimeout<T>(promise: Promise<T>, label: string): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) =>\n setTimeout(\n () =>\n reject(\n new ResolutionError(\n \"RESOLUTION_TIMEOUT\",\n `${label} timed out after ${this.timeoutMs}ms`,\n ),\n ),\n this.timeoutMs,\n ),\n ),\n ]);\n }\n}\n","/**\n * Storage Adapter Interface\n *\n * Defines the contract for session storage implementations.\n * Allows custom storage backends (localStorage, sessionStorage, IndexedDB, etc.)\n */\n\nexport class StorageError extends Error {\n constructor(\n message: string,\n public code:\n | \"quota_exceeded\"\n | \"not_available\"\n | \"parse_error\"\n | \"unknown\" = \"unknown\",\n cause?: unknown,\n ) {\n super(message);\n this.name = \"StorageError\";\n if (cause) {\n this.cause = cause;\n }\n }\n}\n\nexport interface StorageAdapter {\n get<T>(key: string): Promise<T | null>;\n set<T>(key: string, value: T): Promise<void>;\n remove(key: string): Promise<void>;\n clear(): Promise<void>;\n has(key: string): Promise<boolean>;\n isAvailable(): boolean;\n}\n\nfunction getGlobalStorage(\n key: \"localStorage\" | \"sessionStorage\",\n): Storage | null {\n if (typeof globalThis !== \"undefined\" && key in globalThis) {\n const candidate = (globalThis as Record<string, unknown>)[key];\n if (\n candidate !== null &&\n candidate !== undefined &&\n typeof (candidate as Record<string, unknown>).getItem === \"function\"\n ) {\n return candidate as Storage;\n }\n }\n return null;\n}\n\nfunction isStorageAvailable(type: \"local\" | \"session\"): boolean {\n if (typeof window === \"undefined\") {\n try {\n const storage = getGlobalStorage(\"localStorage\");\n if (storage) {\n const testKey = \"__storage_test__\";\n storage.setItem(testKey, testKey);\n storage.removeItem(testKey);\n return true;\n }\n } catch {\n return false;\n }\n return false;\n }\n\n try {\n const storage =\n type === \"local\" ? window.localStorage : window.sessionStorage;\n const testKey = \"__storage_test__\";\n storage.setItem(testKey, testKey);\n storage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Resolve the Storage object regardless of runtime (browser, jsdom, node, deno). */\nfunction resolveLocalStorage(): Storage | null {\n if (typeof window !== \"undefined\" && window.localStorage) {\n return window.localStorage;\n }\n return getGlobalStorage(\"localStorage\");\n}\n\nfunction resolveSessionStorage(): Storage | null {\n if (typeof window !== \"undefined\" && window.sessionStorage) {\n return window.sessionStorage;\n }\n return getGlobalStorage(\"sessionStorage\");\n}\n\nexport class LocalStorageAdapter implements StorageAdapter {\n private prefix: string;\n private _available: boolean | null = null;\n\n constructor(prefix = \"\") {\n this.prefix = prefix;\n }\n\n private getKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n private getStorage(): Storage | null {\n return resolveLocalStorage();\n }\n\n isAvailable(): boolean {\n if (this._available === null) {\n this._available = isStorageAvailable(\"local\");\n }\n return this._available;\n }\n\n async get<T>(key: string): Promise<T | null> {\n if (!this.isAvailable()) return null;\n\n try {\n const store = this.getStorage();\n if (!store) return null;\n const item = store.getItem(this.getKey(key));\n if (item === null) return null;\n return JSON.parse(item) as T;\n } catch (e) {\n throw new StorageError(\n `Failed to parse storage item: ${key}`,\n \"parse_error\",\n e,\n );\n }\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n if (!this.isAvailable()) {\n throw new StorageError(\"LocalStorage is not available\", \"not_available\");\n }\n\n try {\n const store = this.getStorage();\n if (!store) {\n throw new StorageError(\n \"LocalStorage is not available\",\n \"not_available\",\n );\n }\n store.setItem(this.getKey(key), JSON.stringify(value));\n } catch (e) {\n if (e instanceof DOMException && e.name === \"QuotaExceededError\") {\n throw new StorageError(\n `Storage quota exceeded for key: ${key}`,\n \"quota_exceeded\",\n e,\n );\n }\n throw new StorageError(\n `Failed to set storage item: ${key}`,\n \"unknown\",\n e,\n );\n }\n }\n\n async remove(key: string): Promise<void> {\n if (!this.isAvailable()) return;\n const store = this.getStorage();\n if (store) store.removeItem(this.getKey(key));\n }\n\n async clear(): Promise<void> {\n if (!this.isAvailable()) return;\n const store = this.getStorage();\n if (!store) return;\n\n const prefix = this.prefix || \"\";\n if (!prefix) {\n store.clear();\n return;\n }\n\n const keys = Object.keys(store);\n for (const k of keys) {\n if (k.startsWith(prefix)) {\n store.removeItem(k);\n }\n }\n }\n\n async has(key: string): Promise<boolean> {\n if (!this.isAvailable()) return false;\n return (await this.get(key)) !== null;\n }\n}\n\nexport class SessionStorageAdapter implements StorageAdapter {\n private prefix: string;\n private _available: boolean | null = null;\n\n constructor(prefix = \"\") {\n this.prefix = prefix;\n }\n\n private getKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n isAvailable(): boolean {\n if (this._available === null) {\n this._available = isStorageAvailable(\"session\");\n }\n return this._available;\n }\n\n async get<T>(key: string): Promise<T | null> {\n if (!this.isAvailable()) return null;\n\n try {\n const item = window.sessionStorage.getItem(this.getKey(key));\n if (item === null) return null;\n return JSON.parse(item) as T;\n } catch (e) {\n throw new StorageError(\n `Failed to parse storage item: ${key}`,\n \"parse_error\",\n e,\n );\n }\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n if (!this.isAvailable()) {\n throw new StorageError(\n \"SessionStorage is not available\",\n \"not_available\",\n );\n }\n\n try {\n window.sessionStorage.setItem(this.getKey(key), JSON.stringify(value));\n } catch (e) {\n if (e instanceof DOMException && e.name === \"QuotaExceededError\") {\n throw new StorageError(\n `Storage quota exceeded for key: ${key}`,\n \"quota_exceeded\",\n e,\n );\n }\n throw new StorageError(\n `Failed to set storage item: ${key}`,\n \"unknown\",\n e,\n );\n }\n }\n\n async remove(key: string): Promise<void> {\n if (!this.isAvailable()) return;\n window.sessionStorage.removeItem(this.getKey(key));\n }\n\n async clear(): Promise<void> {\n if (!this.isAvailable()) return;\n\n const prefix = this.prefix || \"\";\n if (!prefix) {\n window.sessionStorage.clear();\n return;\n }\n\n const keys = Object.keys(window.sessionStorage);\n for (const k of keys) {\n if (k.startsWith(prefix)) {\n window.sessionStorage.removeItem(k);\n }\n }\n }\n\n async has(key: string): Promise<boolean> {\n if (!this.isAvailable()) return false;\n return (await this.get(key)) !== null;\n }\n}\n\nexport class MemoryStorageAdapter implements StorageAdapter {\n private store: Map<string, unknown> = new Map();\n\n isAvailable(): boolean {\n return true;\n }\n\n async get<T>(key: string): Promise<T | null> {\n const value = this.store.get(key);\n if (value === undefined) return null;\n\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value) as T;\n } catch {\n return value as T;\n }\n }\n\n return value as T;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.store.set(\n key,\n typeof value === \"object\" ? JSON.stringify(value) : value,\n );\n }\n\n async remove(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n }\n\n async has(key: string): Promise<boolean> {\n return this.store.has(key);\n }\n}\n\nexport class NoopStorageAdapter implements StorageAdapter {\n isAvailable(): boolean {\n return false;\n }\n\n async get<T>(_key: string): Promise<T | null> {\n return null;\n }\n\n async set<T>(_key: string, _value: T): Promise<void> {}\n\n async remove(_key: string): Promise<void> {}\n\n async clear(): Promise<void> {}\n\n async has(_key: string): Promise<boolean> {\n return false;\n }\n}\n\nexport function createStorageAdapter(\n type: \"local\" | \"session\" | \"memory\" | \"none\",\n prefix = \"\",\n): StorageAdapter {\n switch (type) {\n case \"local\":\n return new LocalStorageAdapter(prefix);\n case \"session\":\n return new SessionStorageAdapter(prefix);\n case \"memory\":\n return new MemoryStorageAdapter();\n case \"none\":\n default:\n return new NoopStorageAdapter();\n }\n}\n","import { logger } from \"./logger\";\nimport type { StorageAdapter } from \"./storage\";\nimport { LocalStorageAdapter } from \"./storage\";\n\nexport type Namespace = \"eip155\" | \"solana\" | string;\n\nexport interface NamespaceCapabilities {\n atomicBatch?: { supported: boolean; maxBatchSize?: number };\n paymasterService?: { supported: boolean };\n permissions?: boolean;\n serverSigning?: boolean;\n [key: string]: unknown;\n}\n\nexport interface SessionNamespace {\n chains: string[];\n accounts: string[];\n methods: string[];\n events: string[];\n capabilities?: NamespaceCapabilities;\n}\n\nexport interface UniversalWalletSession {\n id: string;\n topic?: string;\n walletId: string;\n walletType: \"walletconnect\" | \"eip6963\" | \"xrpl\" | string;\n namespaces: Record<Namespace, SessionNamespace>;\n platform: \"desktop-web\" | \"mobile-web\" | \"in-app-browser\";\n auth?: {\n method: \"siwe\" | \"siws\" | \"none\";\n issuedAt?: string;\n expiresAt?: string;\n };\n createdAt: string;\n updatedAt: string;\n /** Connector-specific identifier, set during session creation */\n connectorId?: string;\n /** Expiry datetime set by session-key manager */\n expiry?: string | number;\n}\n\nexport interface SessionStorage {\n load(): Promise<UniversalWalletSession | null>;\n save(session: UniversalWalletSession): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport interface CreateEmptySessionInput {\n id: string;\n walletId: string;\n walletType: UniversalWalletSession[\"walletType\"];\n namespaces: Record<Namespace, SessionNamespace>;\n platform: UniversalWalletSession[\"platform\"];\n topic?: string;\n auth?: UniversalWalletSession[\"auth\"];\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport function createEmptySession(\n input: CreateEmptySessionInput,\n): UniversalWalletSession {\n const now = new Date().toISOString();\n\n return {\n id: input.id,\n topic: input.topic,\n walletId: input.walletId,\n walletType: input.walletType,\n namespaces: input.namespaces,\n platform: input.platform,\n auth: input.auth,\n createdAt: input.createdAt ?? now,\n updatedAt: input.updatedAt ?? now,\n };\n}\n\nexport function updateSession(\n session: UniversalWalletSession,\n patch: Partial<UniversalWalletSession>,\n): UniversalWalletSession {\n return {\n ...session,\n ...patch,\n updatedAt: patch.updatedAt ?? new Date().toISOString(),\n };\n}\n\nexport function isSessionExpired(\n session: UniversalWalletSession,\n now: Date,\n): boolean {\n if (!session.auth?.expiresAt) {\n return false;\n }\n\n return new Date(session.auth.expiresAt).getTime() <= now.getTime();\n}\n\n/**\n * Session storage backed by localStorage via the unified StorageAdapter.\n *\n * Resolves the \"dual storage system\" tech debt: instead of directly\n * calling localStorage.getItem/setItem, this delegates to\n * LocalStorageAdapter which provides prefix support, availability\n * detection, quota error handling, and typed parse-error reporting.\n */\nexport class LocalStorageSessionStorage implements SessionStorage {\n private readonly adapter: StorageAdapter;\n private readonly innerKey: string;\n\n /**\n * @param key - localStorage key used to store the session blob.\n * Defaults to \"naculus_web3_session\".\n */\n constructor(key = \"naculus_web3_session\") {\n this.innerKey = \"session\";\n // The supplied key becomes the adapter prefix so multiple\n // storage instances don't collide.\n this.adapter = new LocalStorageAdapter(key + \":\");\n }\n\n /**\n * Return whether localStorage is available in the current environment.\n * Useful for consumers that want to check before calling load/save.\n */\n isAvailable(): boolean {\n return this.adapter.isAvailable();\n }\n\n async load(): Promise<UniversalWalletSession | null> {\n if (!this.adapter.isAvailable()) return null;\n\n try {\n return await this.adapter.get<UniversalWalletSession>(this.innerKey);\n } catch {\n // Parse errors are non-fatal — treat as missing session\n return null;\n }\n }\n\n async save(session: UniversalWalletSession): Promise<void> {\n if (!this.adapter.isAvailable()) return;\n\n try {\n await this.adapter.set(this.innerKey, session);\n } catch (error) {\n logger.warn(\"core/session\", \"Failed to save session:\", error);\n }\n }\n\n async clear(): Promise<void> {\n if (!this.adapter.isAvailable()) return;\n\n await this.adapter.remove(this.innerKey);\n }\n}\n","/**\n * Session Key Error Codes\n */\n\nimport { WalletError } from \"../errors\";\n\nexport type SessionKeyErrorCode =\n | \"session_key_not_found\"\n | \"session_key_expired\"\n | \"session_key_revoked\"\n | \"session_key_scope_exceeded\"\n | \"session_key_method_forbidden\"\n | \"session_key_contract_not_allowed\"\n | \"session_key_chain_not_allowed\"\n | \"session_key_storage_unavailable\"\n | \"session_key_encryption_failed\"\n | \"session_key_required_fields_missing\"\n | \"session_key_max_tx_count_exceeded\"\n | \"session_key_value_limit_exceeded\"\n | \"session_key_gas_limit_exceeded\";\n\nexport const SESSION_KEY_ERROR_MESSAGES: Record<SessionKeyErrorCode, string> = {\n session_key_not_found:\n \"Session key not found. Check the session ID or create a new one.\",\n session_key_expired:\n \"Session key has expired. Please create a new session key.\",\n session_key_revoked:\n \"Session key has been revoked. Please create a new session key.\",\n session_key_scope_exceeded:\n \"Transaction exceeds the session key's permitted scope.\",\n session_key_method_forbidden:\n \"The requested method is forbidden for session keys.\",\n session_key_contract_not_allowed:\n \"The target contract is not in the session key's allowed list.\",\n session_key_chain_not_allowed:\n \"The target chain is not in the session key's allowed list.\",\n session_key_storage_unavailable:\n \"Session key storage is not available in this environment.\",\n session_key_encryption_failed: \"Failed to encrypt/decrypt session key data.\",\n session_key_required_fields_missing:\n \"Required session key fields are missing.\",\n session_key_max_tx_count_exceeded:\n \"Maximum transaction count for this session key has been reached.\",\n session_key_value_limit_exceeded:\n \"Transaction value exceeds the session key's remaining allowance.\",\n session_key_gas_limit_exceeded:\n \"Gas limit exceeds the session key's allowance.\",\n};\n\n/**\n * Create a WalletError with a session-key-specific error code.\n */\nexport function createSessionKeyError(\n code: SessionKeyErrorCode,\n details?: unknown,\n): WalletError {\n return new WalletError(\n code as unknown as any,\n SESSION_KEY_ERROR_MESSAGES[code],\n details,\n );\n}\n","/**\n * HMAC: RFC2104 message authentication code.\n * @module\n */\nimport { abytes, aexists, ahash, clean, Hash, toBytes, type CHash, type Input } from './utils.ts';\n\nexport class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {\n oHash: T;\n iHash: T;\n blockLen: number;\n outputLen: number;\n private finished = false;\n private destroyed = false;\n\n constructor(hash: CHash, _key: Input) {\n super();\n ahash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create() as T;\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create() as T;\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n clean(pad);\n }\n update(buf: Input): this {\n aexists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n abytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest(): Uint8Array {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to?: HMAC<T>): HMAC<T> {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to ||= Object.create(Object.getPrototypeOf(this), {});\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to as this;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n clone(): HMAC<T> {\n return this._cloneInto();\n }\n destroy(): void {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n * @example\n * import { hmac } from '@noble/hashes/hmac';\n * import { sha256 } from '@noble/hashes/sha2';\n * const mac1 = hmac(sha256, 'key', 'message');\n */\nexport const hmac: {\n (hash: CHash, key: Input, message: Input): Uint8Array;\n create(hash: CHash, key: Input): HMAC<any>;\n} = (hash: CHash, key: Input, message: Input): Uint8Array =>\n new HMAC<any>(hash, key).update(message).digest();\nhmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);\n","/**\n * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.\n *\n * ### Design rationale for types\n *\n * * Interaction between classes from different curves should fail:\n * `k256.Point.BASE.add(p256.Point.BASE)`\n * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime\n * * Different calls of `curve()` would return different classes -\n * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,\n * it won't affect others\n *\n * TypeScript can't infer types for classes created inside a function. Classes is one instance\n * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create\n * unique type for every function call.\n *\n * We can use generic types via some param, like curve opts, but that would:\n * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)\n * which is hard to debug.\n * 2. Params can be generic and we can't enforce them to be constant value:\n * if somebody creates curve from non-constant params,\n * it would be allowed to interact with other curves with non-constant params\n *\n * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { hmac as nobleHmac } from '@noble/hashes/hmac.js';\nimport { ahash } from '@noble/hashes/utils';\nimport {\n _validateObject,\n _abool2 as abool,\n _abytes2 as abytes,\n aInRange,\n bitLen,\n bitMask,\n bytesToHex,\n bytesToNumberBE,\n concatBytes,\n createHmacDrbg,\n ensureBytes,\n hexToBytes,\n inRange,\n isBytes,\n memoized,\n numberToHexUnpadded,\n randomBytes as randomBytesWeb,\n type CHash,\n type Hex,\n type PrivKey,\n} from '../utils.ts';\nimport {\n _createCurveFields,\n mulEndoUnsafe,\n negateCt,\n normalizeZ,\n pippenger,\n wNAF,\n type AffinePoint,\n type BasicCurve,\n type CurveLengths,\n type CurvePoint,\n type CurvePointCons,\n} from './curve.ts';\nimport {\n Field,\n FpInvertBatch,\n getMinHashLength,\n mapHashToField,\n nLength,\n validateField,\n type IField,\n type NLength,\n} from './modular.ts';\n\nexport type { AffinePoint };\nexport type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;\n\ntype EndoBasis = [[bigint, bigint], [bigint, bigint]];\n/**\n * When Weierstrass curve has `a=0`, it becomes Koblitz curve.\n * Koblitz curves allow using **efficiently-computable GLV endomorphism ψ**.\n * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.\n * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.\n *\n * Endomorphism consists of beta, lambda and splitScalar:\n *\n * 1. GLV endomorphism ψ transforms a point: `P = (x, y) ↦ ψ(P) = (β·x mod p, y)`\n * 2. GLV scalar decomposition transforms a scalar: `k ≡ k₁ + k₂·λ (mod n)`\n * 3. Then these are combined: `k·P = k₁·P + k₂·ψ(P)`\n * 4. Two 128-bit point-by-scalar multiplications + one point addition is faster than\n * one 256-bit multiplication.\n *\n * where\n * * beta: β ∈ Fₚ with β³ = 1, β ≠ 1\n * * lambda: λ ∈ Fₙ with λ³ = 1, λ ≠ 1\n * * splitScalar decomposes k ↦ k₁, k₂, by using reduced basis vectors.\n * Gauss lattice reduction calculates them from initial basis vectors `(n, 0), (-λ, 0)`\n *\n * Check out `test/misc/endomorphism.js` and\n * [gist](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066).\n */\nexport type EndomorphismOpts = {\n beta: bigint;\n basises?: EndoBasis;\n splitScalar?: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint };\n};\n\n// We construct basis in such way that den is always positive and equals n, but num sign depends on basis (not on secret value)\nconst divNearest = (num: bigint, den: bigint) => (num + (num >= 0 ? den : -den) / _2n) / den;\n\nexport type ScalarEndoParts = { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint };\n\n/**\n * Splits scalar for GLV endomorphism.\n */\nexport function _splitEndoScalar(k: bigint, basis: EndoBasis, n: bigint): ScalarEndoParts {\n // Split scalar into two such that part is ~half bits: `abs(part) < sqrt(N)`\n // Since part can be negative, we need to do this on point.\n // TODO: verifyScalar function which consumes lambda\n const [[a1, b1], [a2, b2]] = basis;\n const c1 = divNearest(b2 * k, n);\n const c2 = divNearest(-b1 * k, n);\n // |k1|/|k2| is < sqrt(N), but can be negative.\n // If we do `k1 mod N`, we'll get big scalar (`> sqrt(N)`): so, we do cheaper negation instead.\n let k1 = k - c1 * a1 - c2 * a2;\n let k2 = -c1 * b1 - c2 * b2;\n const k1neg = k1 < _0n;\n const k2neg = k2 < _0n;\n if (k1neg) k1 = -k1;\n if (k2neg) k2 = -k2;\n // Double check that resulting scalar less than half bits of N: otherwise wNAF will fail.\n // This should only happen on wrong basises. Also, math inside is too complex and I don't trust it.\n const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n; // Half bits of N\n if (k1 < _0n || k1 >= MAX_NUM || k2 < _0n || k2 >= MAX_NUM) {\n throw new Error('splitScalar (endomorphism): failed, k=' + k);\n }\n return { k1neg, k1, k2neg, k2 };\n}\n\nexport type ECDSASigFormat = 'compact' | 'recovered' | 'der';\nexport type ECDSARecoverOpts = {\n prehash?: boolean;\n};\nexport type ECDSAVerifyOpts = {\n prehash?: boolean;\n lowS?: boolean;\n format?: ECDSASigFormat;\n};\nexport type ECDSASignOpts = {\n prehash?: boolean;\n lowS?: boolean;\n format?: ECDSASigFormat;\n extraEntropy?: Uint8Array | boolean;\n};\n\nfunction validateSigFormat(format: string): ECDSASigFormat {\n if (!['compact', 'recovered', 'der'].includes(format))\n throw new Error('Signature format must be \"compact\", \"recovered\", or \"der\"');\n return format as ECDSASigFormat;\n}\n\nfunction validateSigOpts<T extends ECDSASignOpts, D extends Required<ECDSASignOpts>>(\n opts: T,\n def: D\n): Required<ECDSASignOpts> {\n const optsn: ECDSASignOpts = {};\n for (let optName of Object.keys(def)) {\n // @ts-ignore\n optsn[optName] = opts[optName] === undefined ? def[optName] : opts[optName];\n }\n abool(optsn.lowS!, 'lowS');\n abool(optsn.prehash!, 'prehash');\n if (optsn.format !== undefined) validateSigFormat(optsn.format);\n return optsn as Required<ECDSASignOpts>;\n}\n\n/** Instance methods for 3D XYZ projective points. */\nexport interface WeierstrassPoint<T> extends CurvePoint<T, WeierstrassPoint<T>> {\n /** projective X coordinate. Different from affine x. */\n readonly X: T;\n /** projective Y coordinate. Different from affine y. */\n readonly Y: T;\n /** projective z coordinate */\n readonly Z: T;\n /** affine x coordinate. Different from projective X. */\n get x(): T;\n /** affine y coordinate. Different from projective Y. */\n get y(): T;\n /** Encodes point using IEEE P1363 (DER) encoding. First byte is 2/3/4. Default = isCompressed. */\n toBytes(isCompressed?: boolean): Uint8Array;\n toHex(isCompressed?: boolean): string;\n\n /** @deprecated use `.X` */\n readonly px: T;\n /** @deprecated use `.Y` */\n readonly py: T;\n /** @deprecated use `.Z` */\n readonly pz: T;\n /** @deprecated use `toBytes` */\n toRawBytes(isCompressed?: boolean): Uint8Array;\n /** @deprecated use `multiplyUnsafe` */\n multiplyAndAddUnsafe(\n Q: WeierstrassPoint<T>,\n a: bigint,\n b: bigint\n ): WeierstrassPoint<T> | undefined;\n /** @deprecated use `p.y % 2n === 0n` */\n hasEvenY(): boolean;\n /** @deprecated use `p.precompute(windowSize)` */\n _setWindowSize(windowSize: number): void;\n}\n\n/** Static methods for 3D XYZ projective points. */\nexport interface WeierstrassPointCons<T> extends CurvePointCons<WeierstrassPoint<T>> {\n /** Does NOT validate if the point is valid. Use `.assertValidity()`. */\n new (X: T, Y: T, Z: T): WeierstrassPoint<T>;\n CURVE(): WeierstrassOpts<T>;\n /** @deprecated use `Point.BASE.multiply(Point.Fn.fromBytes(privateKey))` */\n fromPrivateKey(privateKey: PrivKey): WeierstrassPoint<T>;\n /** @deprecated use `import { normalizeZ } from '@noble/curves/abstract/curve.js';` */\n normalizeZ(points: WeierstrassPoint<T>[]): WeierstrassPoint<T>[];\n /** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */\n msm(points: WeierstrassPoint<T>[], scalars: bigint[]): WeierstrassPoint<T>;\n}\n\n/**\n * Weierstrass curve options.\n *\n * * p: prime characteristic (order) of finite field, in which arithmetics is done\n * * n: order of prime subgroup a.k.a total amount of valid curve points\n * * h: cofactor, usually 1. h*n is group order; n is subgroup order\n * * a: formula param, must be in field of p\n * * b: formula param, must be in field of p\n * * Gx: x coordinate of generator point a.k.a. base point\n * * Gy: y coordinate of generator point\n */\nexport type WeierstrassOpts<T> = Readonly<{\n p: bigint;\n n: bigint;\n h: bigint;\n a: T;\n b: T;\n Gx: T;\n Gy: T;\n}>;\n\n// When a cofactor != 1, there can be an effective methods to:\n// 1. Determine whether a point is torsion-free\n// 2. Clear torsion component\n// wrapPrivateKey: bls12-381 requires mod(n) instead of rejecting keys >= n\nexport type WeierstrassExtraOpts<T> = Partial<{\n Fp: IField<T>;\n Fn: IField<bigint>;\n allowInfinityPoint: boolean;\n endo: EndomorphismOpts;\n isTorsionFree: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => boolean;\n clearCofactor: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => WeierstrassPoint<T>;\n fromBytes: (bytes: Uint8Array) => AffinePoint<T>;\n toBytes: (\n c: WeierstrassPointCons<T>,\n point: WeierstrassPoint<T>,\n isCompressed: boolean\n ) => Uint8Array;\n}>;\n\n/**\n * Options for ECDSA signatures over a Weierstrass curve.\n *\n * * lowS: (default: true) whether produced / verified signatures occupy low half of ecdsaOpts.p. Prevents malleability.\n * * hmac: (default: noble-hashes hmac) function, would be used to init hmac-drbg for k generation.\n * * randomBytes: (default: webcrypto os-level CSPRNG) custom method for fetching secure randomness.\n * * bits2int, bits2int_modN: used in sigs, sometimes overridden by curves\n */\nexport type ECDSAOpts = Partial<{\n lowS: boolean;\n hmac: HmacFnSync;\n randomBytes: (bytesLength?: number) => Uint8Array;\n bits2int: (bytes: Uint8Array) => bigint;\n bits2int_modN: (bytes: Uint8Array) => bigint;\n}>;\n\n/**\n * Elliptic Curve Diffie-Hellman interface.\n * Provides keygen, secret-to-public conversion, calculating shared secrets.\n */\nexport interface ECDH {\n keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };\n getPublicKey: (secretKey: PrivKey, isCompressed?: boolean) => Uint8Array;\n getSharedSecret: (secretKeyA: PrivKey, publicKeyB: Hex, isCompressed?: boolean) => Uint8Array;\n Point: WeierstrassPointCons<bigint>;\n utils: {\n isValidSecretKey: (secretKey: PrivKey) => boolean;\n isValidPublicKey: (publicKey: Uint8Array, isCompressed?: boolean) => boolean;\n randomSecretKey: (seed?: Uint8Array) => Uint8Array;\n /** @deprecated use `randomSecretKey` */\n randomPrivateKey: (seed?: Uint8Array) => Uint8Array;\n /** @deprecated use `isValidSecretKey` */\n isValidPrivateKey: (secretKey: PrivKey) => boolean;\n /** @deprecated use `Point.Fn.fromBytes()` */\n normPrivateKeyToScalar: (key: PrivKey) => bigint;\n /** @deprecated use `point.precompute()` */\n precompute: (windowSize?: number, point?: WeierstrassPoint<bigint>) => WeierstrassPoint<bigint>;\n };\n lengths: CurveLengths;\n}\n\n/**\n * ECDSA interface.\n * Only supported for prime fields, not Fp2 (extension fields).\n */\nexport interface ECDSA extends ECDH {\n sign: (message: Hex, secretKey: PrivKey, opts?: ECDSASignOpts) => ECDSASigRecovered;\n verify: (\n signature: Uint8Array,\n message: Uint8Array,\n publicKey: Uint8Array,\n opts?: ECDSAVerifyOpts\n ) => boolean;\n recoverPublicKey(signature: Uint8Array, message: Uint8Array, opts?: ECDSARecoverOpts): Uint8Array;\n Signature: ECDSASignatureCons;\n}\nexport class DERErr extends Error {\n constructor(m = '') {\n super(m);\n }\n}\nexport type IDER = {\n // asn.1 DER encoding utils\n Err: typeof DERErr;\n // Basic building block is TLV (Tag-Length-Value)\n _tlv: {\n encode: (tag: number, data: string) => string;\n // v - value, l - left bytes (unparsed)\n decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array };\n };\n // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,\n // since we always use positive integers here. It must always be empty:\n // - add zero byte if exists\n // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)\n _int: {\n encode(num: bigint): string;\n decode(data: Uint8Array): bigint;\n };\n toSig(hex: string | Uint8Array): { r: bigint; s: bigint };\n hexFromSig(sig: { r: bigint; s: bigint }): string;\n};\n/**\n * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:\n *\n * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S]\n *\n * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html\n */\nexport const DER: IDER = {\n // asn.1 DER encoding utils\n Err: DERErr,\n // Basic building block is TLV (Tag-Length-Value)\n _tlv: {\n encode: (tag: number, data: string): string => {\n const { Err: E } = DER;\n if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag');\n if (data.length & 1) throw new E('tlv.encode: unpadded data');\n const dataLen = data.length / 2;\n const len = numberToHexUnpadded(dataLen);\n if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big');\n // length of length with long form flag\n const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '';\n const t = numberToHexUnpadded(tag);\n return t + lenLen + len + data;\n },\n // v - value, l - left bytes (unparsed)\n decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } {\n const { Err: E } = DER;\n let pos = 0;\n if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag');\n if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv');\n const first = data[pos++];\n const isLong = !!(first & 0b1000_0000); // First bit of first length byte is flag for short/long form\n let length = 0;\n if (!isLong) length = first;\n else {\n // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)]\n const lenLen = first & 0b0111_1111;\n if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported');\n if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big'); // this will overflow u32 in js\n const lengthBytes = data.subarray(pos, pos + lenLen);\n if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete');\n if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte');\n for (const b of lengthBytes) length = (length << 8) | b;\n pos += lenLen;\n if (length < 128) throw new E('tlv.decode(long): not minimal encoding');\n }\n const v = data.subarray(pos, pos + length);\n if (v.length !== length) throw new E('tlv.decode: wrong value length');\n return { v, l: data.subarray(pos + length) };\n },\n },\n // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,\n // since we always use positive integers here. It must always be empty:\n // - add zero byte if exists\n // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)\n _int: {\n encode(num: bigint): string {\n const { Err: E } = DER;\n if (num < _0n) throw new E('integer: negative integers are not allowed');\n let hex = numberToHexUnpadded(num);\n // Pad with zero byte if negative flag is present\n if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex;\n if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex');\n return hex;\n },\n decode(data: Uint8Array): bigint {\n const { Err: E } = DER;\n if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative');\n if (data[0] === 0x00 && !(data[1] & 0b1000_0000))\n throw new E('invalid signature integer: unnecessary leading zero');\n return bytesToNumberBE(data);\n },\n },\n toSig(hex: string | Uint8Array): { r: bigint; s: bigint } {\n // parse DER signature\n const { Err: E, _int: int, _tlv: tlv } = DER;\n const data = ensureBytes('signature', hex);\n const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);\n if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing');\n const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);\n const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes);\n if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing');\n return { r: int.decode(rBytes), s: int.decode(sBytes) };\n },\n hexFromSig(sig: { r: bigint; s: bigint }): string {\n const { _tlv: tlv, _int: int } = DER;\n const rs = tlv.encode(0x02, int.encode(sig.r));\n const ss = tlv.encode(0x02, int.encode(sig.s));\n const seq = rs + ss;\n return tlv.encode(0x30, seq);\n },\n};\n\n// Be friendly to bad ECMAScript parsers by not using bigint literals\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);\n\nexport function _normFnElement(Fn: IField<bigint>, key: PrivKey): bigint {\n const { BYTES: expected } = Fn;\n let num: bigint;\n if (typeof key === 'bigint') {\n num = key;\n } else {\n let bytes = ensureBytes('private key', key);\n try {\n num = Fn.fromBytes(bytes);\n } catch (error) {\n throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);\n }\n }\n if (!Fn.isValidNot0(num)) throw new Error('invalid private key: out of range [1..N-1]');\n return num;\n}\n\n/**\n * Creates weierstrass Point constructor, based on specified curve options.\n *\n * @example\n```js\nconst opts = {\n p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),\n n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),\n h: BigInt(1),\n a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),\n b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),\n Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),\n Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),\n};\nconst p256_Point = weierstrass(opts);\n```\n */\nexport function weierstrassN<T>(\n params: WeierstrassOpts<T>,\n extraOpts: WeierstrassExtraOpts<T> = {}\n): WeierstrassPointCons<T> {\n const validated = _createCurveFields('weierstrass', params, extraOpts);\n const { Fp, Fn } = validated;\n let CURVE = validated.CURVE as WeierstrassOpts<T>;\n const { h: cofactor, n: CURVE_ORDER } = CURVE;\n _validateObject(\n extraOpts,\n {},\n {\n allowInfinityPoint: 'boolean',\n clearCofactor: 'function',\n isTorsionFree: 'function',\n fromBytes: 'function',\n toBytes: 'function',\n endo: 'object',\n wrapPrivateKey: 'boolean',\n }\n );\n\n const { endo } = extraOpts;\n if (endo) {\n // validateObject(endo, { beta: 'bigint', splitScalar: 'function' });\n if (!Fp.is0(CURVE.a) || typeof endo.beta !== 'bigint' || !Array.isArray(endo.basises)) {\n throw new Error('invalid endo: expected \"beta\": bigint and \"basises\": array');\n }\n }\n\n const lengths = getWLengths(Fp, Fn);\n\n function assertCompressionIsSupported() {\n if (!Fp.isOdd) throw new Error('compression is not supported: Field does not have .isOdd()');\n }\n\n // Implements IEEE P1363 point encoding\n function pointToBytes(\n _c: WeierstrassPointCons<T>,\n point: WeierstrassPoint<T>,\n isCompressed: boolean\n ): Uint8Array {\n const { x, y } = point.toAffine();\n const bx = Fp.toBytes(x);\n abool(isCompressed, 'isCompressed');\n if (isCompressed) {\n assertCompressionIsSupported();\n const hasEvenY = !Fp.isOdd!(y);\n return concatBytes(pprefix(hasEvenY), bx);\n } else {\n return concatBytes(Uint8Array.of(0x04), bx, Fp.toBytes(y));\n }\n }\n function pointFromBytes(bytes: Uint8Array) {\n abytes(bytes, undefined, 'Point');\n const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65\n const length = bytes.length;\n const head = bytes[0];\n const tail = bytes.subarray(1);\n // No actual validation is done here: use .assertValidity()\n if (length === comp && (head === 0x02 || head === 0x03)) {\n const x = Fp.fromBytes(tail);\n if (!Fp.isValid(x)) throw new Error('bad point: is not on curve, wrong x');\n const y2 = weierstrassEquation(x); // y² = x³ + ax + b\n let y: T;\n try {\n y = Fp.sqrt(y2); // y = y² ^ (p+1)/4\n } catch (sqrtError) {\n const err = sqrtError instanceof Error ? ': ' + sqrtError.message : '';\n throw new Error('bad point: is not on curve, sqrt error' + err);\n }\n assertCompressionIsSupported();\n const isYOdd = Fp.isOdd!(y); // (y & _1n) === _1n;\n const isHeadOdd = (head & 1) === 1; // ECDSA-specific\n if (isHeadOdd !== isYOdd) y = Fp.neg(y);\n return { x, y };\n } else if (length === uncomp && head === 0x04) {\n // TODO: more checks\n const L = Fp.BYTES;\n const x = Fp.fromBytes(tail.subarray(0, L));\n const y = Fp.fromBytes(tail.subarray(L, L * 2));\n if (!isValidXY(x, y)) throw new Error('bad point: is not on curve');\n return { x, y };\n } else {\n throw new Error(\n `bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`\n );\n }\n }\n\n const encodePoint = extraOpts.toBytes || pointToBytes;\n const decodePoint = extraOpts.fromBytes || pointFromBytes;\n function weierstrassEquation(x: T): T {\n const x2 = Fp.sqr(x); // x * x\n const x3 = Fp.mul(x2, x); // x² * x\n return Fp.add(Fp.add(x3, Fp.mul(x, CURVE.a)), CURVE.b); // x³ + a * x + b\n }\n\n // TODO: move top-level\n /** Checks whether equation holds for given x, y: y² == x³ + ax + b */\n function isValidXY(x: T, y: T): boolean {\n const left = Fp.sqr(y); // y²\n const right = weierstrassEquation(x); // x³ + ax + b\n return Fp.eql(left, right);\n }\n\n // Validate whether the passed curve params are valid.\n // Test 1: equation y² = x³ + ax + b should work for generator point.\n if (!isValidXY(CURVE.Gx, CURVE.Gy)) throw new Error('bad curve params: generator point');\n\n // Test 2: discriminant Δ part should be non-zero: 4a³ + 27b² != 0.\n // Guarantees curve is genus-1, smooth (non-singular).\n const _4a3 = Fp.mul(Fp.pow(CURVE.a, _3n), _4n);\n const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27));\n if (Fp.is0(Fp.add(_4a3, _27b2))) throw new Error('bad curve params: a or b');\n\n /** Asserts coordinate is valid: 0 <= n < Fp.ORDER. */\n function acoord(title: string, n: T, banZero = false) {\n if (!Fp.isValid(n) || (banZero && Fp.is0(n))) throw new Error(`bad point coordinate ${title}`);\n return n;\n }\n\n function aprjpoint(other: unknown) {\n if (!(other instanceof Point)) throw new Error('ProjectivePoint expected');\n }\n\n function splitEndoScalarN(k: bigint) {\n if (!endo || !endo.basises) throw new Error('no endo');\n return _splitEndoScalar(k, endo.basises, Fn.ORDER);\n }\n\n // Memoized toAffine / validity check. They are heavy. Points are immutable.\n\n // Converts Projective point to affine (x, y) coordinates.\n // Can accept precomputed Z^-1 - for example, from invertBatch.\n // (X, Y, Z) ∋ (x=X/Z, y=Y/Z)\n const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint<T> => {\n const { X, Y, Z } = p;\n // Fast-path for normalized points\n if (Fp.eql(Z, Fp.ONE)) return { x: X, y: Y };\n const is0 = p.is0();\n // If invZ was 0, we return zero point. However we still want to execute\n // all operations, so we replace invZ with a random number, 1.\n if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(Z);\n const x = Fp.mul(X, iz);\n const y = Fp.mul(Y, iz);\n const zz = Fp.mul(Z, iz);\n if (is0) return { x: Fp.ZERO, y: Fp.ZERO };\n if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid');\n return { x, y };\n });\n // NOTE: on exception this will crash 'cached' and no value will be set.\n // Otherwise true will be return\n const assertValidMemo = memoized((p: Point) => {\n if (p.is0()) {\n // (0, 1, 0) aka ZERO is invalid in most contexts.\n // In BLS, ZERO can be serialized, so we allow it.\n // (0, 0, 0) is invalid representation of ZERO.\n if (extraOpts.allowInfinityPoint && !Fp.is0(p.Y)) return;\n throw new Error('bad point: ZERO');\n }\n // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`\n const { x, y } = p.toAffine();\n if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not field elements');\n if (!isValidXY(x, y)) throw new Error('bad point: equation left != right');\n if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup');\n return true;\n });\n\n function finishEndo(\n endoBeta: EndomorphismOpts['beta'],\n k1p: Point,\n k2p: Point,\n k1neg: boolean,\n k2neg: boolean\n ) {\n k2p = new Point(Fp.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);\n k1p = negateCt(k1neg, k1p);\n k2p = negateCt(k2neg, k2p);\n return k1p.add(k2p);\n }\n\n /**\n * Projective Point works in 3d / projective (homogeneous) coordinates:(X, Y, Z) ∋ (x=X/Z, y=Y/Z).\n * Default Point works in 2d / affine coordinates: (x, y).\n * We're doing calculations in projective, because its operations don't require costly inversion.\n */\n class Point implements WeierstrassPoint<T> {\n // base / generator point\n static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);\n // zero / infinity / identity point\n static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0\n // math field\n static readonly Fp = Fp;\n // scalar field\n static readonly Fn = Fn;\n\n readonly X: T;\n readonly Y: T;\n readonly Z: T;\n\n /** Does NOT validate if the point is valid. Use `.assertValidity()`. */\n constructor(X: T, Y: T, Z: T) {\n this.X = acoord('x', X);\n this.Y = acoord('y', Y, true);\n this.Z = acoord('z', Z);\n Object.freeze(this);\n }\n\n static CURVE(): WeierstrassOpts<T> {\n return CURVE;\n }\n\n /** Does NOT validate if the point is valid. Use `.assertValidity()`. */\n static fromAffine(p: AffinePoint<T>): Point {\n const { x, y } = p || {};\n if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point');\n if (p instanceof Point) throw new Error('projective point not allowed');\n // (0, 0) would've produced (0, 0, 1) - instead, we need (0, 1, 0)\n if (Fp.is0(x) && Fp.is0(y)) return Point.ZERO;\n return new Point(x, y, Fp.ONE);\n }\n\n static fromBytes(bytes: Uint8Array): Point {\n const P = Point.fromAffine(decodePoint(abytes(bytes, undefined, 'point')));\n P.assertValidity();\n return P;\n }\n static fromHex(hex: Hex): Point {\n return Point.fromBytes(ensureBytes('pointHex', hex));\n }\n\n get x(): T {\n return this.toAffine().x;\n }\n get y(): T {\n return this.toAffine().y;\n }\n\n /**\n *\n * @param windowSize\n * @param isLazy true will defer table computation until the first multiplication\n * @returns\n */\n precompute(windowSize: number = 8, isLazy = true): Point {\n wnaf.createCache(this, windowSize);\n if (!isLazy) this.multiply(_3n); // random number\n return this;\n }\n\n // TODO: return `this`\n /** A point on curve is valid if it conforms to equation. */\n assertValidity(): void {\n assertValidMemo(this);\n }\n\n hasEvenY(): boolean {\n const { y } = this.toAffine();\n if (!Fp.isOdd) throw new Error(\"Field doesn't support isOdd\");\n return !Fp.isOdd(y);\n }\n\n /** Compare one point to another. */\n equals(other: Point): boolean {\n aprjpoint(other);\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = other;\n const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));\n const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));\n return U1 && U2;\n }\n\n /** Flips point to one corresponding to (x, -y) in Affine coordinates. */\n negate(): Point {\n return new Point(this.X, Fp.neg(this.Y), this.Z);\n }\n\n // Renes-Costello-Batina exception-free doubling formula.\n // There is 30% faster Jacobian formula, but it is not complete.\n // https://eprint.iacr.org/2015/1060, algorithm 3\n // Cost: 8M + 3S + 3*a + 2*b3 + 15add.\n double() {\n const { a, b } = CURVE;\n const b3 = Fp.mul(b, _3n);\n const { X: X1, Y: Y1, Z: Z1 } = this;\n let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n let t0 = Fp.mul(X1, X1); // step 1\n let t1 = Fp.mul(Y1, Y1);\n let t2 = Fp.mul(Z1, Z1);\n let t3 = Fp.mul(X1, Y1);\n t3 = Fp.add(t3, t3); // step 5\n Z3 = Fp.mul(X1, Z1);\n Z3 = Fp.add(Z3, Z3);\n X3 = Fp.mul(a, Z3);\n Y3 = Fp.mul(b3, t2);\n Y3 = Fp.add(X3, Y3); // step 10\n X3 = Fp.sub(t1, Y3);\n Y3 = Fp.add(t1, Y3);\n Y3 = Fp.mul(X3, Y3);\n X3 = Fp.mul(t3, X3);\n Z3 = Fp.mul(b3, Z3); // step 15\n t2 = Fp.mul(a, t2);\n t3 = Fp.sub(t0, t2);\n t3 = Fp.mul(a, t3);\n t3 = Fp.add(t3, Z3);\n Z3 = Fp.add(t0, t0); // step 20\n t0 = Fp.add(Z3, t0);\n t0 = Fp.add(t0, t2);\n t0 = Fp.mul(t0, t3);\n Y3 = Fp.add(Y3, t0);\n t2 = Fp.mul(Y1, Z1); // step 25\n t2 = Fp.add(t2, t2);\n t0 = Fp.mul(t2, t3);\n X3 = Fp.sub(X3, t0);\n Z3 = Fp.mul(t2, t1);\n Z3 = Fp.add(Z3, Z3); // step 30\n Z3 = Fp.add(Z3, Z3);\n return new Point(X3, Y3, Z3);\n }\n\n // Renes-Costello-Batina exception-free addition formula.\n // There is 30% faster Jacobian formula, but it is not complete.\n // https://eprint.iacr.org/2015/1060, algorithm 1\n // Cost: 12M + 0S + 3*a + 3*b3 + 23add.\n add(other: Point): Point {\n aprjpoint(other);\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = other;\n let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n const a = CURVE.a;\n const b3 = Fp.mul(CURVE.b, _3n);\n let t0 = Fp.mul(X1, X2); // step 1\n let t1 = Fp.mul(Y1, Y2);\n let t2 = Fp.mul(Z1, Z2);\n let t3 = Fp.add(X1, Y1);\n let t4 = Fp.add(X2, Y2); // step 5\n t3 = Fp.mul(t3, t4);\n t4 = Fp.add(t0, t1);\n t3 = Fp.sub(t3, t4);\n t4 = Fp.add(X1, Z1);\n let t5 = Fp.add(X2, Z2); // step 10\n t4 = Fp.mul(t4, t5);\n t5 = Fp.add(t0, t2);\n t4 = Fp.sub(t4, t5);\n t5 = Fp.add(Y1, Z1);\n X3 = Fp.add(Y2, Z2); // step 15\n t5 = Fp.mul(t5, X3);\n X3 = Fp.add(t1, t2);\n t5 = Fp.sub(t5, X3);\n Z3 = Fp.mul(a, t4);\n X3 = Fp.mul(b3, t2); // step 20\n Z3 = Fp.add(X3, Z3);\n X3 = Fp.sub(t1, Z3);\n Z3 = Fp.add(t1, Z3);\n Y3 = Fp.mul(X3, Z3);\n t1 = Fp.add(t0, t0); // step 25\n t1 = Fp.add(t1, t0);\n t2 = Fp.mul(a, t2);\n t4 = Fp.mul(b3, t4);\n t1 = Fp.add(t1, t2);\n t2 = Fp.sub(t0, t2); // step 30\n t2 = Fp.mul(a, t2);\n t4 = Fp.add(t4, t2);\n t0 = Fp.mul(t1, t4);\n Y3 = Fp.add(Y3, t0);\n t0 = Fp.mul(t5, t4); // step 35\n X3 = Fp.mul(t3, X3);\n X3 = Fp.sub(X3, t0);\n t0 = Fp.mul(t3, t1);\n Z3 = Fp.mul(t5, Z3);\n Z3 = Fp.add(Z3, t0); // step 40\n return new Point(X3, Y3, Z3);\n }\n\n subtract(other: Point) {\n return this.add(other.negate());\n }\n\n is0(): boolean {\n return this.equals(Point.ZERO);\n }\n\n /**\n * Constant time multiplication.\n * Uses wNAF method. Windowed method may be 10% faster,\n * but takes 2x longer to generate and consumes 2x memory.\n * Uses precomputes when available.\n * Uses endomorphism for Koblitz curves.\n * @param scalar by which the point would be multiplied\n * @returns New point\n */\n multiply(scalar: bigint): Point {\n const { endo } = extraOpts;\n if (!Fn.isValidNot0(scalar)) throw new Error('invalid scalar: out of range'); // 0 is invalid\n let point: Point, fake: Point; // Fake point is used to const-time mult\n const mul = (n: bigint) => wnaf.cached(this, n, (p) => normalizeZ(Point, p));\n /** See docs for {@link EndomorphismOpts} */\n if (endo) {\n const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);\n const { p: k1p, f: k1f } = mul(k1);\n const { p: k2p, f: k2f } = mul(k2);\n fake = k1f.add(k2f);\n point = finishEndo(endo.beta, k1p, k2p, k1neg, k2neg);\n } else {\n const { p, f } = mul(scalar);\n point = p;\n fake = f;\n }\n // Normalize `z` for both points, but return only real one\n return normalizeZ(Point, [point, fake])[0];\n }\n\n /**\n * Non-constant-time multiplication. Uses double-and-add algorithm.\n * It's faster, but should only be used when you don't care about\n * an exposed secret key e.g. sig verification, which works over *public* keys.\n */\n multiplyUnsafe(sc: bigint): Point {\n const { endo } = extraOpts;\n const p = this as Point;\n if (!Fn.isValid(sc)) throw new Error('invalid scalar: out of range'); // 0 is valid\n if (sc === _0n || p.is0()) return Point.ZERO;\n if (sc === _1n) return p; // fast-path\n if (wnaf.hasCache(this)) return this.multiply(sc);\n if (endo) {\n const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);\n const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2); // 30% faster vs wnaf.unsafe\n return finishEndo(endo.beta, p1, p2, k1neg, k2neg);\n } else {\n return wnaf.unsafe(p, sc);\n }\n }\n\n multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined {\n const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));\n return sum.is0() ? undefined : sum;\n }\n\n /**\n * Converts Projective point to affine (x, y) coordinates.\n * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch\n */\n toAffine(invertedZ?: T): AffinePoint<T> {\n return toAffineMemo(this, invertedZ);\n }\n\n /**\n * Checks whether Point is free of torsion elements (is in prime subgroup).\n * Always torsion-free for cofactor=1 curves.\n */\n isTorsionFree(): boolean {\n const { isTorsionFree } = extraOpts;\n if (cofactor === _1n) return true;\n if (isTorsionFree) return isTorsionFree(Point, this);\n return wnaf.unsafe(this, CURVE_ORDER).is0();\n }\n\n clearCofactor(): Point {\n const { clearCofactor } = extraOpts;\n if (cofactor === _1n) return this; // Fast-path\n if (clearCofactor) return clearCofactor(Point, this) as Point;\n return this.multiplyUnsafe(cofactor);\n }\n\n isSmallOrder(): boolean {\n // can we use this.clearCofactor()?\n return this.multiplyUnsafe(cofactor).is0();\n }\n\n toBytes(isCompressed = true): Uint8Array {\n abool(isCompressed, 'isCompressed');\n this.assertValidity();\n return encodePoint(Point, this, isCompressed);\n }\n\n toHex(isCompressed = true): string {\n return bytesToHex(this.toBytes(isCompressed));\n }\n\n toString() {\n return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;\n }\n\n // TODO: remove\n get px(): T {\n return this.X;\n }\n get py(): T {\n return this.X;\n }\n get pz(): T {\n return this.Z;\n }\n toRawBytes(isCompressed = true): Uint8Array {\n return this.toBytes(isCompressed);\n }\n _setWindowSize(windowSize: number) {\n this.precompute(windowSize);\n }\n static normalizeZ(points: Point[]): Point[] {\n return normalizeZ(Point, points);\n }\n static msm(points: Point[], scalars: bigint[]): Point {\n return pippenger(Point, Fn, points, scalars);\n }\n static fromPrivateKey(privateKey: PrivKey) {\n return Point.BASE.multiply(_normFnElement(Fn, privateKey));\n }\n }\n const bits = Fn.BITS;\n const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);\n Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.\n return Point;\n}\n\n/** Methods of ECDSA signature instance. */\nexport interface ECDSASignature {\n readonly r: bigint;\n readonly s: bigint;\n readonly recovery?: number;\n addRecoveryBit(recovery: number): ECDSASigRecovered;\n hasHighS(): boolean;\n toBytes(format?: string): Uint8Array;\n toHex(format?: string): string;\n\n /** @deprecated */\n assertValidity(): void;\n /** @deprecated */\n normalizeS(): ECDSASignature;\n /** @deprecated use standalone method `curve.recoverPublicKey(sig.toBytes('recovered'), msg)` */\n recoverPublicKey(msgHash: Hex): WeierstrassPoint<bigint>;\n /** @deprecated use `.toBytes('compact')` */\n toCompactRawBytes(): Uint8Array;\n /** @deprecated use `.toBytes('compact')` */\n toCompactHex(): string;\n /** @deprecated use `.toBytes('der')` */\n toDERRawBytes(): Uint8Array;\n /** @deprecated use `.toBytes('der')` */\n toDERHex(): string;\n}\nexport type ECDSASigRecovered = ECDSASignature & {\n readonly recovery: number;\n};\n/** Methods of ECDSA signature constructor. */\nexport type ECDSASignatureCons = {\n new (r: bigint, s: bigint, recovery?: number): ECDSASignature;\n fromBytes(bytes: Uint8Array, format?: ECDSASigFormat): ECDSASignature;\n fromHex(hex: string, format?: ECDSASigFormat): ECDSASignature;\n\n /** @deprecated use `.fromBytes(bytes, 'compact')` */\n fromCompact(hex: Hex): ECDSASignature;\n /** @deprecated use `.fromBytes(bytes, 'der')` */\n fromDER(hex: Hex): ECDSASignature;\n};\n\n// Points start with byte 0x02 when y is even; otherwise 0x03\nfunction pprefix(hasEvenY: boolean): Uint8Array {\n return Uint8Array.of(hasEvenY ? 0x02 : 0x03);\n}\n\n/**\n * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.\n * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.\n * b = True and y = sqrt(u / v) if (u / v) is square in F, and\n * b = False and y = sqrt(Z * (u / v)) otherwise.\n * @param Fp\n * @param Z\n * @returns\n */\nexport function SWUFpSqrtRatio<T>(\n Fp: IField<T>,\n Z: T\n): (u: T, v: T) => { isValid: boolean; value: T } {\n // Generic implementation\n const q = Fp.ORDER;\n let l = _0n;\n for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n;\n const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.\n // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.\n // 2n ** c1 == 2n << (c1-1)\n const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);\n const _2n_pow_c1 = _2n_pow_c1_1 * _2n;\n const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic\n const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic\n const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic\n const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic\n const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2\n const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)\n let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => {\n let tv1 = c6; // 1. tv1 = c6\n let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4\n let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2\n tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v\n let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3\n tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3\n tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2\n tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v\n tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u\n let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2\n tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5\n let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1\n tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7\n tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1\n tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)\n tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)\n // 17. for i in (c1, c1 - 1, ..., 2):\n for (let i = c1; i > _1n; i--) {\n let tv5 = i - _2n; // 18. tv5 = i - 2\n tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5\n let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5\n const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1\n tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1\n tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1\n tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1\n tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)\n tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)\n }\n return { isValid: isQR, value: tv3 };\n };\n if (Fp.ORDER % _4n === _3n) {\n // sqrt_ratio_3mod4(u, v)\n const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic\n const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)\n sqrtRatio = (u: T, v: T) => {\n let tv1 = Fp.sqr(v); // 1. tv1 = v^2\n const tv2 = Fp.mul(u, v); // 2. tv2 = u * v\n tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2\n let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1\n y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2\n const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2\n const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v\n const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u\n let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)\n return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2\n };\n }\n // No curves uses that\n // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8\n return sqrtRatio;\n}\n/**\n * Simplified Shallue-van de Woestijne-Ulas Method\n * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2\n */\nexport function mapToCurveSimpleSWU<T>(\n Fp: IField<T>,\n opts: {\n A: T;\n B: T;\n Z: T;\n }\n): (u: T) => { x: T; y: T } {\n validateField(Fp);\n const { A, B, Z } = opts;\n if (!Fp.isValid(A) || !Fp.isValid(B) || !Fp.isValid(Z))\n throw new Error('mapToCurveSimpleSWU: invalid opts');\n const sqrtRatio = SWUFpSqrtRatio(Fp, Z);\n if (!Fp.isOdd) throw new Error('Field does not have .isOdd()');\n // Input: u, an element of F.\n // Output: (x, y), a point on E.\n return (u: T): { x: T; y: T } => {\n // prettier-ignore\n let tv1, tv2, tv3, tv4, tv5, tv6, x, y;\n tv1 = Fp.sqr(u); // 1. tv1 = u^2\n tv1 = Fp.mul(tv1, Z); // 2. tv1 = Z * tv1\n tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2\n tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1\n tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1\n tv3 = Fp.mul(tv3, B); // 6. tv3 = B * tv3\n tv4 = Fp.cmov(Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)\n tv4 = Fp.mul(tv4, A); // 8. tv4 = A * tv4\n tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2\n tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2\n tv5 = Fp.mul(tv6, A); // 11. tv5 = A * tv6\n tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5\n tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3\n tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4\n tv5 = Fp.mul(tv6, B); // 15. tv5 = B * tv6\n tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5\n x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3\n const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)\n y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1\n y = Fp.mul(y, value); // 20. y = y * y1\n x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)\n y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)\n const e1 = Fp.isOdd!(u) === Fp.isOdd!(y); // 23. e1 = sgn0(u) == sgn0(y)\n y = Fp.cmov(Fp.neg(y), y, e1); // 24. y = CMOV(-y, y, e1)\n const tv4_inv = FpInvertBatch(Fp, [tv4], true)[0];\n x = Fp.mul(x, tv4_inv); // 25. x = x / tv4\n return { x, y };\n };\n}\n\nfunction getWLengths<T>(Fp: IField<T>, Fn: IField<bigint>) {\n return {\n secretKey: Fn.BYTES,\n publicKey: 1 + Fp.BYTES,\n publicKeyUncompressed: 1 + 2 * Fp.BYTES,\n publicKeyHasPrefix: true,\n signature: 2 * Fn.BYTES,\n };\n}\n\n/**\n * Sometimes users only need getPublicKey, getSharedSecret, and secret key handling.\n * This helper ensures no signature functionality is present. Less code, smaller bundle size.\n */\nexport function ecdh(\n Point: WeierstrassPointCons<bigint>,\n ecdhOpts: { randomBytes?: (bytesLength?: number) => Uint8Array } = {}\n): ECDH {\n const { Fn } = Point;\n const randomBytes_ = ecdhOpts.randomBytes || randomBytesWeb;\n const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) });\n\n function isValidSecretKey(secretKey: PrivKey) {\n try {\n return !!_normFnElement(Fn, secretKey);\n } catch (error) {\n return false;\n }\n }\n\n function isValidPublicKey(publicKey: Uint8Array, isCompressed?: boolean): boolean {\n const { publicKey: comp, publicKeyUncompressed } = lengths;\n try {\n const l = publicKey.length;\n if (isCompressed === true && l !== comp) return false;\n if (isCompressed === false && l !== publicKeyUncompressed) return false;\n return !!Point.fromBytes(publicKey);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Produces cryptographically secure secret key from random of size\n * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.\n */\n function randomSecretKey(seed = randomBytes_(lengths.seed)): Uint8Array {\n return mapHashToField(abytes(seed, lengths.seed, 'seed'), Fn.ORDER);\n }\n\n /**\n * Computes public key for a secret key. Checks for validity of the secret key.\n * @param isCompressed whether to return compact (default), or full key\n * @returns Public key, full when isCompressed=false; short when isCompressed=true\n */\n function getPublicKey(secretKey: PrivKey, isCompressed = true): Uint8Array {\n return Point.BASE.multiply(_normFnElement(Fn, secretKey)).toBytes(isCompressed);\n }\n\n function keygen(seed?: Uint8Array) {\n const secretKey = randomSecretKey(seed);\n return { secretKey, publicKey: getPublicKey(secretKey) };\n }\n\n /**\n * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.\n */\n function isProbPub(item: PrivKey | PubKey): boolean | undefined {\n if (typeof item === 'bigint') return false;\n if (item instanceof Point) return true;\n const { secretKey, publicKey, publicKeyUncompressed } = lengths;\n if (Fn.allowedLengths || secretKey === publicKey) return undefined;\n const l = ensureBytes('key', item).length;\n return l === publicKey || l === publicKeyUncompressed;\n }\n\n /**\n * ECDH (Elliptic Curve Diffie Hellman).\n * Computes shared public key from secret key A and public key B.\n * Checks: 1) secret key validity 2) shared key is on-curve.\n * Does NOT hash the result.\n * @param isCompressed whether to return compact (default), or full key\n * @returns shared public key\n */\n function getSharedSecret(secretKeyA: PrivKey, publicKeyB: Hex, isCompressed = true): Uint8Array {\n if (isProbPub(secretKeyA) === true) throw new Error('first arg must be private key');\n if (isProbPub(publicKeyB) === false) throw new Error('second arg must be public key');\n const s = _normFnElement(Fn, secretKeyA);\n const b = Point.fromHex(publicKeyB); // checks for being on-curve\n return b.multiply(s).toBytes(isCompressed);\n }\n\n const utils = {\n isValidSecretKey,\n isValidPublicKey,\n randomSecretKey,\n\n // TODO: remove\n isValidPrivateKey: isValidSecretKey,\n randomPrivateKey: randomSecretKey,\n normPrivateKeyToScalar: (key: PrivKey) => _normFnElement(Fn, key),\n precompute(windowSize = 8, point = Point.BASE): WeierstrassPoint<bigint> {\n return point.precompute(windowSize, false);\n },\n };\n\n return Object.freeze({ getPublicKey, getSharedSecret, keygen, Point, utils, lengths });\n}\n\n/**\n * Creates ECDSA signing interface for given elliptic curve `Point` and `hash` function.\n * We need `hash` for 2 features:\n * 1. Message prehash-ing. NOT used if `sign` / `verify` are called with `prehash: false`\n * 2. k generation in `sign`, using HMAC-drbg(hash)\n *\n * ECDSAOpts are only rarely needed.\n *\n * @example\n * ```js\n * const p256_Point = weierstrass(...);\n * const p256_sha256 = ecdsa(p256_Point, sha256);\n * const p256_sha224 = ecdsa(p256_Point, sha224);\n * const p256_sha224_r = ecdsa(p256_Point, sha224, { randomBytes: (length) => { ... } });\n * ```\n */\nexport function ecdsa(\n Point: WeierstrassPointCons<bigint>,\n hash: CHash,\n ecdsaOpts: ECDSAOpts = {}\n): ECDSA {\n ahash(hash);\n _validateObject(\n ecdsaOpts,\n {},\n {\n hmac: 'function',\n lowS: 'boolean',\n randomBytes: 'function',\n bits2int: 'function',\n bits2int_modN: 'function',\n }\n );\n\n const randomBytes = ecdsaOpts.randomBytes || randomBytesWeb;\n const hmac: HmacFnSync =\n ecdsaOpts.hmac ||\n (((key, ...msgs) => nobleHmac(hash, key, concatBytes(...msgs))) satisfies HmacFnSync);\n\n const { Fp, Fn } = Point;\n const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;\n const { keygen, getPublicKey, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);\n const defaultSigOpts: Required<ECDSASignOpts> = {\n prehash: false,\n lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : false,\n format: undefined as any, //'compact' as ECDSASigFormat,\n extraEntropy: false,\n };\n const defaultSigOpts_format = 'compact';\n\n function isBiggerThanHalfOrder(number: bigint) {\n const HALF = CURVE_ORDER >> _1n;\n return number > HALF;\n }\n function validateRS(title: string, num: bigint): bigint {\n if (!Fn.isValidNot0(num))\n throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);\n return num;\n }\n function validateSigLength(bytes: Uint8Array, format: ECDSASigFormat) {\n validateSigFormat(format);\n const size = lengths.signature!;\n const sizer = format === 'compact' ? size : format === 'recovered' ? size + 1 : undefined;\n return abytes(bytes, sizer, `${format} signature`);\n }\n\n /**\n * ECDSA signature with its (r, s) properties. Supports compact, recovered & DER representations.\n */\n class Signature implements ECDSASignature {\n readonly r: bigint;\n readonly s: bigint;\n readonly recovery?: number;\n constructor(r: bigint, s: bigint, recovery?: number) {\n this.r = validateRS('r', r); // r in [1..N-1];\n this.s = validateRS('s', s); // s in [1..N-1];\n if (recovery != null) this.recovery = recovery;\n Object.freeze(this);\n }\n\n static fromBytes(bytes: Uint8Array, format: ECDSASigFormat = defaultSigOpts_format): Signature {\n validateSigLength(bytes, format);\n let recid: number | undefined;\n if (format === 'der') {\n const { r, s } = DER.toSig(abytes(bytes));\n return new Signature(r, s);\n }\n if (format === 'recovered') {\n recid = bytes[0];\n format = 'compact';\n bytes = bytes.subarray(1);\n }\n const L = Fn.BYTES;\n const r = bytes.subarray(0, L);\n const s = bytes.subarray(L, L * 2);\n return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid);\n }\n\n static fromHex(hex: string, format?: ECDSASigFormat) {\n return this.fromBytes(hexToBytes(hex), format);\n }\n\n addRecoveryBit(recovery: number): RecoveredSignature {\n return new Signature(this.r, this.s, recovery) as RecoveredSignature;\n }\n\n recoverPublicKey(messageHash: Hex): WeierstrassPoint<bigint> {\n const FIELD_ORDER = Fp.ORDER;\n const { r, s, recovery: rec } = this;\n if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');\n\n // ECDSA recovery is hard for cofactor > 1 curves.\n // In sign, `r = q.x mod n`, and here we recover q.x from r.\n // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.\n // However, for cofactor>1, r+n may not get q.x:\n // r+n*i would need to be done instead where i is unknown.\n // To easily get i, we either need to:\n // a. increase amount of valid recid values (4, 5...); OR\n // b. prohibit non-prime-order signatures (recid > 1).\n const hasCofactor = CURVE_ORDER * _2n < FIELD_ORDER;\n if (hasCofactor && rec > 1) throw new Error('recovery id is ambiguous for h>1 curve');\n\n const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;\n if (!Fp.isValid(radj)) throw new Error('recovery id 2 or 3 invalid');\n const x = Fp.toBytes(radj);\n const R = Point.fromBytes(concatBytes(pprefix((rec & 1) === 0), x));\n const ir = Fn.inv(radj); // r^-1\n const h = bits2int_modN(ensureBytes('msgHash', messageHash)); // Truncate hash\n const u1 = Fn.create(-h * ir); // -hr^-1\n const u2 = Fn.create(s * ir); // sr^-1\n // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.\n const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));\n if (Q.is0()) throw new Error('point at infinify');\n Q.assertValidity();\n return Q;\n }\n\n // Signatures should be low-s, to prevent malleability.\n hasHighS(): boolean {\n return isBiggerThanHalfOrder(this.s);\n }\n\n toBytes(format: ECDSASigFormat = defaultSigOpts_format) {\n validateSigFormat(format);\n if (format === 'der') return hexToBytes(DER.hexFromSig(this));\n const r = Fn.toBytes(this.r);\n const s = Fn.toBytes(this.s);\n if (format === 'recovered') {\n if (this.recovery == null) throw new Error('recovery bit must be present');\n return concatBytes(Uint8Array.of(this.recovery), r, s);\n }\n return concatBytes(r, s);\n }\n\n toHex(format?: ECDSASigFormat) {\n return bytesToHex(this.toBytes(format));\n }\n\n // TODO: remove\n assertValidity(): void {}\n static fromCompact(hex: Hex) {\n return Signature.fromBytes(ensureBytes('sig', hex), 'compact');\n }\n static fromDER(hex: Hex) {\n return Signature.fromBytes(ensureBytes('sig', hex), 'der');\n }\n normalizeS() {\n return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;\n }\n toDERRawBytes() {\n return this.toBytes('der');\n }\n toDERHex() {\n return bytesToHex(this.toBytes('der'));\n }\n toCompactRawBytes() {\n return this.toBytes('compact');\n }\n toCompactHex() {\n return bytesToHex(this.toBytes('compact'));\n }\n }\n type RecoveredSignature = Signature & { recovery: number };\n\n // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.\n // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.\n // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.\n // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors\n const bits2int =\n ecdsaOpts.bits2int ||\n function bits2int_def(bytes: Uint8Array): bigint {\n // Our custom check \"just in case\", for protection against DoS\n if (bytes.length > 8192) throw new Error('input is too large');\n // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)\n // for some cases, since bytes.length * 8 is not actual bitLength.\n const num = bytesToNumberBE(bytes); // check for == u8 done here\n const delta = bytes.length * 8 - fnBits; // truncate to nBitLength leftmost bits\n return delta > 0 ? num >> BigInt(delta) : num;\n };\n const bits2int_modN =\n ecdsaOpts.bits2int_modN ||\n function bits2int_modN_def(bytes: Uint8Array): bigint {\n return Fn.create(bits2int(bytes)); // can't use bytesToNumberBE here\n };\n // Pads output with zero as per spec\n const ORDER_MASK = bitMask(fnBits);\n /** Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. */\n function int2octets(num: bigint): Uint8Array {\n // IMPORTANT: the check ensures working for case `Fn.BYTES != Fn.BITS * 8`\n aInRange('num < 2^' + fnBits, num, _0n, ORDER_MASK);\n return Fn.toBytes(num);\n }\n\n function validateMsgAndHash(message: Uint8Array, prehash: boolean) {\n abytes(message, undefined, 'message');\n return prehash ? abytes(hash(message), undefined, 'prehashed message') : message;\n }\n\n /**\n * Steps A, D of RFC6979 3.2.\n * Creates RFC6979 seed; converts msg/privKey to numbers.\n * Used only in sign, not in verify.\n *\n * Warning: we cannot assume here that message has same amount of bytes as curve order,\n * this will be invalid at least for P521. Also it can be bigger for P224 + SHA256.\n */\n function prepSig(message: Uint8Array, privateKey: PrivKey, opts: ECDSASignOpts) {\n if (['recovered', 'canonical'].some((k) => k in opts))\n throw new Error('sign() legacy options not supported');\n const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts);\n message = validateMsgAndHash(message, prehash); // RFC6979 3.2 A: h1 = H(m)\n // We can't later call bits2octets, since nested bits2int is broken for curves\n // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.\n // const bits2octets = (bits) => int2octets(bits2int_modN(bits))\n const h1int = bits2int_modN(message);\n const d = _normFnElement(Fn, privateKey); // validate secret key, convert to bigint\n const seedArgs = [int2octets(d), int2octets(h1int)];\n // extraEntropy. RFC6979 3.6: additional k' (optional).\n if (extraEntropy != null && extraEntropy !== false) {\n // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')\n // gen random bytes OR pass as-is\n const e = extraEntropy === true ? randomBytes(lengths.secretKey) : extraEntropy;\n seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes\n }\n const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2\n const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!\n // Converts signature params into point w r/s, checks result for validity.\n // To transform k => Signature:\n // q = k⋅G\n // r = q.x mod n\n // s = k^-1(m + rd) mod n\n // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to\n // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:\n // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT\n function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined {\n // RFC 6979 Section 3.2, step 3: k = bits2int(T)\n // Important: all mod() calls here must be done over N\n const k = bits2int(kBytes); // mod n, not mod p\n if (!Fn.isValidNot0(k)) return; // Valid scalars (including k) must be in 1..N-1\n const ik = Fn.inv(k); // k^-1 mod n\n const q = Point.BASE.multiply(k).toAffine(); // q = k⋅G\n const r = Fn.create(q.x); // r = q.x mod n\n if (r === _0n) return;\n const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above\n if (s === _0n) return;\n let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)\n let normS = s;\n if (lowS && isBiggerThanHalfOrder(s)) {\n normS = Fn.neg(s); // if lowS was passed, ensure s is always\n recovery ^= 1; // // in the bottom half of N\n }\n return new Signature(r, normS, recovery) as RecoveredSignature; // use normS, not s\n }\n return { seed, k2sig };\n }\n\n /**\n * Signs message hash with a secret key.\n *\n * ```\n * sign(m, d) where\n * k = rfc6979_hmac_drbg(m, d)\n * (x, y) = G × k\n * r = x mod n\n * s = (m + dr) / k mod n\n * ```\n */\n function sign(message: Hex, secretKey: PrivKey, opts: ECDSASignOpts = {}): RecoveredSignature {\n message = ensureBytes('message', message);\n const { seed, k2sig } = prepSig(message, secretKey, opts); // Steps A, D of RFC6979 3.2.\n const drbg = createHmacDrbg<RecoveredSignature>(hash.outputLen, Fn.BYTES, hmac);\n const sig = drbg(seed, k2sig); // Steps B, C, D, E, F, G\n return sig;\n }\n\n function tryParsingSig(sg: Hex | SignatureLike) {\n // Try to deduce format\n let sig: Signature | undefined = undefined;\n const isHex = typeof sg === 'string' || isBytes(sg);\n const isObj =\n !isHex &&\n sg !== null &&\n typeof sg === 'object' &&\n typeof sg.r === 'bigint' &&\n typeof sg.s === 'bigint';\n if (!isHex && !isObj)\n throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');\n if (isObj) {\n sig = new Signature(sg.r, sg.s);\n } else if (isHex) {\n try {\n sig = Signature.fromBytes(ensureBytes('sig', sg), 'der');\n } catch (derError) {\n if (!(derError instanceof DER.Err)) throw derError;\n }\n if (!sig) {\n try {\n sig = Signature.fromBytes(ensureBytes('sig', sg), 'compact');\n } catch (error) {\n return false;\n }\n }\n }\n if (!sig) return false;\n return sig;\n }\n\n /**\n * Verifies a signature against message and public key.\n * Rejects lowS signatures by default: see {@link ECDSAVerifyOpts}.\n * Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:\n *\n * ```\n * verify(r, s, h, P) where\n * u1 = hs^-1 mod n\n * u2 = rs^-1 mod n\n * R = u1⋅G + u2⋅P\n * mod(R.x, n) == r\n * ```\n */\n function verify(\n signature: Hex | SignatureLike,\n message: Hex,\n publicKey: Hex,\n opts: ECDSAVerifyOpts = {}\n ): boolean {\n const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);\n publicKey = ensureBytes('publicKey', publicKey);\n message = validateMsgAndHash(ensureBytes('message', message), prehash);\n if ('strict' in opts) throw new Error('options.strict was renamed to lowS');\n const sig =\n format === undefined\n ? tryParsingSig(signature)\n : Signature.fromBytes(ensureBytes('sig', signature as Hex), format);\n if (sig === false) return false;\n try {\n const P = Point.fromBytes(publicKey);\n if (lowS && sig.hasHighS()) return false;\n const { r, s } = sig;\n const h = bits2int_modN(message); // mod n, not mod p\n const is = Fn.inv(s); // s^-1 mod n\n const u1 = Fn.create(h * is); // u1 = hs^-1 mod n\n const u2 = Fn.create(r * is); // u2 = rs^-1 mod n\n const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2)); // u1⋅G + u2⋅P\n if (R.is0()) return false;\n const v = Fn.create(R.x); // v = r.x mod n\n return v === r;\n } catch (e) {\n return false;\n }\n }\n\n function recoverPublicKey(\n signature: Uint8Array,\n message: Uint8Array,\n opts: ECDSARecoverOpts = {}\n ): Uint8Array {\n const { prehash } = validateSigOpts(opts, defaultSigOpts);\n message = validateMsgAndHash(message, prehash);\n return Signature.fromBytes(signature, 'recovered').recoverPublicKey(message).toBytes();\n }\n\n return Object.freeze({\n keygen,\n getPublicKey,\n getSharedSecret,\n utils,\n lengths,\n Point,\n sign,\n verify,\n recoverPublicKey,\n Signature,\n hash,\n });\n}\n\n// TODO: remove everything below\n/** @deprecated use ECDSASignature */\nexport type SignatureType = ECDSASignature;\n/** @deprecated use ECDSASigRecovered */\nexport type RecoveredSignatureType = ECDSASigRecovered;\n/** @deprecated switch to Uint8Array signatures in format 'compact' */\nexport type SignatureLike = { r: bigint; s: bigint };\nexport type ECDSAExtraEntropy = Hex | boolean;\n/** @deprecated use `ECDSAExtraEntropy` */\nexport type Entropy = Hex | boolean;\nexport type BasicWCurve<T> = BasicCurve<T> & {\n // Params: a, b\n a: T;\n b: T;\n\n // Optional params\n allowedPrivateKeyLengths?: readonly number[]; // for P521\n wrapPrivateKey?: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n\n endo?: EndomorphismOpts;\n // When a cofactor != 1, there can be an effective methods to:\n // 1. Determine whether a point is torsion-free\n isTorsionFree?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => boolean;\n // 2. Clear torsion component\n clearCofactor?: (c: WeierstrassPointCons<T>, point: WeierstrassPoint<T>) => WeierstrassPoint<T>;\n};\n/** @deprecated use ECDSASignOpts */\nexport type SignOpts = ECDSASignOpts;\n/** @deprecated use ECDSASignOpts */\nexport type VerOpts = ECDSAVerifyOpts;\n\n/** @deprecated use WeierstrassPoint */\nexport type ProjPointType<T> = WeierstrassPoint<T>;\n/** @deprecated use WeierstrassPointCons */\nexport type ProjConstructor<T> = WeierstrassPointCons<T>;\n/** @deprecated use ECDSASignatureCons */\nexport type SignatureConstructor = ECDSASignatureCons;\n\n// TODO: remove\nexport type CurvePointsType<T> = BasicWCurve<T> & {\n fromBytes?: (bytes: Uint8Array) => AffinePoint<T>;\n toBytes?: (\n c: WeierstrassPointCons<T>,\n point: WeierstrassPoint<T>,\n isCompressed: boolean\n ) => Uint8Array;\n};\n\n// LegacyWeierstrassOpts\nexport type CurvePointsTypeWithLength<T> = Readonly<CurvePointsType<T> & Partial<NLength>>;\n\n// LegacyWeierstrass\nexport type CurvePointsRes<T> = {\n Point: WeierstrassPointCons<T>;\n\n /** @deprecated use `Point.CURVE()` */\n CURVE: CurvePointsType<T>;\n /** @deprecated use `Point` */\n ProjectivePoint: WeierstrassPointCons<T>;\n /** @deprecated use `Point.Fn.fromBytes(privateKey)` */\n normPrivateKeyToScalar: (key: PrivKey) => bigint;\n /** @deprecated */\n weierstrassEquation: (x: T) => T;\n /** @deprecated use `Point.Fn.isValidNot0(num)` */\n isWithinCurveOrder: (num: bigint) => boolean;\n};\n\n// Aliases to legacy types\n// export type CurveType = LegacyECDSAOpts;\n// export type CurveFn = LegacyECDSA;\n// export type CurvePointsRes<T> = LegacyWeierstrass<T>;\n// export type CurvePointsType<T> = LegacyWeierstrassOpts<T>;\n// export type CurvePointsTypeWithLength<T> = LegacyWeierstrassOpts<T>;\n// export type BasicWCurve<T> = LegacyWeierstrassOpts<T>;\n\n/** @deprecated use `Uint8Array` */\nexport type PubKey = Hex | WeierstrassPoint<bigint>;\nexport type CurveType = BasicWCurve<bigint> & {\n hash: CHash; // CHash not FHash because we need outputLen for DRBG\n hmac?: HmacFnSync;\n randomBytes?: (bytesLength?: number) => Uint8Array;\n lowS?: boolean;\n bits2int?: (bytes: Uint8Array) => bigint;\n bits2int_modN?: (bytes: Uint8Array) => bigint;\n};\nexport type CurveFn = {\n /** @deprecated use `Point.CURVE()` */\n CURVE: CurvePointsType<bigint>;\n keygen: ECDSA['keygen'];\n getPublicKey: ECDSA['getPublicKey'];\n getSharedSecret: ECDSA['getSharedSecret'];\n sign: ECDSA['sign'];\n verify: ECDSA['verify'];\n Point: WeierstrassPointCons<bigint>;\n /** @deprecated use `Point` */\n ProjectivePoint: WeierstrassPointCons<bigint>;\n Signature: ECDSASignatureCons;\n utils: ECDSA['utils'];\n lengths: ECDSA['lengths'];\n};\n/** @deprecated use `weierstrass` in newer releases */\nexport function weierstrassPoints<T>(c: CurvePointsTypeWithLength<T>): CurvePointsRes<T> {\n const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);\n const Point = weierstrassN(CURVE, curveOpts);\n return _weierstrass_new_output_to_legacy(c, Point);\n}\nexport type WsPointComposed<T> = {\n CURVE: WeierstrassOpts<T>;\n curveOpts: WeierstrassExtraOpts<T>;\n};\nexport type WsComposed = {\n /** @deprecated use `Point.CURVE()` */\n CURVE: WeierstrassOpts<bigint>;\n hash: CHash;\n curveOpts: WeierstrassExtraOpts<bigint>;\n ecdsaOpts: ECDSAOpts;\n};\nfunction _weierstrass_legacy_opts_to_new<T>(c: CurvePointsType<T>): WsPointComposed<T> {\n const CURVE: WeierstrassOpts<T> = {\n a: c.a,\n b: c.b,\n p: c.Fp.ORDER,\n n: c.n,\n h: c.h,\n Gx: c.Gx,\n Gy: c.Gy,\n };\n const Fp = c.Fp;\n let allowedLengths = c.allowedPrivateKeyLengths\n ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))\n : undefined;\n const Fn = Field(CURVE.n, {\n BITS: c.nBitLength,\n allowedLengths: allowedLengths,\n modFromBytes: c.wrapPrivateKey,\n });\n const curveOpts: WeierstrassExtraOpts<T> = {\n Fp,\n Fn,\n allowInfinityPoint: c.allowInfinityPoint,\n endo: c.endo,\n isTorsionFree: c.isTorsionFree,\n clearCofactor: c.clearCofactor,\n fromBytes: c.fromBytes,\n toBytes: c.toBytes,\n };\n return { CURVE, curveOpts };\n}\nfunction _ecdsa_legacy_opts_to_new(c: CurveType): WsComposed {\n const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);\n const ecdsaOpts: ECDSAOpts = {\n hmac: c.hmac,\n randomBytes: c.randomBytes,\n lowS: c.lowS,\n bits2int: c.bits2int,\n bits2int_modN: c.bits2int_modN,\n };\n return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };\n}\nexport function _legacyHelperEquat<T>(Fp: IField<T>, a: T, b: T): (x: T) => T {\n /**\n * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y².\n * @returns y²\n */\n function weierstrassEquation(x: T): T {\n const x2 = Fp.sqr(x); // x * x\n const x3 = Fp.mul(x2, x); // x² * x\n return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x³ + a * x + b\n }\n return weierstrassEquation;\n}\nfunction _weierstrass_new_output_to_legacy<T>(\n c: CurvePointsType<T>,\n Point: WeierstrassPointCons<T>\n): CurvePointsRes<T> {\n const { Fp, Fn } = Point;\n function isWithinCurveOrder(num: bigint): boolean {\n return inRange(num, _1n, Fn.ORDER);\n }\n const weierstrassEquation = _legacyHelperEquat(Fp, c.a, c.b);\n return Object.assign(\n {},\n {\n CURVE: c,\n Point: Point,\n ProjectivePoint: Point,\n normPrivateKeyToScalar: (key: PrivKey) => _normFnElement(Fn, key),\n weierstrassEquation,\n isWithinCurveOrder,\n }\n );\n}\nfunction _ecdsa_new_output_to_legacy(c: CurveType, _ecdsa: ECDSA): CurveFn {\n const Point = _ecdsa.Point;\n return Object.assign({}, _ecdsa, {\n ProjectivePoint: Point,\n CURVE: Object.assign({}, c, nLength(Point.Fn.ORDER, Point.Fn.BITS)),\n });\n}\n\n// _ecdsa_legacy\nexport function weierstrass(c: CurveType): CurveFn {\n const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);\n const Point = weierstrassN(CURVE, curveOpts);\n const signs = ecdsa(Point, hash, ecdsaOpts);\n return _ecdsa_new_output_to_legacy(c, signs);\n}\n","/**\n * Hex, bytes and number utilities.\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport {\n abytes as abytes_,\n bytesToHex as bytesToHex_,\n concatBytes as concatBytes_,\n hexToBytes as hexToBytes_,\n isBytes as isBytes_,\n} from '@noble/hashes/utils.js';\nexport {\n abytes,\n anumber,\n bytesToHex,\n bytesToUtf8,\n concatBytes,\n hexToBytes,\n isBytes,\n randomBytes,\n utf8ToBytes,\n} from '@noble/hashes/utils.js';\nconst _0n = /* @__PURE__ */ BigInt(0);\nconst _1n = /* @__PURE__ */ BigInt(1);\nexport type Hex = Uint8Array | string; // hex strings are accepted for simplicity\nexport type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve\nexport type CHash = {\n (message: Uint8Array | string): Uint8Array;\n blockLen: number;\n outputLen: number;\n create(opts?: { dkLen?: number }): any; // For shake\n};\nexport type FHash = (message: Uint8Array | string) => Uint8Array;\n\nexport function abool(title: string, value: boolean): void {\n if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value);\n}\n\n// tmp name until v2\nexport function _abool2(value: boolean, title: string = ''): boolean {\n if (typeof value !== 'boolean') {\n const prefix = title && `\"${title}\"`;\n throw new Error(prefix + 'expected boolean, got type=' + typeof value);\n }\n return value;\n}\n\n// tmp name until v2\n/** Asserts something is Uint8Array. */\nexport function _abytes2(value: Uint8Array, length?: number, title: string = ''): Uint8Array {\n const bytes = isBytes_(value);\n const len = value?.length;\n const needsLen = length !== undefined;\n if (!bytes || (needsLen && len !== length)) {\n const prefix = title && `\"${title}\" `;\n const ofLen = needsLen ? ` of length ${length}` : '';\n const got = bytes ? `length=${len}` : `type=${typeof value}`;\n throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);\n }\n return value;\n}\n\n// Used in weierstrass, der\nexport function numberToHexUnpadded(num: number | bigint): string {\n const hex = num.toString(16);\n return hex.length & 1 ? '0' + hex : hex;\n}\n\nexport function hexToNumber(hex: string): bigint {\n if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian\n}\n\n// BE: Big Endian, LE: Little Endian\nexport function bytesToNumberBE(bytes: Uint8Array): bigint {\n return hexToNumber(bytesToHex_(bytes));\n}\nexport function bytesToNumberLE(bytes: Uint8Array): bigint {\n abytes_(bytes);\n return hexToNumber(bytesToHex_(Uint8Array.from(bytes).reverse()));\n}\n\nexport function numberToBytesBE(n: number | bigint, len: number): Uint8Array {\n return hexToBytes_(n.toString(16).padStart(len * 2, '0'));\n}\nexport function numberToBytesLE(n: number | bigint, len: number): Uint8Array {\n return numberToBytesBE(n, len).reverse();\n}\n// Unpadded, rarely used\nexport function numberToVarBytesBE(n: number | bigint): Uint8Array {\n return hexToBytes_(numberToHexUnpadded(n));\n}\n\n/**\n * Takes hex string or Uint8Array, converts to Uint8Array.\n * Validates output length.\n * Will throw error for other types.\n * @param title descriptive title for an error e.g. 'secret key'\n * @param hex hex string or Uint8Array\n * @param expectedLength optional, will compare to result array's length\n * @returns\n */\nexport function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array {\n let res: Uint8Array;\n if (typeof hex === 'string') {\n try {\n res = hexToBytes_(hex);\n } catch (e) {\n throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);\n }\n } else if (isBytes_(hex)) {\n // Uint8Array.from() instead of hash.slice() because node.js Buffer\n // is instance of Uint8Array, and its slice() creates **mutable** copy\n res = Uint8Array.from(hex);\n } else {\n throw new Error(title + ' must be hex string or Uint8Array');\n }\n const len = res.length;\n if (typeof expectedLength === 'number' && len !== expectedLength)\n throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);\n return res;\n}\n\n// Compares 2 u8a-s in kinda constant time\nexport function equalBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n/**\n * Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,\n * and Buffer#slice creates mutable copy. Never use Buffers!\n */\nexport function copyBytes(bytes: Uint8Array): Uint8Array {\n return Uint8Array.from(bytes);\n}\n\n/**\n * Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols\n * Should be safe to use for things expected to be ASCII.\n * Returns exact same result as utf8ToBytes for ASCII or throws.\n */\nexport function asciiToBytes(ascii: string): Uint8Array {\n return Uint8Array.from(ascii, (c, i) => {\n const charCode = c.charCodeAt(0);\n if (c.length !== 1 || charCode > 127) {\n throw new Error(\n `string contains non-ASCII character \"${ascii[i]}\" with code ${charCode} at position ${i}`\n );\n }\n return charCode;\n });\n}\n\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\n// export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\n// export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;\n\n// Is positive bigint\nconst isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;\n\nexport function inRange(n: bigint, min: bigint, max: bigint): boolean {\n return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;\n}\n\n/**\n * Asserts min <= n < max. NOTE: It's < max and not <= max.\n * @example\n * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)\n */\nexport function aInRange(title: string, n: bigint, min: bigint, max: bigint): void {\n // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?\n // consider P=256n, min=0n, max=P\n // - a for min=0 would require -1: `inRange('x', x, -1n, P)`\n // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`\n // - our way is the cleanest: `inRange('x', x, 0n, P)\n if (!inRange(n, min, max))\n throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);\n}\n\n// Bit operations\n\n/**\n * Calculates amount of bits in a bigint.\n * Same as `n.toString(2).length`\n * TODO: merge with nLength in modular\n */\nexport function bitLen(n: bigint): number {\n let len;\n for (len = 0; n > _0n; n >>= _1n, len += 1);\n return len;\n}\n\n/**\n * Gets single bit at position.\n * NOTE: first bit position is 0 (same as arrays)\n * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`\n */\nexport function bitGet(n: bigint, pos: number): bigint {\n return (n >> BigInt(pos)) & _1n;\n}\n\n/**\n * Sets single bit at position.\n */\nexport function bitSet(n: bigint, pos: number, value: boolean): bigint {\n return n | ((value ? _1n : _0n) << BigInt(pos));\n}\n\n/**\n * Calculate mask for N bits. Not using ** operator with bigints because of old engines.\n * Same as BigInt(`0b${Array(i).fill('1').join('')}`)\n */\nexport const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n;\n\n// DRBG\n\ntype Pred<T> = (v: Uint8Array) => T | undefined;\n/**\n * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n * @returns function that will call DRBG until 2nd arg returns something meaningful\n * @example\n * const drbg = createHmacDRBG<Key>(32, 32, hmac);\n * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined\n */\nexport function createHmacDrbg<T>(\n hashLen: number,\n qByteLen: number,\n hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array\n): (seed: Uint8Array, predicate: Pred<T>) => T {\n if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');\n if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');\n if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');\n // Step B, Step C: set hashLen to 8*ceil(hlen/8)\n const u8n = (len: number) => new Uint8Array(len); // creates Uint8Array\n const u8of = (byte: number) => Uint8Array.of(byte); // another shortcut\n let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same\n let i = 0; // Iterations counter, will throw when over 1000\n const reset = () => {\n v.fill(1);\n k.fill(0);\n i = 0;\n };\n const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)\n const reseed = (seed = u8n(0)) => {\n // HMAC-DRBG reseed() function. Steps D-G\n k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)\n v = h(); // v = hmac(k || v)\n if (seed.length === 0) return;\n k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)\n v = h(); // v = hmac(k || v)\n };\n const gen = () => {\n // HMAC-DRBG generate() function\n if (i++ >= 1000) throw new Error('drbg: tried 1000 values');\n let len = 0;\n const out: Uint8Array[] = [];\n while (len < qByteLen) {\n v = h();\n const sl = v.slice();\n out.push(sl);\n len += v.length;\n }\n return concatBytes_(...out);\n };\n const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {\n reset();\n reseed(seed); // Steps D-G\n let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]\n while (!(res = pred(gen()))) reseed();\n reset();\n return res;\n };\n return genUntil;\n}\n\n// Validating curves and fields\n\nconst validatorFns = {\n bigint: (val: any): boolean => typeof val === 'bigint',\n function: (val: any): boolean => typeof val === 'function',\n boolean: (val: any): boolean => typeof val === 'boolean',\n string: (val: any): boolean => typeof val === 'string',\n stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes_(val),\n isSafeInteger: (val: any): boolean => Number.isSafeInteger(val),\n array: (val: any): boolean => Array.isArray(val),\n field: (val: any, object: any): any => (object as any).Fp.isValid(val),\n hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen),\n} as const;\ntype Validator = keyof typeof validatorFns;\ntype ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };\n// type Record<K extends string | number | symbol, T> = { [P in K]: T; }\n\nexport function validateObject<T extends Record<string, any>>(\n object: T,\n validators: ValMap<T>,\n optValidators: ValMap<T> = {}\n): T {\n const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {\n const checkVal = validatorFns[type];\n if (typeof checkVal !== 'function') throw new Error('invalid validator function');\n\n const val = object[fieldName as keyof typeof object];\n if (isOptional && val === undefined) return;\n if (!checkVal(val, object)) {\n throw new Error(\n 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val\n );\n }\n };\n for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false);\n for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true);\n return object;\n}\n// validate type tests\n// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };\n// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!\n// // Should fail type-check\n// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });\n// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });\n// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });\n// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });\n\nexport function isHash(val: CHash): boolean {\n return typeof val === 'function' && Number.isSafeInteger(val.outputLen);\n}\nexport function _validateObject(\n object: Record<string, any>,\n fields: Record<string, string>,\n optFields: Record<string, string> = {}\n): void {\n if (!object || typeof object !== 'object') throw new Error('expected valid options object');\n type Item = keyof typeof object;\n function checkField(fieldName: Item, expectedType: string, isOpt: boolean) {\n const val = object[fieldName];\n if (isOpt && val === undefined) return;\n const current = typeof val;\n if (current !== expectedType || val === null)\n throw new Error(`param \"${fieldName}\" is invalid: expected ${expectedType}, got ${current}`);\n }\n Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));\n Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));\n}\n\n/**\n * throws not implemented error\n */\nexport const notImplemented = (): never => {\n throw new Error('not implemented');\n};\n\n/**\n * Memoizes (caches) computation result.\n * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.\n */\nexport function memoized<T extends object, R, O extends any[]>(\n fn: (arg: T, ...args: O) => R\n): (arg: T, ...args: O) => R {\n const map = new WeakMap<T, R>();\n return (arg: T, ...args: O): R => {\n const val = map.get(arg);\n if (val !== undefined) return val;\n const computed = fn(arg, ...args);\n map.set(arg, computed);\n return computed;\n };\n}\n","/**\n * Utils for modular division and fields.\n * Field over 11 is a finite (Galois) field is integer number operations `mod 11`.\n * There is no division: it is replaced by modular multiplicative inverse.\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport {\n _validateObject,\n anumber,\n bitMask,\n bytesToNumberBE,\n bytesToNumberLE,\n ensureBytes,\n numberToBytesBE,\n numberToBytesLE,\n} from '../utils.ts';\n\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);\n// prettier-ignore\nconst _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);\n// prettier-ignore\nconst _8n = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);\n\n// Calculates a modulo b\nexport function mod(a: bigint, b: bigint): bigint {\n const result = a % b;\n return result >= _0n ? result : b + result;\n}\n/**\n * Efficiently raise num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * pow(2n, 6n, 11n) // 64n % 11n == 9n\n */\nexport function pow(num: bigint, power: bigint, modulo: bigint): bigint {\n return FpPow(Field(modulo), num, power);\n}\n\n/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */\nexport function pow2(x: bigint, power: bigint, modulo: bigint): bigint {\n let res = x;\n while (power-- > _0n) {\n res *= res;\n res %= modulo;\n }\n return res;\n}\n\n/**\n * Inverses number over modulo.\n * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).\n */\nexport function invert(number: bigint, modulo: bigint): bigint {\n if (number === _0n) throw new Error('invert: expected non-zero number');\n if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo);\n // Fermat's little theorem \"CT-like\" version inv(n) = n^(m-2) mod m is 30x slower.\n let a = mod(number, modulo);\n let b = modulo;\n // prettier-ignore\n let x = _0n, y = _1n, u = _1n, v = _0n;\n while (a !== _0n) {\n // JIT applies optimization if those two lines follow each other\n const q = b / a;\n const r = b % a;\n const m = x - u * q;\n const n = y - v * q;\n // prettier-ignore\n b = a, a = r, x = u, y = v, u = m, v = n;\n }\n const gcd = b;\n if (gcd !== _1n) throw new Error('invert: does not exist');\n return mod(x, modulo);\n}\n\nfunction assertIsSquare<T>(Fp: IField<T>, root: T, n: T): void {\n if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');\n}\n\n// Not all roots are possible! Example which will throw:\n// const NUM =\n// n = 72057594037927816n;\n// Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));\nfunction sqrt3mod4<T>(Fp: IField<T>, n: T) {\n const p1div4 = (Fp.ORDER + _1n) / _4n;\n const root = Fp.pow(n, p1div4);\n assertIsSquare(Fp, root, n);\n return root;\n}\n\nfunction sqrt5mod8<T>(Fp: IField<T>, n: T) {\n const p5div8 = (Fp.ORDER - _5n) / _8n;\n const n2 = Fp.mul(n, _2n);\n const v = Fp.pow(n2, p5div8);\n const nv = Fp.mul(n, v);\n const i = Fp.mul(Fp.mul(nv, _2n), v);\n const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));\n assertIsSquare(Fp, root, n);\n return root;\n}\n\n// Based on RFC9380, Kong algorithm\n// prettier-ignore\nfunction sqrt9mod16(P: bigint): <T>(Fp: IField<T>, n: T) => T {\n const Fp_ = Field(P);\n const tn = tonelliShanks(P);\n const c1 = tn(Fp_, Fp_.neg(Fp_.ONE));// 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F\n const c2 = tn(Fp_, c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F\n const c3 = tn(Fp_, Fp_.neg(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F\n const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic\n return <T>(Fp: IField<T>, n: T) => {\n let tv1 = Fp.pow(n, c4); // 1. tv1 = x^c4\n let tv2 = Fp.mul(tv1, c1); // 2. tv2 = c1 * tv1\n const tv3 = Fp.mul(tv1, c2); // 3. tv3 = c2 * tv1\n const tv4 = Fp.mul(tv1, c3); // 4. tv4 = c3 * tv1\n const e1 = Fp.eql(Fp.sqr(tv2), n); // 5. e1 = (tv2^2) == x\n const e2 = Fp.eql(Fp.sqr(tv3), n); // 6. e2 = (tv3^2) == x\n tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x\n tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x\n const e3 = Fp.eql(Fp.sqr(tv2), n); // 9. e3 = (tv2^2) == x\n const root = Fp.cmov(tv1, tv2, e3);// 10. z = CMOV(tv1, tv2, e3) # Select sqrt from tv1 & tv2\n assertIsSquare(Fp, root, n);\n return root;\n };\n}\n\n/**\n * Tonelli-Shanks square root search algorithm.\n * 1. https://eprint.iacr.org/2012/685.pdf (page 12)\n * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks\n * @param P field order\n * @returns function that takes field Fp (created from P) and number n\n */\nexport function tonelliShanks(P: bigint): <T>(Fp: IField<T>, n: T) => T {\n // Initialization (precomputation).\n // Caching initialization could boost perf by 7%.\n if (P < _3n) throw new Error('sqrt is not defined for small field');\n // Factor P - 1 = Q * 2^S, where Q is odd\n let Q = P - _1n;\n let S = 0;\n while (Q % _2n === _0n) {\n Q /= _2n;\n S++;\n }\n\n // Find the first quadratic non-residue Z >= 2\n let Z = _2n;\n const _Fp = Field(P);\n while (FpLegendre(_Fp, Z) === 1) {\n // Basic primality test for P. After x iterations, chance of\n // not finding quadratic non-residue is 2^x, so 2^1000.\n if (Z++ > 1000) throw new Error('Cannot find square root: probably non-prime P');\n }\n // Fast-path; usually done before Z, but we do \"primality test\".\n if (S === 1) return sqrt3mod4;\n\n // Slow-path\n // TODO: test on Fp2 and others\n let cc = _Fp.pow(Z, Q); // c = z^Q\n const Q1div2 = (Q + _1n) / _2n;\n return function tonelliSlow<T>(Fp: IField<T>, n: T): T {\n if (Fp.is0(n)) return n;\n // Check if n is a quadratic residue using Legendre symbol\n if (FpLegendre(Fp, n) !== 1) throw new Error('Cannot find square root');\n\n // Initialize variables for the main loop\n let M = S;\n let c = Fp.mul(Fp.ONE, cc); // c = z^Q, move cc from field _Fp into field Fp\n let t = Fp.pow(n, Q); // t = n^Q, first guess at the fudge factor\n let R = Fp.pow(n, Q1div2); // R = n^((Q+1)/2), first guess at the square root\n\n // Main loop\n // while t != 1\n while (!Fp.eql(t, Fp.ONE)) {\n if (Fp.is0(t)) return Fp.ZERO; // if t=0 return R=0\n let i = 1;\n\n // Find the smallest i >= 1 such that t^(2^i) ≡ 1 (mod P)\n let t_tmp = Fp.sqr(t); // t^(2^1)\n while (!Fp.eql(t_tmp, Fp.ONE)) {\n i++;\n t_tmp = Fp.sqr(t_tmp); // t^(2^2)...\n if (i === M) throw new Error('Cannot find square root');\n }\n\n // Calculate the exponent for b: 2^(M - i - 1)\n const exponent = _1n << BigInt(M - i - 1); // bigint is important\n const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)\n\n // Update variables\n M = i;\n c = Fp.sqr(b); // c = b^2\n t = Fp.mul(t, c); // t = (t * b^2)\n R = Fp.mul(R, b); // R = R*b\n }\n return R;\n };\n}\n\n/**\n * Square root for a finite field. Will try optimized versions first:\n *\n * 1. P ≡ 3 (mod 4)\n * 2. P ≡ 5 (mod 8)\n * 3. P ≡ 9 (mod 16)\n * 4. Tonelli-Shanks algorithm\n *\n * Different algorithms can give different roots, it is up to user to decide which one they want.\n * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).\n */\nexport function FpSqrt(P: bigint): <T>(Fp: IField<T>, n: T) => T {\n // P ≡ 3 (mod 4) => √n = n^((P+1)/4)\n if (P % _4n === _3n) return sqrt3mod4;\n // P ≡ 5 (mod 8) => Atkin algorithm, page 10 of https://eprint.iacr.org/2012/685.pdf\n if (P % _8n === _5n) return sqrt5mod8;\n // P ≡ 9 (mod 16) => Kong algorithm, page 11 of https://eprint.iacr.org/2012/685.pdf (algorithm 4)\n if (P % _16n === _9n) return sqrt9mod16(P);\n // Tonelli-Shanks algorithm\n return tonelliShanks(P);\n}\n\n// Little-endian check for first LE bit (last BE bit);\nexport const isNegativeLE = (num: bigint, modulo: bigint): boolean =>\n (mod(num, modulo) & _1n) === _1n;\n\n/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */\nexport interface IField<T> {\n ORDER: bigint;\n isLE: boolean;\n BYTES: number;\n BITS: number;\n MASK: bigint;\n ZERO: T;\n ONE: T;\n // 1-arg\n create: (num: T) => T;\n isValid: (num: T) => boolean;\n is0: (num: T) => boolean;\n isValidNot0: (num: T) => boolean;\n neg(num: T): T;\n inv(num: T): T;\n sqrt(num: T): T;\n sqr(num: T): T;\n // 2-args\n eql(lhs: T, rhs: T): boolean;\n add(lhs: T, rhs: T): T;\n sub(lhs: T, rhs: T): T;\n mul(lhs: T, rhs: T | bigint): T;\n pow(lhs: T, power: bigint): T;\n div(lhs: T, rhs: T | bigint): T;\n // N for NonNormalized (for now)\n addN(lhs: T, rhs: T): T;\n subN(lhs: T, rhs: T): T;\n mulN(lhs: T, rhs: T | bigint): T;\n sqrN(num: T): T;\n\n // Optional\n // Should be same as sgn0 function in\n // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1).\n // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway.\n isOdd?(num: T): boolean; // Odd instead of even since we have it for Fp2\n allowedLengths?: number[];\n // legendre?(num: T): T;\n invertBatch: (lst: T[]) => T[];\n toBytes(num: T): Uint8Array;\n fromBytes(bytes: Uint8Array, skipValidation?: boolean): T;\n // If c is False, CMOV returns a, otherwise it returns b.\n cmov(a: T, b: T, c: boolean): T;\n}\n// prettier-ignore\nconst FIELD_FIELDS = [\n 'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',\n 'eql', 'add', 'sub', 'mul', 'pow', 'div',\n 'addN', 'subN', 'mulN', 'sqrN'\n] as const;\nexport function validateField<T>(field: IField<T>): IField<T> {\n const initial = {\n ORDER: 'bigint',\n MASK: 'bigint',\n BYTES: 'number',\n BITS: 'number',\n } as Record<string, string>;\n const opts = FIELD_FIELDS.reduce((map, val: string) => {\n map[val] = 'function';\n return map;\n }, initial);\n _validateObject(field, opts);\n // const max = 16384;\n // if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');\n // if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');\n return field;\n}\n\n// Generic field functions\n\n/**\n * Same as `pow` but for Fp: non-constant-time.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n */\nexport function FpPow<T>(Fp: IField<T>, num: T, power: bigint): T {\n if (power < _0n) throw new Error('invalid exponent, negatives unsupported');\n if (power === _0n) return Fp.ONE;\n if (power === _1n) return num;\n let p = Fp.ONE;\n let d = num;\n while (power > _0n) {\n if (power & _1n) p = Fp.mul(p, d);\n d = Fp.sqr(d);\n power >>= _1n;\n }\n return p;\n}\n\n/**\n * Efficiently invert an array of Field elements.\n * Exception-free. Will return `undefined` for 0 elements.\n * @param passZero map 0 to 0 (instead of undefined)\n */\nexport function FpInvertBatch<T>(Fp: IField<T>, nums: T[], passZero = false): T[] {\n const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : undefined);\n // Walk from first to last, multiply them by each other MOD p\n const multipliedAcc = nums.reduce((acc, num, i) => {\n if (Fp.is0(num)) return acc;\n inverted[i] = acc;\n return Fp.mul(acc, num);\n }, Fp.ONE);\n // Invert last element\n const invertedAcc = Fp.inv(multipliedAcc);\n // Walk from last to first, multiply them by inverted each other MOD p\n nums.reduceRight((acc, num, i) => {\n if (Fp.is0(num)) return acc;\n inverted[i] = Fp.mul(acc, inverted[i]);\n return Fp.mul(acc, num);\n }, invertedAcc);\n return inverted;\n}\n\n// TODO: remove\nexport function FpDiv<T>(Fp: IField<T>, lhs: T, rhs: T | bigint): T {\n return Fp.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, Fp.ORDER) : Fp.inv(rhs));\n}\n\n/**\n * Legendre symbol.\n * Legendre constant is used to calculate Legendre symbol (a | p)\n * which denotes the value of a^((p-1)/2) (mod p).\n *\n * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue\n * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue\n * * (a | p) ≡ 0 if a ≡ 0 (mod p)\n */\nexport function FpLegendre<T>(Fp: IField<T>, n: T): -1 | 0 | 1 {\n // We can use 3rd argument as optional cache of this value\n // but seems unneeded for now. The operation is very fast.\n const p1mod2 = (Fp.ORDER - _1n) / _2n;\n const powered = Fp.pow(n, p1mod2);\n const yes = Fp.eql(powered, Fp.ONE);\n const zero = Fp.eql(powered, Fp.ZERO);\n const no = Fp.eql(powered, Fp.neg(Fp.ONE));\n if (!yes && !zero && !no) throw new Error('invalid Legendre symbol result');\n return yes ? 1 : zero ? 0 : -1;\n}\n\n// This function returns True whenever the value x is a square in the field F.\nexport function FpIsSquare<T>(Fp: IField<T>, n: T): boolean {\n const l = FpLegendre(Fp, n);\n return l === 1;\n}\n\nexport type NLength = { nByteLength: number; nBitLength: number };\n// CURVE.n lengths\nexport function nLength(n: bigint, nBitLength?: number): NLength {\n // Bit size, byte size of CURVE.n\n if (nBitLength !== undefined) anumber(nBitLength);\n const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;\n const nByteLength = Math.ceil(_nBitLength / 8);\n return { nBitLength: _nBitLength, nByteLength };\n}\n\ntype FpField = IField<bigint> & Required<Pick<IField<bigint>, 'isOdd'>>;\ntype SqrtFn = (n: bigint) => bigint;\ntype FieldOpts = Partial<{\n sqrt: SqrtFn;\n isLE: boolean;\n BITS: number;\n modFromBytes: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n\n allowedLengths?: readonly number[]; // for P521 (adds padding for smaller sizes)\n}>;\n/**\n * Creates a finite field. Major performance optimizations:\n * * 1. Denormalized operations like mulN instead of mul.\n * * 2. Identical object shape: never add or remove keys.\n * * 3. `Object.freeze`.\n * Fragile: always run a benchmark on a change.\n * Security note: operations don't check 'isValid' for all elements for performance reasons,\n * it is caller responsibility to check this.\n * This is low-level code, please make sure you know what you're doing.\n *\n * Note about field properties:\n * * CHARACTERISTIC p = prime number, number of elements in main subgroup.\n * * ORDER q = similar to cofactor in curves, may be composite `q = p^m`.\n *\n * @param ORDER field order, probably prime, or could be composite\n * @param bitLen how many bits the field consumes\n * @param isLE (default: false) if encoding / decoding should be in little-endian\n * @param redef optional faster redefinitions of sqrt and other methods\n */\nexport function Field(\n ORDER: bigint,\n bitLenOrOpts?: number | FieldOpts, // TODO: use opts only in v2?\n isLE = false,\n opts: { sqrt?: SqrtFn } = {}\n): Readonly<FpField> {\n if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);\n let _nbitLength: number | undefined = undefined;\n let _sqrt: SqrtFn | undefined = undefined;\n let modFromBytes: boolean = false;\n let allowedLengths: undefined | readonly number[] = undefined;\n if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {\n if (opts.sqrt || isLE) throw new Error('cannot specify opts in two arguments');\n const _opts = bitLenOrOpts;\n if (_opts.BITS) _nbitLength = _opts.BITS;\n if (_opts.sqrt) _sqrt = _opts.sqrt;\n if (typeof _opts.isLE === 'boolean') isLE = _opts.isLE;\n if (typeof _opts.modFromBytes === 'boolean') modFromBytes = _opts.modFromBytes;\n allowedLengths = _opts.allowedLengths;\n } else {\n if (typeof bitLenOrOpts === 'number') _nbitLength = bitLenOrOpts;\n if (opts.sqrt) _sqrt = opts.sqrt;\n }\n const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);\n if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes');\n let sqrtP: ReturnType<typeof FpSqrt>; // cached sqrtP\n const f: Readonly<FpField> = Object.freeze({\n ORDER,\n isLE,\n BITS,\n BYTES,\n MASK: bitMask(BITS),\n ZERO: _0n,\n ONE: _1n,\n allowedLengths: allowedLengths,\n create: (num) => mod(num, ORDER),\n isValid: (num) => {\n if (typeof num !== 'bigint')\n throw new Error('invalid field element: expected bigint, got ' + typeof num);\n return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible\n },\n is0: (num) => num === _0n,\n // is valid and invertible\n isValidNot0: (num: bigint) => !f.is0(num) && f.isValid(num),\n isOdd: (num) => (num & _1n) === _1n,\n neg: (num) => mod(-num, ORDER),\n eql: (lhs, rhs) => lhs === rhs,\n\n sqr: (num) => mod(num * num, ORDER),\n add: (lhs, rhs) => mod(lhs + rhs, ORDER),\n sub: (lhs, rhs) => mod(lhs - rhs, ORDER),\n mul: (lhs, rhs) => mod(lhs * rhs, ORDER),\n pow: (num, power) => FpPow(f, num, power),\n div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),\n\n // Same as above, but doesn't normalize\n sqrN: (num) => num * num,\n addN: (lhs, rhs) => lhs + rhs,\n subN: (lhs, rhs) => lhs - rhs,\n mulN: (lhs, rhs) => lhs * rhs,\n\n inv: (num) => invert(num, ORDER),\n sqrt:\n _sqrt ||\n ((n) => {\n if (!sqrtP) sqrtP = FpSqrt(ORDER);\n return sqrtP(f, n);\n }),\n toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),\n fromBytes: (bytes, skipValidation = true) => {\n if (allowedLengths) {\n if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {\n throw new Error(\n 'Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length\n );\n }\n const padded = new Uint8Array(BYTES);\n // isLE add 0 to right, !isLE to the left.\n padded.set(bytes, isLE ? 0 : padded.length - bytes.length);\n bytes = padded;\n }\n if (bytes.length !== BYTES)\n throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);\n let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);\n if (modFromBytes) scalar = mod(scalar, ORDER);\n if (!skipValidation)\n if (!f.isValid(scalar)) throw new Error('invalid field element: outside of range 0..ORDER');\n // NOTE: we don't validate scalar here, please use isValid. This done such way because some\n // protocol may allow non-reduced scalar that reduced later or changed some other way.\n return scalar;\n },\n // TODO: we don't need it here, move out to separate fn\n invertBatch: (lst) => FpInvertBatch(f, lst),\n // We can't move this out because Fp6, Fp12 implement it\n // and it's unclear what to return in there.\n cmov: (a, b, c) => (c ? b : a),\n } as FpField);\n return Object.freeze(f);\n}\n\n// Generic random scalar, we can do same for other fields if via Fp2.mul(Fp2.ONE, Fp2.random)?\n// This allows unsafe methods like ignore bias or zero. These unsafe, but often used in different protocols (if deterministic RNG).\n// which mean we cannot force this via opts.\n// Not sure what to do with randomBytes, we can accept it inside opts if wanted.\n// Probably need to export getMinHashLength somewhere?\n// random(bytes?: Uint8Array, unsafeAllowZero = false, unsafeAllowBias = false) {\n// const LEN = !unsafeAllowBias ? getMinHashLength(ORDER) : BYTES;\n// if (bytes === undefined) bytes = randomBytes(LEN); // _opts.randomBytes?\n// const num = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);\n// // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0\n// const reduced = unsafeAllowZero ? mod(num, ORDER) : mod(num, ORDER - _1n) + _1n;\n// return reduced;\n// },\n\nexport function FpSqrtOdd<T>(Fp: IField<T>, elm: T): T {\n if (!Fp.isOdd) throw new Error(\"Field doesn't have isOdd\");\n const root = Fp.sqrt(elm);\n return Fp.isOdd(root) ? root : Fp.neg(root);\n}\n\nexport function FpSqrtEven<T>(Fp: IField<T>, elm: T): T {\n if (!Fp.isOdd) throw new Error(\"Field doesn't have isOdd\");\n const root = Fp.sqrt(elm);\n return Fp.isOdd(root) ? Fp.neg(root) : root;\n}\n\n/**\n * \"Constant-time\" private key generation utility.\n * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).\n * Which makes it slightly more biased, less secure.\n * @deprecated use `mapKeyToField` instead\n */\nexport function hashToPrivateScalar(\n hash: string | Uint8Array,\n groupOrder: bigint,\n isLE = false\n): bigint {\n hash = ensureBytes('privateHash', hash);\n const hashLen = hash.length;\n const minLen = nLength(groupOrder).nByteLength + 8;\n if (minLen < 24 || hashLen < minLen || hashLen > 1024)\n throw new Error(\n 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen\n );\n const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);\n return mod(num, groupOrder - _1n) + _1n;\n}\n\n/**\n * Returns total number of bytes consumed by the field element.\n * For example, 32 bytes for usual 256-bit weierstrass curve.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of field\n */\nexport function getFieldBytesLength(fieldOrder: bigint): number {\n if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint');\n const bitLength = fieldOrder.toString(2).length;\n return Math.ceil(bitLength / 8);\n}\n\n/**\n * Returns minimal amount of bytes that can be safely reduced\n * by field order.\n * Should be 2^-128 for 128-bit curve such as P256.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of target hash\n */\nexport function getMinHashLength(fieldOrder: bigint): number {\n const length = getFieldBytesLength(fieldOrder);\n return length + Math.ceil(length / 2);\n}\n\n/**\n * \"Constant-time\" private key generation utility.\n * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF\n * and convert them into private scalar, with the modulo bias being negligible.\n * Needs at least 48 bytes of input for 32-byte private key.\n * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/\n * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final\n * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5\n * @param hash hash output from SHA3 or a similar function\n * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)\n * @param isLE interpret hash bytes as LE num\n * @returns valid private scalar\n */\nexport function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array {\n const len = key.length;\n const fieldLen = getFieldBytesLength(fieldOrder);\n const minLen = getMinHashLength(fieldOrder);\n // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.\n if (len < 16 || len < minLen || len > 1024)\n throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);\n const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);\n // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0\n const reduced = mod(num, fieldOrder - _1n) + _1n;\n return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);\n}\n","/**\n * Methods for elliptic curve multiplication by scalars.\n * Contains wNAF, pippenger.\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { bitLen, bitMask, validateObject } from '../utils.ts';\nimport { Field, FpInvertBatch, nLength, validateField, type IField } from './modular.ts';\n\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\n\nexport type AffinePoint<T> = {\n x: T;\n y: T;\n} & { Z?: never };\n\n// This was initialy do this way to re-use montgomery ladder in field (add->mul,double->sqr), but\n// that didn't happen and there is probably not much reason to have separate Group like this?\nexport interface Group<T extends Group<T>> {\n double(): T;\n negate(): T;\n add(other: T): T;\n subtract(other: T): T;\n equals(other: T): boolean;\n multiply(scalar: bigint): T;\n toAffine?(invertedZ?: any): AffinePoint<any>;\n}\n\n// We can't \"abstract out\" coordinates (X, Y, Z; and T in Edwards): argument names of constructor\n// are not accessible. See Typescript gh-56093, gh-41594.\n//\n// We have to use recursive types, so it will return actual point, not constained `CurvePoint`.\n// If, at any point, P is `any`, it will erase all types and replace it\n// with `any`, because of recursion, `any implements CurvePoint`,\n// but we lose all constrains on methods.\n\n/** Base interface for all elliptic curve Points. */\nexport interface CurvePoint<F, P extends CurvePoint<F, P>> extends Group<P> {\n /** Affine x coordinate. Different from projective / extended X coordinate. */\n x: F;\n /** Affine y coordinate. Different from projective / extended Y coordinate. */\n y: F;\n Z?: F;\n double(): P;\n negate(): P;\n add(other: P): P;\n subtract(other: P): P;\n equals(other: P): boolean;\n multiply(scalar: bigint): P;\n assertValidity(): void;\n clearCofactor(): P;\n is0(): boolean;\n isTorsionFree(): boolean;\n isSmallOrder(): boolean;\n multiplyUnsafe(scalar: bigint): P;\n /**\n * Massively speeds up `p.multiply(n)` by using precompute tables (caching). See {@link wNAF}.\n * @param isLazy calculate cache now. Default (true) ensures it's deferred to first `multiply()`\n */\n precompute(windowSize?: number, isLazy?: boolean): P;\n /** Converts point to 2D xy affine coordinates */\n toAffine(invertedZ?: F): AffinePoint<F>;\n toBytes(): Uint8Array;\n toHex(): string;\n}\n\n/** Base interface for all elliptic curve Point constructors. */\nexport interface CurvePointCons<P extends CurvePoint<any, P>> {\n [Symbol.hasInstance]: (item: unknown) => boolean;\n BASE: P;\n ZERO: P;\n /** Field for basic curve math */\n Fp: IField<P_F<P>>;\n /** Scalar field, for scalars in multiply and others */\n Fn: IField<bigint>;\n /** Creates point from x, y. Does NOT validate if the point is valid. Use `.assertValidity()`. */\n fromAffine(p: AffinePoint<P_F<P>>): P;\n fromBytes(bytes: Uint8Array): P;\n fromHex(hex: Uint8Array | string): P;\n}\n\n// Type inference helpers: PC - PointConstructor, P - Point, Fp - Field element\n// Short names, because we use them a lot in result types:\n// * we can't do 'P = GetCurvePoint<PC>': this is default value and doesn't constrain anything\n// * we can't do 'type X = GetCurvePoint<PC>': it won't be accesible for arguments/return types\n// * `CurvePointCons<P extends CurvePoint<any, P>>` constraints from interface definition\n// won't propagate, if `PC extends CurvePointCons<any>`: the P would be 'any', which is incorrect\n// * PC could be super specific with super specific P, which implements CurvePoint<any, P>.\n// this means we need to do stuff like\n// `function test<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(`\n// if we want type safety around P, otherwise PC_P<PC> will be any\n\n/** Returns Fp type from Point (P_F<P> == P.F) */\nexport type P_F<P extends CurvePoint<any, P>> = P extends CurvePoint<infer F, P> ? F : never;\n/** Returns Fp type from PointCons (PC_F<PC> == PC.P.F) */\nexport type PC_F<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['Fp']['ZERO'];\n/** Returns Point type from PointCons (PC_P<PC> == PC.P) */\nexport type PC_P<PC extends CurvePointCons<CurvePoint<any, any>>> = PC['ZERO'];\n\n// Ugly hack to get proper type inference, because in typescript fails to infer resursively.\n// The hack allows to do up to 10 chained operations without applying type erasure.\n//\n// Types which won't work:\n// * `CurvePointCons<CurvePoint<any, any>>`, will return `any` after 1 operation\n// * `CurvePointCons<any>: WeierstrassPointCons<bigint> extends CurvePointCons<any> = false`\n// * `P extends CurvePoint, PC extends CurvePointCons<P>`\n// * It can't infer P from PC alone\n// * Too many relations between F, P & PC\n// * It will infer P/F if `arg: CurvePointCons<F, P>`, but will fail if PC is generic\n// * It will work correctly if there is an additional argument of type P\n// * But generally, we don't want to parametrize `CurvePointCons` over `F`: it will complicate\n// types, making them un-inferable\n// prettier-ignore\nexport type PC_ANY = CurvePointCons<\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any,\n CurvePoint<any, any>\n >>>>>>>>>\n>;\n\nexport interface CurveLengths {\n secretKey?: number;\n publicKey?: number;\n publicKeyUncompressed?: number;\n publicKeyHasPrefix?: boolean;\n signature?: number;\n seed?: number;\n}\nexport type GroupConstructor<T> = {\n BASE: T;\n ZERO: T;\n};\n/** @deprecated */\nexport type ExtendedGroupConstructor<T> = GroupConstructor<T> & {\n Fp: IField<any>;\n Fn: IField<bigint>;\n fromAffine(ap: AffinePoint<any>): T;\n};\nexport type Mapper<T> = (i: T[]) => T[];\n\nexport function negateCt<T extends { negate: () => T }>(condition: boolean, item: T): T {\n const neg = item.negate();\n return condition ? neg : item;\n}\n\n/**\n * Takes a bunch of Projective Points but executes only one\n * inversion on all of them. Inversion is very slow operation,\n * so this improves performance massively.\n * Optimization: converts a list of projective points to a list of identical points with Z=1.\n */\nexport function normalizeZ<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(\n c: PC,\n points: P[]\n): P[] {\n const invertedZs = FpInvertBatch(\n c.Fp,\n points.map((p) => p.Z!)\n );\n return points.map((p, i) => c.fromAffine(p.toAffine(invertedZs[i])));\n}\n\nfunction validateW(W: number, bits: number) {\n if (!Number.isSafeInteger(W) || W <= 0 || W > bits)\n throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);\n}\n\n/** Internal wNAF opts for specific W and scalarBits */\nexport type WOpts = {\n windows: number;\n windowSize: number;\n mask: bigint;\n maxNumber: number;\n shiftBy: bigint;\n};\n\nfunction calcWOpts(W: number, scalarBits: number): WOpts {\n validateW(W, scalarBits);\n const windows = Math.ceil(scalarBits / W) + 1; // W=8 33. Not 32, because we skip zero\n const windowSize = 2 ** (W - 1); // W=8 128. Not 256, because we skip zero\n const maxNumber = 2 ** W; // W=8 256\n const mask = bitMask(W); // W=8 255 == mask 0b11111111\n const shiftBy = BigInt(W); // W=8 8\n return { windows, windowSize, mask, maxNumber, shiftBy };\n}\n\nfunction calcOffsets(n: bigint, window: number, wOpts: WOpts) {\n const { windowSize, mask, maxNumber, shiftBy } = wOpts;\n let wbits = Number(n & mask); // extract W bits.\n let nextN = n >> shiftBy; // shift number by W bits.\n\n // What actually happens here:\n // const highestBit = Number(mask ^ (mask >> 1n));\n // let wbits2 = wbits - 1; // skip zero\n // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~);\n\n // split if bits > max: +224 => 256-32\n if (wbits > windowSize) {\n // we skip zero, which means instead of `>= size-1`, we do `> size`\n wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.\n nextN += _1n; // +256 (carry)\n }\n const offsetStart = window * windowSize;\n const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero\n const isZero = wbits === 0; // is current window slice a 0?\n const isNeg = wbits < 0; // is current window slice negative?\n const isNegF = window % 2 !== 0; // fake random statement for noise\n const offsetF = offsetStart; // fake offset for noise\n return { nextN, offset, isZero, isNeg, isNegF, offsetF };\n}\n\nfunction validateMSMPoints(points: any[], c: any) {\n if (!Array.isArray(points)) throw new Error('array expected');\n points.forEach((p, i) => {\n if (!(p instanceof c)) throw new Error('invalid point at index ' + i);\n });\n}\nfunction validateMSMScalars(scalars: any[], field: any) {\n if (!Array.isArray(scalars)) throw new Error('array of scalars expected');\n scalars.forEach((s, i) => {\n if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i);\n });\n}\n\n// Since points in different groups cannot be equal (different object constructor),\n// we can have single place to store precomputes.\n// Allows to make points frozen / immutable.\nconst pointPrecomputes = new WeakMap<any, any[]>();\nconst pointWindowSizes = new WeakMap<any, number>();\n\nfunction getW(P: any): number {\n // To disable precomputes:\n // return 1;\n return pointWindowSizes.get(P) || 1;\n}\n\nfunction assert0(n: bigint): void {\n if (n !== _0n) throw new Error('invalid wNAF');\n}\n\n/**\n * Elliptic curve multiplication of Point by scalar. Fragile.\n * Table generation takes **30MB of ram and 10ms on high-end CPU**,\n * but may take much longer on slow devices. Actual generation will happen on\n * first call of `multiply()`. By default, `BASE` point is precomputed.\n *\n * Scalars should always be less than curve order: this should be checked inside of a curve itself.\n * Creates precomputation tables for fast multiplication:\n * - private scalar is split by fixed size windows of W bits\n * - every window point is collected from window's table & added to accumulator\n * - since windows are different, same point inside tables won't be accessed more than once per calc\n * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)\n * - +1 window is neccessary for wNAF\n * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication\n *\n * @todo Research returning 2d JS array of windows, instead of a single window.\n * This would allow windows to be in different memory locations\n */\nexport class wNAF<PC extends PC_ANY> {\n private readonly BASE: PC_P<PC>;\n private readonly ZERO: PC_P<PC>;\n private readonly Fn: PC['Fn'];\n readonly bits: number;\n\n // Parametrized with a given Point class (not individual point)\n constructor(Point: PC, bits: number) {\n this.BASE = Point.BASE;\n this.ZERO = Point.ZERO;\n this.Fn = Point.Fn;\n this.bits = bits;\n }\n\n // non-const time multiplication ladder\n _unsafeLadder(elm: PC_P<PC>, n: bigint, p: PC_P<PC> = this.ZERO): PC_P<PC> {\n let d: PC_P<PC> = elm;\n while (n > _0n) {\n if (n & _1n) p = p.add(d);\n d = d.double();\n n >>= _1n;\n }\n return p;\n }\n\n /**\n * Creates a wNAF precomputation window. Used for caching.\n * Default window size is set by `utils.precompute()` and is equal to 8.\n * Number of precomputed points depends on the curve size:\n * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:\n * - 𝑊 is the window size\n * - 𝑛 is the bitlength of the curve order.\n * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.\n * @param point Point instance\n * @param W window size\n * @returns precomputed point tables flattened to a single array\n */\n private precomputeWindow(point: PC_P<PC>, W: number): PC_P<PC>[] {\n const { windows, windowSize } = calcWOpts(W, this.bits);\n const points: PC_P<PC>[] = [];\n let p: PC_P<PC> = point;\n let base = p;\n for (let window = 0; window < windows; window++) {\n base = p;\n points.push(base);\n // i=1, bc we skip 0\n for (let i = 1; i < windowSize; i++) {\n base = base.add(p);\n points.push(base);\n }\n p = base.double();\n }\n return points;\n }\n\n /**\n * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.\n * More compact implementation:\n * https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541\n * @returns real and fake (for const-time) points\n */\n private wNAF(W: number, precomputes: PC_P<PC>[], n: bigint): { p: PC_P<PC>; f: PC_P<PC> } {\n // Scalar should be smaller than field order\n if (!this.Fn.isValid(n)) throw new Error('invalid scalar');\n // Accumulators\n let p = this.ZERO;\n let f = this.BASE;\n // This code was first written with assumption that 'f' and 'p' will never be infinity point:\n // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,\n // there is negate now: it is possible that negated element from low value\n // would be the same as high element, which will create carry into next window.\n // It's not obvious how this can fail, but still worth investigating later.\n const wo = calcWOpts(W, this.bits);\n for (let window = 0; window < wo.windows; window++) {\n // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise\n const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);\n n = nextN;\n if (isZero) {\n // bits are 0: add garbage to fake point\n // Important part for const-time getPublicKey: add random \"noise\" point to f.\n f = f.add(negateCt(isNegF, precomputes[offsetF]));\n } else {\n // bits are 1: add to result point\n p = p.add(negateCt(isNeg, precomputes[offset]));\n }\n }\n assert0(n);\n // Return both real and fake points: JIT won't eliminate f.\n // At this point there is a way to F be infinity-point even if p is not,\n // which makes it less const-time: around 1 bigint multiply.\n return { p, f };\n }\n\n /**\n * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.\n * @param acc accumulator point to add result of multiplication\n * @returns point\n */\n private wNAFUnsafe(\n W: number,\n precomputes: PC_P<PC>[],\n n: bigint,\n acc: PC_P<PC> = this.ZERO\n ): PC_P<PC> {\n const wo = calcWOpts(W, this.bits);\n for (let window = 0; window < wo.windows; window++) {\n if (n === _0n) break; // Early-exit, skip 0 value\n const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);\n n = nextN;\n if (isZero) {\n // Window bits are 0: skip processing.\n // Move to next window.\n continue;\n } else {\n const item = precomputes[offset];\n acc = acc.add(isNeg ? item.negate() : item); // Re-using acc allows to save adds in MSM\n }\n }\n assert0(n);\n return acc;\n }\n\n private getPrecomputes(W: number, point: PC_P<PC>, transform?: Mapper<PC_P<PC>>): PC_P<PC>[] {\n // Calculate precomputes on a first run, reuse them after\n let comp = pointPrecomputes.get(point);\n if (!comp) {\n comp = this.precomputeWindow(point, W) as PC_P<PC>[];\n if (W !== 1) {\n // Doing transform outside of if brings 15% perf hit\n if (typeof transform === 'function') comp = transform(comp);\n pointPrecomputes.set(point, comp);\n }\n }\n return comp;\n }\n\n cached(\n point: PC_P<PC>,\n scalar: bigint,\n transform?: Mapper<PC_P<PC>>\n ): { p: PC_P<PC>; f: PC_P<PC> } {\n const W = getW(point);\n return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);\n }\n\n unsafe(point: PC_P<PC>, scalar: bigint, transform?: Mapper<PC_P<PC>>, prev?: PC_P<PC>): PC_P<PC> {\n const W = getW(point);\n if (W === 1) return this._unsafeLadder(point, scalar, prev); // For W=1 ladder is ~x2 faster\n return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);\n }\n\n // We calculate precomputes for elliptic curve point multiplication\n // using windowed method. This specifies window size and\n // stores precomputed values. Usually only base point would be precomputed.\n createCache(P: PC_P<PC>, W: number): void {\n validateW(W, this.bits);\n pointWindowSizes.set(P, W);\n pointPrecomputes.delete(P);\n }\n\n hasCache(elm: PC_P<PC>): boolean {\n return getW(elm) !== 1;\n }\n}\n\n/**\n * Endomorphism-specific multiplication for Koblitz curves.\n * Cost: 128 dbl, 0-256 adds.\n */\nexport function mulEndoUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(\n Point: PC,\n point: P,\n k1: bigint,\n k2: bigint\n): { p1: P; p2: P } {\n let acc = point;\n let p1 = Point.ZERO;\n let p2 = Point.ZERO;\n while (k1 > _0n || k2 > _0n) {\n if (k1 & _1n) p1 = p1.add(acc);\n if (k2 & _1n) p2 = p2.add(acc);\n acc = acc.double();\n k1 >>= _1n;\n k2 >>= _1n;\n }\n return { p1, p2 };\n}\n\n/**\n * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).\n * 30x faster vs naive addition on L=4096, 10x faster than precomputes.\n * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.\n * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.\n * @param c Curve Point constructor\n * @param fieldN field over CURVE.N - important that it's not over CURVE.P\n * @param points array of L curve points\n * @param scalars array of L scalars (aka secret keys / bigints)\n */\nexport function pippenger<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(\n c: PC,\n fieldN: IField<bigint>,\n points: P[],\n scalars: bigint[]\n): P {\n // If we split scalars by some window (let's say 8 bits), every chunk will only\n // take 256 buckets even if there are 4096 scalars, also re-uses double.\n // TODO:\n // - https://eprint.iacr.org/2024/750.pdf\n // - https://tches.iacr.org/index.php/TCHES/article/view/10287\n // 0 is accepted in scalars\n validateMSMPoints(points, c);\n validateMSMScalars(scalars, fieldN);\n const plength = points.length;\n const slength = scalars.length;\n if (plength !== slength) throw new Error('arrays of points and scalars must have equal length');\n // if (plength === 0) throw new Error('array must be of length >= 2');\n const zero = c.ZERO;\n const wbits = bitLen(BigInt(plength));\n let windowSize = 1; // bits\n if (wbits > 12) windowSize = wbits - 3;\n else if (wbits > 4) windowSize = wbits - 2;\n else if (wbits > 0) windowSize = 2;\n const MASK = bitMask(windowSize);\n const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array\n const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;\n let sum = zero;\n for (let i = lastBits; i >= 0; i -= windowSize) {\n buckets.fill(zero);\n for (let j = 0; j < slength; j++) {\n const scalar = scalars[j];\n const wbits = Number((scalar >> BigInt(i)) & MASK);\n buckets[wbits] = buckets[wbits].add(points[j]);\n }\n let resI = zero; // not using this will do small speed-up, but will lose ct\n // Skip first bucket, because it is zero\n for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {\n sumI = sumI.add(buckets[j]);\n resI = resI.add(sumI);\n }\n sum = sum.add(resI);\n if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double();\n }\n return sum as P;\n}\n/**\n * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).\n * @param c Curve Point constructor\n * @param fieldN field over CURVE.N - important that it's not over CURVE.P\n * @param points array of L curve points\n * @returns function which multiplies points with scaars\n */\nexport function precomputeMSMUnsafe<P extends CurvePoint<any, P>, PC extends CurvePointCons<P>>(\n c: PC,\n fieldN: IField<bigint>,\n points: P[],\n windowSize: number\n): (scalars: bigint[]) => P {\n /**\n * Performance Analysis of Window-based Precomputation\n *\n * Base Case (256-bit scalar, 8-bit window):\n * - Standard precomputation requires:\n * - 31 additions per scalar × 256 scalars = 7,936 ops\n * - Plus 255 summary additions = 8,191 total ops\n * Note: Summary additions can be optimized via accumulator\n *\n * Chunked Precomputation Analysis:\n * - Using 32 chunks requires:\n * - 255 additions per chunk\n * - 256 doublings\n * - Total: (255 × 32) + 256 = 8,416 ops\n *\n * Memory Usage Comparison:\n * Window Size | Standard Points | Chunked Points\n * ------------|-----------------|---------------\n * 4-bit | 520 | 15\n * 8-bit | 4,224 | 255\n * 10-bit | 13,824 | 1,023\n * 16-bit | 557,056 | 65,535\n *\n * Key Advantages:\n * 1. Enables larger window sizes due to reduced memory overhead\n * 2. More efficient for smaller scalar counts:\n * - 16 chunks: (16 × 255) + 256 = 4,336 ops\n * - ~2x faster than standard 8,191 ops\n *\n * Limitations:\n * - Not suitable for plain precomputes (requires 256 constant doublings)\n * - Performance degrades with larger scalar counts:\n * - Optimal for ~256 scalars\n * - Less efficient for 4096+ scalars (Pippenger preferred)\n */\n validateW(windowSize, fieldN.BITS);\n validateMSMPoints(points, c);\n const zero = c.ZERO;\n const tableSize = 2 ** windowSize - 1; // table size (without zero)\n const chunks = Math.ceil(fieldN.BITS / windowSize); // chunks of item\n const MASK = bitMask(windowSize);\n const tables = points.map((p: P) => {\n const res = [];\n for (let i = 0, acc = p; i < tableSize; i++) {\n res.push(acc);\n acc = acc.add(p);\n }\n return res;\n });\n return (scalars: bigint[]): P => {\n validateMSMScalars(scalars, fieldN);\n if (scalars.length > points.length)\n throw new Error('array of scalars must be smaller than array of points');\n let res = zero;\n for (let i = 0; i < chunks; i++) {\n // No need to double if accumulator is still zero.\n if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double();\n const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize);\n for (let j = 0; j < scalars.length; j++) {\n const n = scalars[j];\n const curr = Number((n >> shiftBy) & MASK);\n if (!curr) continue; // skip zero scalars chunks\n res = res.add(tables[j][curr - 1]);\n }\n }\n return res;\n };\n}\n\n// TODO: remove\n/**\n * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok.\n * Though generator can be different (Fp2 / Fp6 for BLS).\n */\nexport type BasicCurve<T> = {\n Fp: IField<T>; // Field over which we'll do calculations (Fp)\n n: bigint; // Curve order, total count of valid points in the field\n nBitLength?: number; // bit length of curve order\n nByteLength?: number; // byte length of curve order\n h: bigint; // cofactor. we can assign default=1, but users will just ignore it w/o validation\n hEff?: bigint; // Number to multiply to clear cofactor\n Gx: T; // base point X coordinate\n Gy: T; // base point Y coordinate\n allowInfinityPoint?: boolean; // bls12-381 requires it. ZERO point is valid, but invalid pubkey\n};\n\n// TODO: remove\n/** @deprecated */\nexport function validateBasic<FP, T>(\n curve: BasicCurve<FP> & T\n): Readonly<\n {\n readonly nBitLength: number;\n readonly nByteLength: number;\n } & BasicCurve<FP> &\n T & {\n p: bigint;\n }\n> {\n validateField(curve.Fp);\n validateObject(\n curve,\n {\n n: 'bigint',\n h: 'bigint',\n Gx: 'field',\n Gy: 'field',\n },\n {\n nBitLength: 'isSafeInteger',\n nByteLength: 'isSafeInteger',\n }\n );\n // Set defaults\n return Object.freeze({\n ...nLength(curve.n, curve.nBitLength),\n ...curve,\n ...{ p: curve.Fp.ORDER },\n } as const);\n}\n\nexport type ValidCurveParams<T> = {\n p: bigint;\n n: bigint;\n h: bigint;\n a: T;\n b?: T;\n d?: T;\n Gx: T;\n Gy: T;\n};\n\nfunction createField<T>(order: bigint, field?: IField<T>, isLE?: boolean): IField<T> {\n if (field) {\n if (field.ORDER !== order) throw new Error('Field.ORDER must match order: Fp == p, Fn == n');\n validateField(field);\n return field;\n } else {\n return Field(order, { isLE }) as unknown as IField<T>;\n }\n}\nexport type FpFn<T> = { Fp: IField<T>; Fn: IField<bigint> };\n\n/** Validates CURVE opts and creates fields */\nexport function _createCurveFields<T>(\n type: 'weierstrass' | 'edwards',\n CURVE: ValidCurveParams<T>,\n curveOpts: Partial<FpFn<T>> = {},\n FpFnLE?: boolean\n): FpFn<T> & { CURVE: ValidCurveParams<T> } {\n if (FpFnLE === undefined) FpFnLE = type === 'edwards';\n if (!CURVE || typeof CURVE !== 'object') throw new Error(`expected valid ${type} CURVE object`);\n for (const p of ['p', 'n', 'h'] as const) {\n const val = CURVE[p];\n if (!(typeof val === 'bigint' && val > _0n))\n throw new Error(`CURVE.${p} must be positive bigint`);\n }\n const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE);\n const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE);\n const _b: 'b' | 'd' = type === 'weierstrass' ? 'b' : 'd';\n const params = ['Gx', 'Gy', 'a', _b] as const;\n for (const p of params) {\n // @ts-ignore\n if (!Fp.isValid(CURVE[p]))\n throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`);\n }\n CURVE = Object.freeze(Object.assign({}, CURVE));\n return { CURVE, Fp, Fn };\n}\n","/**\n * Utilities for short weierstrass curves, combined with noble-hashes.\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.ts';\nimport type { CHash } from './utils.ts';\n\n/** connects noble-curves to noble-hashes */\nexport function getHash(hash: CHash): { hash: CHash } {\n return { hash };\n}\n/** Same API as @noble/hashes, with ability to create curve with custom hash */\nexport type CurveDef = Readonly<Omit<CurveType, 'hash'>>;\nexport type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn };\n\n/** @deprecated use new `weierstrass()` and `ecdsa()` methods */\nexport function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate {\n const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, hash: hash });\n return { ...create(defHash), create };\n}\n","/**\n * SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).\n *\n * Belongs to Koblitz curves: it has efficiently-computable GLV endomorphism ψ,\n * check out {@link EndomorphismOpts}. Seems to be rigid (not backdoored).\n * @module\n */\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { randomBytes } from '@noble/hashes/utils.js';\nimport { createCurve, type CurveFnWithCreate } from './_shortw_utils.ts';\nimport type { CurveLengths } from './abstract/curve.ts';\nimport {\n createHasher,\n type H2CHasher,\n type H2CMethod,\n isogenyMap,\n} from './abstract/hash-to-curve.ts';\nimport { Field, mapHashToField, mod, pow2 } from './abstract/modular.ts';\nimport {\n _normFnElement,\n type EndomorphismOpts,\n mapToCurveSimpleSWU,\n type WeierstrassPoint as PointType,\n type WeierstrassOpts,\n type WeierstrassPointCons,\n} from './abstract/weierstrass.ts';\nimport type { Hex, PrivKey } from './utils.ts';\nimport {\n bytesToNumberBE,\n concatBytes,\n ensureBytes,\n inRange,\n numberToBytesBE,\n utf8ToBytes,\n} from './utils.ts';\n\n// Seems like generator was produced from some seed:\n// `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`\n// // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n\nconst secp256k1_CURVE: WeierstrassOpts<bigint> = {\n p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),\n n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),\n h: BigInt(1),\n a: BigInt(0),\n b: BigInt(7),\n Gx: BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),\n Gy: BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'),\n};\n\nconst secp256k1_ENDO: EndomorphismOpts = {\n beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),\n basises: [\n [BigInt('0x3086d221a7d46bcde86c90e49284eb15'), -BigInt('0xe4437ed6010e88286f547fa90abfe4c3')],\n [BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), BigInt('0x3086d221a7d46bcde86c90e49284eb15')],\n ],\n};\n\nconst _0n = /* @__PURE__ */ BigInt(0);\nconst _1n = /* @__PURE__ */ BigInt(1);\nconst _2n = /* @__PURE__ */ BigInt(2);\n\n/**\n * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.\n * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]\n */\nfunction sqrtMod(y: bigint): bigint {\n const P = secp256k1_CURVE.p;\n // prettier-ignore\n const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);\n // prettier-ignore\n const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);\n const b2 = (y * y * y) % P; // x^3, 11\n const b3 = (b2 * b2 * y) % P; // x^7\n const b6 = (pow2(b3, _3n, P) * b3) % P;\n const b9 = (pow2(b6, _3n, P) * b3) % P;\n const b11 = (pow2(b9, _2n, P) * b2) % P;\n const b22 = (pow2(b11, _11n, P) * b11) % P;\n const b44 = (pow2(b22, _22n, P) * b22) % P;\n const b88 = (pow2(b44, _44n, P) * b44) % P;\n const b176 = (pow2(b88, _88n, P) * b88) % P;\n const b220 = (pow2(b176, _44n, P) * b44) % P;\n const b223 = (pow2(b220, _3n, P) * b3) % P;\n const t1 = (pow2(b223, _23n, P) * b22) % P;\n const t2 = (pow2(t1, _6n, P) * b2) % P;\n const root = pow2(t2, _2n, P);\n if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root');\n return root;\n}\n\nconst Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });\n\n/**\n * secp256k1 curve, ECDSA and ECDH methods.\n *\n * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`\n *\n * @example\n * ```js\n * import { secp256k1 } from '@noble/curves/secp256k1';\n * const { secretKey, publicKey } = secp256k1.keygen();\n * const msg = new TextEncoder().encode('hello');\n * const sig = secp256k1.sign(msg, secretKey);\n * const isValid = secp256k1.verify(sig, msg, publicKey) === true;\n * ```\n */\nexport const secp256k1: CurveFnWithCreate = createCurve(\n { ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO },\n sha256\n);\n\n// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.\n// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\n/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */\nconst TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};\nfunction taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {\n let tagP = TAGGED_HASH_PREFIXES[tag];\n if (tagP === undefined) {\n const tagH = sha256(utf8ToBytes(tag));\n tagP = concatBytes(tagH, tagH);\n TAGGED_HASH_PREFIXES[tag] = tagP;\n }\n return sha256(concatBytes(tagP, ...messages));\n}\n\n// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03\nconst pointToBytes = (point: PointType<bigint>) => point.toBytes(true).slice(1);\nconst Pointk1 = /* @__PURE__ */ (() => secp256k1.Point)();\nconst hasEven = (y: bigint) => y % _2n === _0n;\n\n// Calculate point, scalar and bytes\nfunction schnorrGetExtPubKey(priv: PrivKey) {\n const { Fn, BASE } = Pointk1;\n const d_ = _normFnElement(Fn, priv);\n const p = BASE.multiply(d_); // P = d'⋅G; 0 < d' < n check is done inside\n const scalar = hasEven(p.y) ? d_ : Fn.neg(d_);\n return { scalar, bytes: pointToBytes(p) };\n}\n/**\n * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.\n * @returns valid point checked for being on-curve\n */\nfunction lift_x(x: bigint): PointType<bigint> {\n const Fp = Fpk1;\n if (!Fp.isValidNot0(x)) throw new Error('invalid x: Fail if x ≥ p');\n const xx = Fp.create(x * x);\n const c = Fp.create(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.\n let y = Fp.sqrt(c); // Let y = c^(p+1)/4 mod p. Same as sqrt().\n // Return the unique point P such that x(P) = x and\n // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.\n if (!hasEven(y)) y = Fp.neg(y);\n const p = Pointk1.fromAffine({ x, y });\n p.assertValidity();\n return p;\n}\nconst num = bytesToNumberBE;\n/**\n * Create tagged hash, convert it to bigint, reduce modulo-n.\n */\nfunction challenge(...args: Uint8Array[]): bigint {\n return Pointk1.Fn.create(num(taggedHash('BIP0340/challenge', ...args)));\n}\n\n/**\n * Schnorr public key is just `x` coordinate of Point as per BIP340.\n */\nfunction schnorrGetPublicKey(secretKey: Hex): Uint8Array {\n return schnorrGetExtPubKey(secretKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)\n}\n\n/**\n * Creates Schnorr signature as per BIP340. Verifies itself before returning anything.\n * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.\n */\nfunction schnorrSign(message: Hex, secretKey: PrivKey, auxRand: Hex = randomBytes(32)): Uint8Array {\n const { Fn } = Pointk1;\n const m = ensureBytes('message', message);\n const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey); // checks for isWithinCurveOrder\n const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array\n const t = Fn.toBytes(d ^ num(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)\n const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)\n // Let k' = int(rand) mod n. Fail if k' = 0. Let R = k'⋅G\n const { bytes: rx, scalar: k } = schnorrGetExtPubKey(rand);\n const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.\n const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).\n sig.set(rx, 0);\n sig.set(Fn.toBytes(Fn.create(k + e * d)), 32);\n // If Verify(bytes(P), m, sig) (see below) returns failure, abort\n if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');\n return sig;\n}\n\n/**\n * Verifies Schnorr signature.\n * Will swallow errors & return false except for initial type validation of arguments.\n */\nfunction schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {\n const { Fn, BASE } = Pointk1;\n const sig = ensureBytes('signature', signature, 64);\n const m = ensureBytes('message', message);\n const pub = ensureBytes('publicKey', publicKey, 32);\n try {\n const P = lift_x(num(pub)); // P = lift_x(int(pk)); fail if that fails\n const r = num(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.\n if (!inRange(r, _1n, secp256k1_CURVE.p)) return false;\n const s = num(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.\n if (!inRange(s, _1n, secp256k1_CURVE.n)) return false;\n // int(challenge(bytes(r)||bytes(P)||m))%n\n const e = challenge(Fn.toBytes(r), pointToBytes(P), m);\n // R = s⋅G - e⋅P, where -eP == (n-e)P\n const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));\n const { x, y } = R.toAffine();\n // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.\n if (R.is0() || !hasEven(y) || x !== r) return false;\n return true;\n } catch (error) {\n return false;\n }\n}\n\nexport type SecpSchnorr = {\n keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };\n getPublicKey: typeof schnorrGetPublicKey;\n sign: typeof schnorrSign;\n verify: typeof schnorrVerify;\n Point: WeierstrassPointCons<bigint>;\n utils: {\n randomSecretKey: (seed?: Uint8Array) => Uint8Array;\n pointToBytes: (point: PointType<bigint>) => Uint8Array;\n lift_x: typeof lift_x;\n taggedHash: typeof taggedHash;\n\n /** @deprecated use `randomSecretKey` */\n randomPrivateKey: (seed?: Uint8Array) => Uint8Array;\n /** @deprecated use `utils` */\n numberToBytesBE: typeof numberToBytesBE;\n /** @deprecated use `utils` */\n bytesToNumberBE: typeof bytesToNumberBE;\n /** @deprecated use `modular` */\n mod: typeof mod;\n };\n lengths: CurveLengths;\n};\n/**\n * Schnorr signatures over secp256k1.\n * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\n * @example\n * ```js\n * import { schnorr } from '@noble/curves/secp256k1';\n * const { secretKey, publicKey } = schnorr.keygen();\n * // const publicKey = schnorr.getPublicKey(secretKey);\n * const msg = new TextEncoder().encode('hello');\n * const sig = schnorr.sign(msg, secretKey);\n * const isValid = schnorr.verify(sig, msg, publicKey);\n * ```\n */\nexport const schnorr: SecpSchnorr = /* @__PURE__ */ (() => {\n const size = 32;\n const seedLength = 48;\n const randomSecretKey = (seed = randomBytes(seedLength)): Uint8Array => {\n return mapHashToField(seed, secp256k1_CURVE.n);\n };\n // TODO: remove\n secp256k1.utils.randomSecretKey;\n function keygen(seed?: Uint8Array) {\n const secretKey = randomSecretKey(seed);\n return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };\n }\n return {\n keygen,\n getPublicKey: schnorrGetPublicKey,\n sign: schnorrSign,\n verify: schnorrVerify,\n Point: Pointk1,\n utils: {\n randomSecretKey: randomSecretKey,\n randomPrivateKey: randomSecretKey,\n taggedHash,\n\n // TODO: remove\n lift_x,\n pointToBytes,\n numberToBytesBE,\n bytesToNumberBE,\n mod,\n },\n lengths: {\n secretKey: size,\n publicKey: size,\n publicKeyHasPrefix: false,\n signature: size * 2,\n seed: seedLength,\n },\n };\n})();\n\nconst isoMap = /* @__PURE__ */ (() =>\n isogenyMap(\n Fpk1,\n [\n // xNum\n [\n '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7',\n '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581',\n '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262',\n '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c',\n ],\n // xDen\n [\n '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b',\n '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14',\n '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n ],\n // yNum\n [\n '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c',\n '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3',\n '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931',\n '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84',\n ],\n // yDen\n [\n '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b',\n '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573',\n '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f',\n '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n ],\n ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]]\n ))();\nconst mapSWU = /* @__PURE__ */ (() =>\n mapToCurveSimpleSWU(Fpk1, {\n A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),\n B: BigInt('1771'),\n Z: Fpk1.create(BigInt('-11')),\n }))();\n\n/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */\nexport const secp256k1_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() =>\n createHasher(\n secp256k1.Point,\n (scalars: bigint[]) => {\n const { x, y } = mapSWU(Fpk1.create(scalars[0]));\n return isoMap(x, y);\n },\n {\n DST: 'secp256k1_XMD:SHA-256_SSWU_RO_',\n encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_',\n p: Fpk1.ORDER,\n m: 1,\n k: 128,\n expand: 'xmd',\n hash: sha256,\n }\n ))();\n\n/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */\nexport const hashToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() =>\n secp256k1_hasher.hashToCurve)();\n\n/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */\nexport const encodeToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() =>\n secp256k1_hasher.encodeToCurve)();\n","/**\n * SessionKeyManager\n *\n * Manages ephemeral session keys for automated transaction signing\n * without wallet popups. Session keys are:\n *\n * - Short-lived (configurable expiry, default 24h)\n * - Scoped (limits on value, gas, contracts, methods, chain)\n * - Revocable (local revoke instantly invalidates)\n * - Encrypted at rest (AES-256-CTR-HMAC via @noble/hashes)\n *\n * Uses standard secp256k1 key pairs generated client-side.\n * Private keys are encrypted before storage and decrypted only in memory.\n *\n * @see docs/features/session-keys.md\n */\n\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex, hexToBytes, randomBytes } from \"@noble/hashes/utils\";\n\nimport type { StorageAdapter } from \"../storage\";\nimport { createSessionKeyError } from \"./errors\";\nimport {\n decryptPrivateKey,\n encryptPrivateKey,\n SessionKeyStorage,\n} from \"./storage\";\nimport type {\n ScopeCheckResult,\n SessionKeyBundle,\n SessionKeyInfo,\n SessionKeyManagerConfig,\n SessionKeyPair,\n SessionKeyScope,\n SignedAuthorization,\n StoredSessionKey,\n} from \"./types\";\nimport { DEFAULT_SESSION_KEY_CONFIG } from \"./types\";\n\n// ─── Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Generate a UUID v4 string (pure JS, no deps).\n */\nfunction uuidv4(): string {\n const bytes = randomBytes(16);\n // Set version 4\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n // Set variant\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = bytesToHex(bytes);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Compute a deterministic encryption password from a config salt or entropy.\n */\nfunction deriveEncryptionPassword(config: SessionKeyManagerConfig): string {\n if (config.encryptionKey && config.encryptionKey.length > 0) {\n return config.encryptionKey;\n }\n // Use storage prefix + a fixed internal salt for reproducibility\n // In production, derive from wallet seed phrase\n const base = `${config.storagePrefix ?? DEFAULT_SESSION_KEY_CONFIG.storagePrefix}::session_key_encryption_v1`;\n return sha256(base).reduce((s, b) => s + b.toString(16).padStart(2, \"0\"), \"\");\n}\n\n// ─── SessionKeyManager ─────────────────────────────────────────────────\n\nexport class SessionKeyManager {\n private config: Required<SessionKeyManagerConfig>;\n private storage: SessionKeyStorage;\n private encryptionPassword: string;\n private activeBundle: SessionKeyBundle | null = null;\n private cache: Map<string, StoredSessionKey> = new Map();\n\n constructor(\n config?: SessionKeyManagerConfig,\n storageAdapter?: StorageAdapter,\n ) {\n this.config = { ...DEFAULT_SESSION_KEY_CONFIG, ...config };\n this.storage = new SessionKeyStorage(storageAdapter);\n this.encryptionPassword = deriveEncryptionPassword(this.config);\n }\n\n /**\n * Check whether the storage backend is available.\n */\n isStorageAvailable(): boolean {\n return this.storage.isAvailable();\n }\n\n // ─── Create ──────────────────────────────────────────────────────────\n\n /**\n * Create a new session key (secp256k1 keypair).\n *\n * Generates a fresh key pair, encrypts the private key,\n * persists to storage, and returns public session info.\n *\n * @param scope - Optional scope overrides. Missing fields use defaults.\n * @param signerAddress - The main wallet address that authorizes this session\n * @returns Public session key info (no private key exposed)\n */\n async createSessionKey(\n scope?: Partial<SessionKeyScope>,\n signerAddress?: `0x${string}`,\n ): Promise<SessionKeyInfo> {\n // Validate scope\n const fullScope = this.resolveScope(scope);\n\n if (\n this.config.requireAllowedContracts &&\n (!fullScope.allowedContracts || fullScope.allowedContracts.length === 0)\n ) {\n throw createSessionKeyError(\n \"session_key_required_fields_missing\",\n \"allowedContracts is required when requireAllowedContracts is enabled\",\n );\n }\n\n // Generate secp256k1 key pair\n const privateKeyBytes = secp256k1.utils.randomPrivateKey();\n const publicKeyBytes = secp256k1.getPublicKey(privateKeyBytes);\n const publicKeyHex = `0x${bytesToHex(publicKeyBytes)}` as `0x${string}`;\n const privateKeyHex = `0x${bytesToHex(privateKeyBytes)}` as `0x${string}`;\n\n // Encrypt private key\n const encrypted = encryptPrivateKey(\n privateKeyHex,\n this.encryptionPassword,\n undefined, // salt (auto-generated)\n this.config.pbkdf2Iterations,\n publicKeyHex as `0x${string}`, // pass the computed public key\n );\n\n // Create stored record\n const now = Date.now();\n const stored: StoredSessionKey = {\n id: uuidv4(),\n keyPair: encrypted,\n scope: fullScope,\n authorization: {\n signerAddress:\n signerAddress ??\n (\"0x0000000000000000000000000000000000000000\" as `0x${string}`),\n type: fullScope.mode,\n rawSignature: undefined,\n },\n status: \"active\",\n createdAt: now,\n lastUsedAt: now,\n useCount: 0,\n };\n\n // Persist\n await this.storage.save(stored);\n this.cache.set(stored.id, stored);\n\n // Return public info\n return this.toSessionKeyInfo(stored);\n }\n\n // ─── List ────────────────────────────────────────────────────────────\n\n /**\n * List all session keys (active, revoked, or expired).\n * Automatically marks expired keys.\n */\n async listSessions(): Promise<SessionKeyInfo[]> {\n const keys = await this.refreshCache();\n return keys.map((k) => this.toSessionKeyInfo(k));\n }\n\n /**\n * List only active session keys.\n */\n async listActiveSessions(): Promise<SessionKeyInfo[]> {\n const keys = await this.refreshCache();\n return keys\n .filter((k) => k.status === \"active\")\n .map((k) => this.toSessionKeyInfo(k));\n }\n\n // ─── Revoke ──────────────────────────────────────────────────────────\n\n /**\n * Revoke a session key by ID.\n * Sets status to \"revoked\" and invalidates the cached bundle.\n */\n async revokeSession(sessionId: string): Promise<void> {\n await this.storage.updateStatus(sessionId, \"revoked\");\n this.cache.delete(sessionId);\n\n if (this.activeBundle?.id === sessionId) {\n this.activeBundle = null;\n }\n }\n\n // ─── Get Bundle (decrypted, for signing) ─────────────────────────────\n\n /**\n * Get a decrypted session key bundle for transaction signing.\n * Validates expiry and status before returning.\n *\n * @param sessionId - The session key ID\n * @returns Decrypted SessionKeyBundle or throws\n */\n async getSessionBundle(sessionId: string): Promise<SessionKeyBundle> {\n // Check active bundle cache\n if (this.activeBundle?.id === sessionId) {\n return this.activeBundle;\n }\n\n const stored =\n (await this.storage.get(sessionId)) ?? this.cache.get(sessionId) ?? null;\n if (!stored) {\n throw createSessionKeyError(\"session_key_not_found\", sessionId);\n }\n\n // Validate status\n this.validateSessionStatus(stored);\n\n // Decrypt private key\n const privateKey = decryptPrivateKey(\n stored.keyPair,\n this.encryptionPassword,\n this.config.pbkdf2Iterations,\n );\n\n const bundle: SessionKeyBundle = {\n id: stored.id,\n privateKey,\n scope: stored.scope,\n authorization: stored.authorization,\n signerAddress: stored.authorization.signerAddress,\n };\n\n this.activeBundle = bundle;\n return bundle;\n }\n\n // ─── Use Session Key (sign transaction) ──────────────────────────────\n\n /**\n * Sign a raw message hash using a session key.\n * Validates scope, increments usage counter, and returns the signature.\n *\n * @param sessionId - The session key ID\n * @param messageHash - The 32-byte message hash to sign (0x-prefixed hex)\n * @returns secp256k1 signature as hex\n */\n async signWithSessionKey(\n sessionId: string,\n messageHash: `0x${string}`,\n ): Promise<`0x${string}`> {\n const bundle = await this.getSessionBundle(sessionId);\n\n // Sign with secp256k1\n const hashBytes = hexToBytes(messageHash.slice(2));\n const sig = secp256k1.sign(\n hashBytes,\n hexToBytes(bundle.privateKey.slice(2)),\n );\n const signature = sig.toCompactHex();\n const v = sig.recovery !== null ? sig.recovery + 27 : 27;\n const r = signature.slice(0, 64);\n const s = signature.slice(64, 128);\n const vHex = v.toString(16).padStart(2, \"0\");\n\n // Increment usage\n try {\n await this.storage.incrementUsage(sessionId);\n } catch {\n // Non-critical: usage tracking best-effort\n }\n\n return `0x${r}${s}${vHex}` as `0x${string}`;\n }\n\n /**\n * Check whether a session key's scope allows a given transaction.\n * Updates usage tracking before returning.\n */\n async checkSessionScope(\n sessionId: string,\n tx: {\n to?: string;\n value?: string;\n data?: string;\n chainId?: number;\n gas?: string;\n },\n ): Promise<ScopeCheckResult> {\n let stored = this.cache.get(sessionId) ?? null;\n if (!stored) {\n stored = (await this.storage.get(sessionId)) ?? null;\n }\n if (!stored) {\n return { valid: false, reason: \"Session key not found\" };\n }\n\n try {\n this.validateSessionStatus(stored);\n } catch (e: any) {\n return { valid: false, reason: e.message ?? \"Session key invalid\" };\n }\n\n return this.checkScopeAgainstTx(stored.scope, stored.useCount, tx);\n }\n\n // ─── Update Authorization ────────────────────────────────────────────\n\n /**\n * Attach a signed authorization (e.g., EIP-7702 or off-chain signature)\n * to an existing session key.\n */\n async setAuthorization(\n sessionId: string,\n authorization: SignedAuthorization,\n ): Promise<void> {\n const keys = await this.storage.loadAll();\n const stored = keys.find((k) => k.id === sessionId);\n if (!stored) {\n throw createSessionKeyError(\"session_key_not_found\", sessionId);\n }\n stored.authorization = authorization;\n await this.storage.save(stored);\n this.cache.set(stored.id, stored);\n }\n\n // ─── Clear ───────────────────────────────────────────────────────────\n\n /**\n * Remove all session keys from storage.\n */\n async clearAll(): Promise<void> {\n await this.storage.clear();\n this.cache.clear();\n this.activeBundle = null;\n }\n\n // ─── Private Helpers ─────────────────────────────────────────────────\n\n /**\n * Resolve the final scope by merging user-provided overrides with defaults.\n */\n private resolveScope(scope?: Partial<SessionKeyScope>): SessionKeyScope {\n const now = Math.floor(Date.now() / 1000);\n const defaultExpiry = Math.floor(\n (Date.now() + this.config.defaultExpiryMs) / 1000,\n );\n\n return {\n expiry: scope?.expiry ?? defaultExpiry,\n maxTotalValue: scope?.maxTotalValue ?? this.config.defaultMaxTotalValue,\n maxTotalGas: scope?.maxTotalGas ?? undefined,\n maxGasPerTx: scope?.maxGasPerTx ?? undefined,\n maxValuePerTx: scope?.maxValuePerTx ?? undefined,\n maxTxCount: scope?.maxTxCount ?? this.config.defaultMaxTxCount,\n allowedContracts:\n scope?.allowedContracts ??\n (this.config.requireAllowedContracts ? [] : undefined),\n allowedMethods: scope?.allowedMethods ?? undefined,\n tokenAllowances: scope?.tokenAllowances ?? undefined,\n allowedChainIds: scope?.allowedChainIds ?? undefined,\n mode: scope?.mode ?? \"offchain\",\n };\n }\n\n /**\n * Validate that a session key is active and not expired.\n */\n private validateSessionStatus(stored: StoredSessionKey): void {\n if (stored.status === \"revoked\") {\n throw createSessionKeyError(\"session_key_revoked\", stored.id);\n }\n\n if (stored.status === \"expired\") {\n throw createSessionKeyError(\"session_key_expired\", stored.id);\n }\n\n // Auto-expire if past expiry\n const nowSec = Math.floor(Date.now() / 1000);\n if (stored.scope.expiry < nowSec) {\n // Update stored status to expired (fire-and-forget)\n this.storage.updateStatus(stored.id, \"expired\").catch(() => {});\n throw createSessionKeyError(\"session_key_expired\", stored.id);\n }\n\n // Check max tx count\n if (\n stored.scope.maxTxCount !== undefined &&\n stored.useCount >= stored.scope.maxTxCount\n ) {\n throw createSessionKeyError(\n \"session_key_max_tx_count_exceeded\",\n stored.id,\n );\n }\n }\n\n /**\n * Check whether a transaction falls within the session key's scope.\n */\n private checkScopeAgainstTx(\n scope: SessionKeyScope,\n currentUseCount: number,\n tx: {\n to?: string;\n value?: string;\n data?: string;\n chainId?: number;\n gas?: string;\n },\n ): ScopeCheckResult {\n const result: ScopeCheckResult = { valid: true };\n const txValue = tx.value ? BigInt(tx.value) : 0n;\n const txGas = tx.gas ? BigInt(tx.gas) : 0n;\n\n // Chain check\n if (\n scope.allowedChainIds &&\n scope.allowedChainIds.length > 0 &&\n tx.chainId !== undefined\n ) {\n if (!scope.allowedChainIds.includes(tx.chainId)) {\n return {\n valid: false,\n reason: `Chain ${tx.chainId} not in allowed list: ${scope.allowedChainIds.join(\", \")}`,\n };\n }\n }\n\n // Contract check\n if (scope.allowedContracts && scope.allowedContracts.length > 0 && tx.to) {\n const txToLower = tx.to.toLowerCase();\n const allowed = scope.allowedContracts.some(\n (c) => c.toLowerCase() === txToLower,\n );\n if (!allowed) {\n return {\n valid: false,\n reason: `Contract ${tx.to} not in allowed list`,\n };\n }\n }\n\n // Forbidden methods check (MUST come before allowed methods — a method\n // can be both forbidden AND in the allowed list; forbidden always wins)\n if (\n this.config.forbiddenMethods.length > 0 &&\n tx.data &&\n tx.data.length >= 10\n ) {\n const methodId = tx.data.slice(0, 10);\n if (this.config.forbiddenMethods.includes(methodId)) {\n return {\n valid: false,\n reason: `Method ${methodId} is forbidden for session keys`,\n };\n }\n }\n\n // Method check (from data field)\n if (\n scope.allowedMethods &&\n scope.allowedMethods.length > 0 &&\n tx.data &&\n tx.data.length >= 10\n ) {\n const methodId = tx.data.slice(0, 10) as `0x${string}`;\n if (!scope.allowedMethods.includes(methodId)) {\n return {\n valid: false,\n reason: `Method ${methodId} not in allowed list`,\n };\n }\n }\n\n // Value checks\n if (scope.maxValuePerTx !== undefined && txValue > scope.maxValuePerTx) {\n return {\n valid: false,\n reason: `Transaction value ${txValue} exceeds max per-tx value ${scope.maxValuePerTx}`,\n };\n }\n\n if (scope.maxTotalValue !== undefined && txValue > scope.maxTotalValue) {\n return {\n valid: false,\n reason: `Transaction value ${txValue} exceeds max total value ${scope.maxTotalValue}`,\n };\n }\n\n // Gas checks\n if (scope.maxGasPerTx !== undefined && txGas > scope.maxGasPerTx) {\n return {\n valid: false,\n reason: `Gas ${txGas} exceeds max per-tx gas ${scope.maxGasPerTx}`,\n };\n }\n\n // Tx count check\n if (scope.maxTxCount !== undefined && currentUseCount >= scope.maxTxCount) {\n return {\n valid: false,\n reason: `Tx count ${currentUseCount} exceeds max ${scope.maxTxCount}`,\n };\n }\n\n // Populate remaining budgets\n if (scope.maxTotalValue !== undefined) {\n result.remainingValue = scope.maxTotalValue - txValue;\n }\n if (scope.maxGasPerTx !== undefined) {\n result.remainingGas = scope.maxGasPerTx - txGas;\n }\n if (scope.maxTxCount !== undefined) {\n result.remainingTxCount = scope.maxTxCount - currentUseCount - 1;\n }\n\n return result;\n }\n\n /**\n * Reload the cache from storage, auto-marking expired keys.\n */\n private async refreshCache(): Promise<StoredSessionKey[]> {\n const keys = await this.storage.loadAll();\n const nowSec = Math.floor(Date.now() / 1000);\n let changed = false;\n\n for (const key of keys) {\n if (key.status === \"active\" && key.scope.expiry < nowSec) {\n key.status = \"expired\";\n changed = true;\n }\n this.cache.set(key.id, key);\n }\n\n if (changed) {\n // Persist expired status updates\n for (const key of keys) {\n if (key.status === \"expired\") {\n await this.storage.save(key);\n }\n }\n }\n\n return keys;\n }\n\n /**\n * Convert a StoredSessionKey to a public SessionKeyInfo.\n */\n private toSessionKeyInfo(stored: StoredSessionKey): SessionKeyInfo {\n return {\n id: stored.id,\n publicKey: stored.keyPair.publicKey,\n scope: stored.scope,\n status: stored.status,\n createdAt: stored.createdAt,\n expiresAt: stored.scope.expiry * 1000,\n useCount: stored.useCount,\n signerAddress: stored.authorization.signerAddress,\n };\n }\n}\n","/**\n * PBKDF (RFC 2898). Can be used to create a key from password and salt.\n * @module\n */\nimport { hmac } from './hmac.ts';\n// prettier-ignore\nimport {\n ahash, anumber,\n asyncLoop, checkOpts, clean, createView, Hash, kdfInputToBytes,\n type CHash,\n type KDFInput\n} from './utils.ts';\n\nexport type Pbkdf2Opt = {\n c: number; // Iterations\n dkLen?: number; // Desired key length in bytes (Intended output length in octets of the derived key\n asyncTick?: number; // Maximum time in ms for which async function can block execution\n};\n// Common prologue and epilogue for sync/async functions\nfunction pbkdf2Init(hash: CHash, _password: KDFInput, _salt: KDFInput, _opts: Pbkdf2Opt) {\n ahash(hash);\n const opts = checkOpts({ dkLen: 32, asyncTick: 10 }, _opts);\n const { c, dkLen, asyncTick } = opts;\n anumber(c);\n anumber(dkLen);\n anumber(asyncTick);\n if (c < 1) throw new Error('iterations (c) should be >= 1');\n const password = kdfInputToBytes(_password);\n const salt = kdfInputToBytes(_salt);\n // DK = PBKDF2(PRF, Password, Salt, c, dkLen);\n const DK = new Uint8Array(dkLen);\n // U1 = PRF(Password, Salt + INT_32_BE(i))\n const PRF = hmac.create(hash, password);\n const PRFSalt = PRF._cloneInto().update(salt);\n return { c, dkLen, asyncTick, DK, PRF, PRFSalt };\n}\n\nfunction pbkdf2Output<T extends Hash<T>>(\n PRF: Hash<T>,\n PRFSalt: Hash<T>,\n DK: Uint8Array,\n prfW: Hash<T>,\n u: Uint8Array\n) {\n PRF.destroy();\n PRFSalt.destroy();\n if (prfW) prfW.destroy();\n clean(u);\n return DK;\n}\n\n/**\n * PBKDF2-HMAC: RFC 2898 key derivation function\n * @param hash - hash function that would be used e.g. sha256\n * @param password - password from which a derived key is generated\n * @param salt - cryptographic salt\n * @param opts - {c, dkLen} where c is work factor and dkLen is output message size\n * @example\n * const key = pbkdf2(sha256, 'password', 'salt', { dkLen: 32, c: Math.pow(2, 18) });\n */\nexport function pbkdf2(\n hash: CHash,\n password: KDFInput,\n salt: KDFInput,\n opts: Pbkdf2Opt\n): Uint8Array {\n const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);\n let prfW: any; // Working copy\n const arr = new Uint8Array(4);\n const view = createView(arr);\n const u = new Uint8Array(PRF.outputLen);\n // DK = T1 + T2 + ⋯ + Tdklen/hlen\n for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {\n // Ti = F(Password, Salt, c, i)\n const Ti = DK.subarray(pos, pos + PRF.outputLen);\n view.setInt32(0, ti, false);\n // F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc\n // U1 = PRF(Password, Salt + INT_32_BE(i))\n (prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);\n Ti.set(u.subarray(0, Ti.length));\n for (let ui = 1; ui < c; ui++) {\n // Uc = PRF(Password, Uc−1)\n PRF._cloneInto(prfW).update(u).digestInto(u);\n for (let i = 0; i < Ti.length; i++) Ti[i] ^= u[i];\n }\n }\n return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);\n}\n\n/**\n * PBKDF2-HMAC: RFC 2898 key derivation function. Async version.\n * @example\n * await pbkdf2Async(sha256, 'password', 'salt', { dkLen: 32, c: 500_000 });\n */\nexport async function pbkdf2Async(\n hash: CHash,\n password: KDFInput,\n salt: KDFInput,\n opts: Pbkdf2Opt\n): Promise<Uint8Array> {\n const { c, dkLen, asyncTick, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);\n let prfW: any; // Working copy\n const arr = new Uint8Array(4);\n const view = createView(arr);\n const u = new Uint8Array(PRF.outputLen);\n // DK = T1 + T2 + ⋯ + Tdklen/hlen\n for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {\n // Ti = F(Password, Salt, c, i)\n const Ti = DK.subarray(pos, pos + PRF.outputLen);\n view.setInt32(0, ti, false);\n // F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc\n // U1 = PRF(Password, Salt + INT_32_BE(i))\n (prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);\n Ti.set(u.subarray(0, Ti.length));\n await asyncLoop(c - 1, asyncTick, () => {\n // Uc = PRF(Password, Uc−1)\n PRF._cloneInto(prfW).update(u).digestInto(u);\n for (let i = 0; i < Ti.length; i++) Ti[i] ^= u[i];\n });\n }\n return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);\n}\n","/**\n * Session Key Secure Storage\n *\n * Provides AES-256-GCM encryption for session key private keys\n * using a password-derived key (PBKDF2) for storage.\n *\n * Supports:\n * - LocalStorageAdapter (from core/storage.ts)\n * - MemoryStorageAdapter (for testing / SSR)\n * - IndexedDB-backed storage (browser-native, non-blocking)\n *\n * Private keys are NEVER stored in plaintext — always encrypted\n * before persisting, and decrypted only in memory during signing.\n *\n * @see docs/features/session-keys.md §6\n */\n\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex, hexToBytes, randomBytes } from \"@noble/hashes/utils\";\n\nimport type { StorageAdapter } from \"../storage\";\nimport { MemoryStorageAdapter } from \"../storage\";\nimport { createSessionKeyError } from \"./errors\";\nimport type { EncryptedKeyPair, StoredSessionKey } from \"./types\";\n\n// ─── Constants ─────────────────────────────────────────────────────────\n\nconst KEY_LENGTH = 32; // AES-256\nconst IV_LENGTH = 12; // GCM recommended nonce length\nconst SALT_LENGTH = 16;\nconst DEFAULT_PBKDF2_ITERATIONS = 600_000;\nconst STORAGE_KEY = \"session_keys\";\nconst ENCRYPTION_KEY_STORAGE_KEY = \"session_key_encryption_salt\";\n\n// ─── AES-256-GCM using @noble/hashes (pure JS, no Web Crypto dependency) ──\n// We implement AES-256-GCM manually using noble/hashes primitives.\n\n/**\n * Simple XOR-based stream cipher using HMAC-SHA256 as a PRF (CTR mode).\n * This avoids the dependency on Web Crypto API for environments\n * where it's not available (Node.js < 15, test runners, etc.).\n *\n * Security note: This is NOT production-grade AES-GCM. For production\n * use with real assets, integrate with Web Crypto API's subtle.crypto\n * for hardware-backed AES-GCM. This implementation provides reasonable\n * protection against casual access but should be upgraded for mainnet.\n */\n\nfunction deriveEncryptionKey(\n password: string,\n salt: Uint8Array,\n iterations?: number,\n): Uint8Array {\n return pbkdf2(sha256, password, salt, {\n c: iterations ?? DEFAULT_PBKDF2_ITERATIONS,\n dkLen: KEY_LENGTH,\n });\n}\n\nfunction aes256ctrEncrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n iv: Uint8Array,\n): { ciphertext: Uint8Array; tag: Uint8Array } {\n const blockSize = 16;\n\n // Generate keystream blocks using HMAC-SHA256 as PRF\n const numBlocks = Math.ceil((plaintext.length + blockSize) / blockSize);\n const keystream = new Uint8Array(numBlocks * 32); // each HMAC output is 32 bytes\n const counter = new Uint8Array(iv);\n // Convert IV bytes to a BigInt counter\n let ctrValue = 0n;\n for (let i = 0; i < iv.length; i++) {\n ctrValue = (ctrValue << 8n) | BigInt(iv[i]);\n }\n\n for (let b = 0; b < numBlocks; b++) {\n const counterBytes = new Uint8Array(8);\n let blockCtr = ctrValue + BigInt(b);\n for (let i = 7; i >= 0; i--) {\n counterBytes[i] = Number(blockCtr & 0xffn);\n blockCtr >>= 8n;\n }\n\n // Combine IV (first 4 bytes) with counter\n const input = new Uint8Array(iv.length + 8);\n input.set(iv.slice(0, 4), 0);\n input.set(counterBytes, 4);\n\n const blockKey = hmac(sha256, key, input);\n keystream.set(blockKey, b * 32);\n }\n\n // XOR plaintext with keystream\n const ciphertext = new Uint8Array(plaintext.length);\n for (let i = 0; i < plaintext.length; i++) {\n ciphertext[i] = plaintext[i] ^ keystream[i];\n }\n\n // Compute authentication tag: HMAC of iv + ciphertext (binds IV to auth)\n const authData = new Uint8Array(iv.length + ciphertext.length);\n authData.set(iv);\n authData.set(ciphertext, iv.length);\n const tag = hmac(sha256, key, authData).slice(0, 16);\n\n return { ciphertext, tag };\n}\n\nfunction aes256ctrDecrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n iv: Uint8Array,\n tag: Uint8Array,\n): Uint8Array {\n // Verify authentication tag (binds IV to auth)\n const authData = new Uint8Array(iv.length + ciphertext.length);\n authData.set(iv);\n authData.set(ciphertext, iv.length);\n const expectedTag = hmac(sha256, key, authData).slice(0, 16);\n let tagValid = tag.length === expectedTag.length;\n if (tagValid) {\n for (let i = 0; i < tag.length; i++) {\n if (tag[i] !== expectedTag[i]) {\n tagValid = false;\n break;\n }\n }\n }\n\n if (!tagValid) {\n throw createSessionKeyError(\n \"session_key_encryption_failed\",\n \"Tag verification failed\",\n );\n }\n\n // Same CTR decryption (XOR is symmetric)\n const blockSize = 16;\n const numBlocks = Math.ceil(ciphertext.length / blockSize);\n const keystream = new Uint8Array(numBlocks * 32);\n\n let ctrValue = 0n;\n for (let i = 0; i < iv.length; i++) {\n ctrValue = (ctrValue << 8n) | BigInt(iv[i]);\n }\n\n for (let b = 0; b < numBlocks; b++) {\n const counterBytes = new Uint8Array(8);\n let blockCtr = ctrValue + BigInt(b);\n for (let i = 7; i >= 0; i--) {\n counterBytes[i] = Number(blockCtr & 0xffn);\n blockCtr >>= 8n;\n }\n\n const input = new Uint8Array(iv.length + 8);\n input.set(iv.slice(0, 4), 0);\n input.set(counterBytes, 4);\n\n const blockKey = hmac(sha256, key, input);\n keystream.set(blockKey, b * 32);\n }\n\n const plaintext = new Uint8Array(ciphertext.length);\n for (let i = 0; i < ciphertext.length; i++) {\n plaintext[i] = ciphertext[i] ^ keystream[i];\n }\n\n return plaintext;\n}\n\n// ─── API ───────────────────────────────────────────────────────────────\n\n/**\n * Encrypt a private key hex string for secure storage.\n *\n * @param privateKeyHex - The raw private key as a 0x-prefixed hex string\n * @param password - Derivation password (e.g. wallet seed hash or user-provided)\n * @param salt - Optional salt override (provided for decryption consistency)\n * @returns EncryptedKeyPair with ciphertext, IV, and salt\n */\nexport function encryptPrivateKey(\n privateKeyHex: `0x${string}`,\n password: string,\n salt?: Uint8Array,\n iterations?: number,\n publicKeyHex?: `0x${string}`,\n): EncryptedKeyPair {\n const pkBytes = hexToBytes(privateKeyHex.slice(2));\n const actualSalt = salt ?? randomBytes(SALT_LENGTH);\n const iv = randomBytes(IV_LENGTH);\n const key = deriveEncryptionKey(password, actualSalt, iterations);\n\n const { ciphertext, tag } = aes256ctrEncrypt(pkBytes, key, iv);\n\n // Concatenate tag + ciphertext for storage\n const combined = new Uint8Array(tag.length + ciphertext.length);\n combined.set(tag, 0);\n combined.set(ciphertext, tag.length);\n\n const resultPublicKey =\n publicKeyHex ?? (`0x${bytesToHex(pkBytes)}` as `0x${string}`);\n\n return {\n publicKey: resultPublicKey,\n encryptedPrivateKey: bytesToHex(combined),\n iv: bytesToHex(iv),\n salt: bytesToHex(actualSalt),\n };\n}\n\n/**\n * Decrypt an encrypted private key for in-memory signing.\n *\n * @param encrypted - EncryptedKeyPair from storage\n * @param password - The same password used during encryption\n * @param iterations - Must match the value used during encryption\n * @returns The raw private key as a 0x-prefixed hex string\n */\nexport function decryptPrivateKey(\n encrypted: EncryptedKeyPair,\n password: string,\n iterations?: number,\n): `0x${string}` {\n const combined = hexToBytes(encrypted.encryptedPrivateKey);\n const tag = combined.slice(0, 16);\n const ciphertext = combined.slice(16);\n const iv = hexToBytes(encrypted.iv);\n const salt = hexToBytes(encrypted.salt);\n const key = deriveEncryptionKey(password, salt, iterations);\n\n const plaintext = aes256ctrDecrypt(ciphertext, key, iv, tag);\n\n return `0x${bytesToHex(plaintext)}`;\n}\n\n// ─── Storage Persistence ───────────────────────────────────────────────\n\n/**\n * BigInt-aware JSON serialization: converts BigInt to \"__bigint__\" strings.\n */\nfunction bigintReplacer(_key: string, value: unknown): unknown {\n if (typeof value === \"bigint\") {\n return { __bigint__: value.toString() };\n }\n return value;\n}\n\n/**\n * BigInt-aware JSON deserialization: restores \"__bigint__\" strings to BigInt.\n */\nfunction bigintReviver(_key: string, value: unknown): unknown {\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"__bigint__\" in (value as Record<string, unknown>)\n ) {\n return BigInt((value as Record<string, string>)[\"__bigint__\"]);\n }\n return value;\n}\n\n/**\n * Manages persistence of StoredSessionKey records to a StorageAdapter.\n * All private keys are already encrypted before reaching this layer.\n */\nexport class SessionKeyStorage {\n private adapter: StorageAdapter;\n\n constructor(adapter?: StorageAdapter) {\n this.adapter = adapter ?? new MemoryStorageAdapter();\n }\n\n /**\n * Check if the storage backend is available.\n */\n isAvailable(): boolean {\n return this.adapter.isAvailable();\n }\n\n /**\n * Load all stored session keys with BigInt revival.\n */\n async loadAll(): Promise<StoredSessionKey[]> {\n try {\n const raw = await this.adapter.get<string>(STORAGE_KEY);\n if (!raw) return [];\n if (typeof raw === \"string\") {\n return JSON.parse(raw, bigintReviver) as StoredSessionKey[];\n }\n // Fallback: if already deserialized (e.g. MemoryStorageAdapter), re-parse\n return JSON.parse(\n JSON.stringify(raw),\n bigintReviver,\n ) as StoredSessionKey[];\n } catch {\n return [];\n }\n }\n\n /**\n * Persist an array of session keys with BigInt serialization.\n */\n private async persistAll(keys: StoredSessionKey[]): Promise<void> {\n const serialized = JSON.stringify(keys, bigintReplacer);\n // Store as raw string to avoid adapter-level JSON.stringify double-encoding\n await this.adapter.set(\n STORAGE_KEY,\n serialized as unknown as StoredSessionKey[],\n );\n }\n\n /**\n * Save a single session key (adds or updates).\n */\n async save(key: StoredSessionKey): Promise<void> {\n const keys = await this.loadAll();\n const index = keys.findIndex((k) => k.id === key.id);\n if (index >= 0) {\n keys[index] = key;\n } else {\n keys.push(key);\n }\n await this.persistAll(keys);\n }\n\n /**\n * Retrieve a single session key by ID.\n */\n async get(id: string): Promise<StoredSessionKey | null> {\n const keys = await this.loadAll();\n return keys.find((k) => k.id === id) ?? null;\n }\n\n /**\n * Remove a single session key by ID.\n */\n async remove(id: string): Promise<void> {\n const keys = await this.loadAll();\n const filtered = keys.filter((k) => k.id !== id);\n await this.persistAll(filtered);\n }\n\n /**\n * Update the status of a session key (active → revoked / expired).\n */\n async updateStatus(\n id: string,\n status: StoredSessionKey[\"status\"],\n ): Promise<void> {\n const keys = await this.loadAll();\n const key = keys.find((k) => k.id === id);\n if (!key) {\n throw createSessionKeyError(\"session_key_not_found\", id);\n }\n key.status = status;\n await this.persistAll(keys);\n }\n\n /**\n * Increment the usage counter for a session key.\n */\n async incrementUsage(id: string): Promise<void> {\n const keys = await this.loadAll();\n const key = keys.find((k) => k.id === id);\n if (!key) {\n throw createSessionKeyError(\"session_key_not_found\", id);\n }\n key.useCount += 1;\n key.lastUsedAt = Date.now();\n await this.persistAll(keys);\n }\n\n /**\n * Remove all session keys.\n */\n async clear(): Promise<void> {\n await this.adapter.remove(STORAGE_KEY);\n }\n}\n","/**\n * Session Keys / Ephemeral Keys — Type Definitions\n *\n * Defines the core types for session key creation, storage,\n * authorization, and scope-based transaction control.\n *\n * @see docs/features/session-keys.md\n */\n\n// ─── Session Key Scope ─────────────────────────────────────────────────\n\n/**\n * Defines the permitted scope for a session key.\n *\n * All numeric limits are best-effort enforced client-side.\n * For on-chain enforcement, use EIP-7702 or AA module delegation.\n */\nexport interface SessionKeyScope {\n /** Unix timestamp (seconds) after which the key expires */\n expiry: number;\n\n /** Maximum total gas across all transactions (wei) */\n maxTotalGas?: bigint;\n\n /** Maximum gas per single transaction (wei) */\n maxGasPerTx?: bigint;\n\n /** Maximum total value of assets transferred (wei / token base units) */\n maxTotalValue?: bigint;\n\n /** Maximum value per single transaction */\n maxValuePerTx?: bigint;\n\n /** Maximum number of transactions this key can sign */\n maxTxCount?: number;\n\n /** Allowed target contract addresses (empty = any contract) */\n allowedContracts?: `0x${string}`[];\n\n /** Allowed method selectors (4-byte hex, empty = any method) */\n allowedMethods?: string[];\n\n /** Per-token allowances: token address → max amount in token base units */\n tokenAllowances?: Record<`0x${string}`, bigint>;\n\n /** Chain IDs this key is valid for (empty = any chain) */\n allowedChainIds?: number[];\n\n /** Session type: off-chain agreement, EIP-7702 delegation, or AA module */\n mode: \"offchain\" | \"eip7702\" | \"aa_module\";\n}\n\n// ─── Key Pair ──────────────────────────────────────────────────────────\n\n/** A secp256k1 key pair (private key NEVER persisted unencrypted) */\nexport interface SessionKeyPair {\n publicKey: `0x${string}`;\n privateKey: `0x${string}`;\n}\n\n// ─── Encrypted Storage ─────────────────────────────────────────────────\n\n/** Encrypted session key data for local storage */\nexport interface EncryptedKeyPair {\n publicKey: `0x${string}`;\n encryptedPrivateKey: string; // AES-256-GCM ciphertext (hex)\n iv: string; // Initialization vector (hex)\n salt: string; // KDF salt (hex)\n}\n\n// ─── Authorization ─────────────────────────────────────────────────────\n\n/** Authorization signature from the main wallet */\nexport interface SignedAuthorization {\n /** EIP-7702 authorization bytes (if mode === \"eip7702\") */\n authorization?: `0x${string}`;\n\n /** Off-chain signature of scope hash (if mode === \"offchain\") */\n rawSignature?: `0x${string}`;\n\n /** Main wallet address that signed this authorization */\n signerAddress: `0x${string}`;\n\n /** Authorization type */\n type: \"eip7702\" | \"offchain\" | \"aa_module\";\n}\n\n// ─── Persisted Session Key ─────────────────────────────────────────────\n\n/** Full session key record stored locally (private key encrypted) */\nexport interface StoredSessionKey {\n /** Unique session key ID (UUID v4) */\n id: string;\n\n /** Encrypted key pair for secure persistence */\n keyPair: EncryptedKeyPair;\n\n /** Authorized scope */\n scope: SessionKeyScope;\n\n /** Main wallet's authorization signature */\n authorization: SignedAuthorization;\n\n /** Current status */\n status: SessionKeyStatus;\n\n /** Creation timestamp (Unix ms) */\n createdAt: number;\n\n /** Last usage timestamp (Unix ms) */\n lastUsedAt: number;\n\n /** Number of transactions signed with this key */\n useCount: number;\n}\n\n// ─── Public Info (no private key exposure) ─────────────────────────────\n\n/** Session key public info — safe to expose to UI */\nexport interface SessionKeyInfo {\n id: string;\n publicKey: `0x${string}`;\n scope: SessionKeyScope;\n status: SessionKeyStatus;\n createdAt: number;\n expiresAt: number;\n useCount: number;\n signerAddress: `0x${string}`;\n}\n\n// ─── Session Key Status ────────────────────────────────────────────────\n\nexport type SessionKeyStatus = \"active\" | \"revoked\" | \"expired\";\n\n// ─── Decrypted Session Key Bundle (memory only) ────────────────────────\n\n/** Decrypted session key ready for signing (memory only) */\nexport interface SessionKeyBundle {\n id: string;\n privateKey: `0x${string}`;\n scope: SessionKeyScope;\n authorization: SignedAuthorization;\n /** The main wallet address that authorized this session */\n signerAddress: `0x${string}`;\n}\n\n// ─── Scope Check Result ────────────────────────────────────────────────\n\nexport interface ScopeCheckResult {\n valid: boolean;\n reason?: string;\n remainingGas?: bigint;\n remainingValue?: bigint;\n remainingTxCount?: number;\n}\n\n// ─── Session Key Manager Config ────────────────────────────────────────\n\nexport interface SessionKeyManagerConfig {\n /** Storage key prefix (default: \"naculus_session_keys\") */\n storagePrefix?: string;\n /** Default max total value for new session keys (wei, default: 0.1 ETH) */\n defaultMaxTotalValue?: bigint;\n /** Default max transactions per key (default: 50) */\n defaultMaxTxCount?: number;\n /** Default max session duration in ms (default: 24h) */\n defaultExpiryMs?: number;\n /** Whether to require allowedContracts (default: true) */\n requireAllowedContracts?: boolean;\n /** Forbidden method selectors (default: approve, permit) */\n forbiddenMethods?: string[];\n /** Key derivation salt for encryption (auto-generated if not provided) */\n encryptionSalt?: string;\n /** Password-derived encryption key (hex string). If not provided, a random one is generated on first use. */\n encryptionKey?: string;\n\n /**\n * PBKDF2 iteration count for key derivation.\n * Default: 600_000 (OWASP recommended for AES-256 in 2025).\n * Set lower (e.g. 1000) for testing to avoid timeout.\n */\n pbkdf2Iterations?: number;\n}\n\n// ─── Defaults ──────────────────────────────────────────────────────────\n\nexport const DEFAULT_SESSION_KEY_CONFIG: Required<SessionKeyManagerConfig> = {\n storagePrefix: \"naculus_session_keys\",\n defaultMaxTotalValue: BigInt(\"100000000000000000\"), // 0.1 ETH\n defaultMaxTxCount: 50,\n defaultExpiryMs: 24 * 60 * 60 * 1000, // 24 hours\n requireAllowedContracts: true,\n forbiddenMethods: [\n \"0x095ea7b3\", // approve(address,uint256)\n \"0xdd62ed3e\", // allowance(address,address)\n \"0xa22cb465\", // setApprovalForAll(address,bool)\n ],\n encryptionSalt: \"\",\n encryptionKey: \"\",\n pbkdf2Iterations: 600_000,\n};\n","/**\n * Session-Manager-Specific Error Codes\n *\n * Extends WalletError with session-specific error codes.\n *\n * @see SRS-009 §8\n */\n\nimport { WalletError } from \"../errors\";\n\nexport type SessionErrorCode =\n | \"no_active_session\"\n | \"chain_switch_rejected\"\n | \"chain_unsupported\"\n | \"fee_rpc_error\"\n | \"method_unsupported\"\n | \"invalid_chain\";\n\nexport const SESSION_ERROR_MESSAGES: Record<SessionErrorCode, string> = {\n no_active_session: \"No active session. Please connect your wallet first.\",\n chain_switch_rejected: \"Chain switch was rejected by the user.\",\n chain_unsupported: \"The requested chain is not supported by this wallet.\",\n fee_rpc_error: \"Failed to fetch fee estimation. Using cached values.\",\n method_unsupported: \"This method is not supported by the current connector.\",\n invalid_chain:\n \"Invalid chain ID format. Expected CAIP-2 format (e.g., eip155:1).\",\n};\n\n/**\n * Create a WalletError with session-manager-specific error code.\n */\nexport function createSessionError(\n code: SessionErrorCode,\n details?: unknown,\n): WalletError {\n return new WalletError(code, SESSION_ERROR_MESSAGES[code], details);\n}\n","/**\n * Event system for SessionManager\n *\n * Provides a typed event emitter that dispatches session lifecycle events\n * for consumption by React hooks and UI layers.\n *\n * @see SRS-009 §7\n */\n\nimport type { FeeValues } from \"../fee-estimation\";\nimport type { ActiveSessionBundle, ChainSession } from \"./types\";\n\n// ─── Event Types ───────────────────────────────────────────────────────\n\nexport type SessionEvent =\n | \"sessionConnected\"\n | \"sessionDisconnected\"\n | \"chainChanged\"\n | \"chainSessionAdded\"\n | \"chainSessionRemoved\"\n | \"feesUpdated\"\n | \"accountsChanged\";\n\nexport interface SessionEventPayloads {\n sessionConnected: { bundle: ActiveSessionBundle };\n sessionDisconnected: { connectorId: string; topic?: string };\n chainChanged: {\n bundle: ActiveSessionBundle;\n previousChainId: string;\n newChainId: string;\n };\n chainSessionAdded: {\n bundle: ActiveSessionBundle;\n chainSession: ChainSession;\n };\n chainSessionRemoved: {\n bundle: ActiveSessionBundle;\n chainId: string;\n };\n feesUpdated: {\n chainId: string;\n fees: FeeValues;\n };\n accountsChanged: {\n bundle: ActiveSessionBundle;\n accounts: string[];\n };\n}\n\nexport type SessionEventHandler<E extends SessionEvent = SessionEvent> = (\n payload: SessionEventPayloads[E],\n) => void;\n\n// ─── Event Emitter ─────────────────────────────────────────────────────\n\nexport class SessionEventEmitter {\n private listeners: Map<SessionEvent, Set<SessionEventHandler>> = new Map();\n\n /**\n * Register an event handler.\n */\n on<E extends SessionEvent>(event: E, handler: SessionEventHandler<E>): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler as SessionEventHandler);\n }\n\n /**\n * Remove a previously registered event handler.\n */\n off<E extends SessionEvent>(event: E, handler: SessionEventHandler<E>): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.delete(handler as SessionEventHandler);\n if (handlers.size === 0) {\n this.listeners.delete(event);\n }\n }\n }\n\n /**\n * Remove all handlers for a specific event.\n */\n removeAllListeners(event?: SessionEvent): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Emit an event to all registered handlers.\n * Errors in handlers are caught and logged to prevent cascading failures.\n */\n protected emit<E extends SessionEvent>(\n event: E,\n payload: SessionEventPayloads[E],\n ): void {\n const handlers = this.listeners.get(event);\n if (!handlers) return;\n\n for (const handler of handlers) {\n try {\n handler(payload as SessionEventPayloads[SessionEvent]);\n } catch (error) {\n console.error(\n `[SessionEventEmitter] Error in handler for \"${event}\":`,\n error,\n );\n }\n }\n }\n}\n","/**\n * Session Persistence\n *\n * Extends LocalStorageSessionStorage to persist ChainSession data\n * alongside the wallet session, enabling multi-chain state recovery\n * across page reloads.\n *\n * @see SRS-009 §9\n */\n\nimport { logger } from \"../logger\";\nimport type { UniversalWalletSession } from \"../session\";\nimport { isSessionExpired } from \"../session\";\nimport type { StorageAdapter } from \"../storage\";\nimport { LocalStorageAdapter, MemoryStorageAdapter } from \"../storage\";\nimport type {\n ActiveSessionBundle,\n ChainSession,\n PersistedSessionData,\n} from \"./types\";\n\nconst DEFAULT_KEY = \"naculus_web3_session_manager\";\n\nexport class SessionPersistence {\n private adapter: StorageAdapter;\n private key: string;\n\n /**\n * @param key - Storage key for the persisted data.\n * @param adapter - Optional custom storage adapter. Defaults to LocalStorageAdapter.\n */\n constructor(key?: string, adapter?: StorageAdapter) {\n this.key = key ?? DEFAULT_KEY;\n this.adapter = adapter ?? new LocalStorageAdapter(\"naculus_sm:\");\n }\n\n /**\n * Return whether the backing storage is available.\n */\n isAvailable(): boolean {\n return this.adapter.isAvailable();\n }\n\n /**\n * Load the persisted session data.\n * Returns null if no data is found or parsing fails.\n */\n async load(): Promise<PersistedSessionData | null> {\n if (!this.adapter.isAvailable()) return null;\n\n try {\n return await this.adapter.get<PersistedSessionData>(this.key);\n } catch (error) {\n logger.warn(\n \"session/persistence\",\n \"Failed to load persisted session:\",\n error,\n );\n await this.adapter.remove(this.key);\n return null;\n }\n }\n\n /**\n * Save session data to persistent storage.\n */\n async save(data: PersistedSessionData): Promise<void> {\n if (!this.adapter.isAvailable()) return;\n\n try {\n await this.adapter.set(this.key, data);\n } catch (error) {\n logger.warn(\"session/persistence\", \"Failed to save session:\", error);\n }\n }\n\n /**\n * Clear persisted session data.\n */\n async clear(): Promise<void> {\n if (!this.adapter.isAvailable()) return;\n\n await this.adapter.remove(this.key);\n }\n\n /**\n * Serialize an ActiveSessionBundle to PersistedSessionData.\n * Converts the Map to a Record for JSON compatibility.\n */\n serializeBundle(bundle: ActiveSessionBundle): PersistedSessionData {\n const chainSessions: Record<string, ChainSession> = {};\n bundle.chainSessions.forEach((session, chainId) => {\n chainSessions[chainId] = session;\n });\n\n return {\n walletSession: bundle.walletSession,\n lastActiveChainId: bundle.activeChainId,\n chainSessions,\n lastConnectedAt: bundle.lastActiveAt,\n };\n }\n\n /**\n * Deserialize PersistedSessionData back to a bundle structure.\n * Returns null if the wallet session has expired.\n */\n deserializeToBundle(data: PersistedSessionData): ActiveSessionBundle | null {\n if (isSessionExpired(data.walletSession, new Date())) {\n logger.warn(\n \"session/persistence\",\n \"Persisted session is expired, ignoring\",\n );\n return null;\n }\n\n const chainSessions = new Map<string, ChainSession>();\n for (const [chainId, session] of Object.entries(data.chainSessions)) {\n chainSessions.set(chainId, session);\n }\n\n return {\n walletSession: data.walletSession,\n chainSessions,\n activeChainId: data.lastActiveChainId,\n lastActiveAt: data.lastConnectedAt,\n };\n }\n}\n\n/**\n * Create a SessionPersistence instance.\n */\nexport function createSessionPersistence(\n key?: string,\n adapter?: StorageAdapter,\n): SessionPersistence {\n // If no localStorage available, use memory storage to avoid crashes\n if (!adapter) {\n const hasLocalStorage =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as any).localStorage !== \"undefined\";\n\n if (!hasLocalStorage) {\n return new SessionPersistence(key, new MemoryStorageAdapter());\n }\n }\n return new SessionPersistence(key, adapter);\n}\n","/**\n * Chain Session Model for Multi-Chain Session Management\n *\n * @see SRS-009 §3\n */\n\nimport type { FeeEstimationConfig, FeeValues } from \"../fee-estimation\";\nimport type { UniversalWalletSession } from \"../session\";\n\n// ─── Chain Session ──────────────────────────────────────────────────────\n\n/**\n * Chain-specific session data.\n *\n * Defines the state of a session on one specific chain.\n * A single UniversalWalletSession can contain multiple ChainSessions\n * across different namespaces (e.g., EVM + Solana).\n */\nexport interface ChainSession {\n /** Chain ID in CAIP-2 format (e.g., \"eip155:1\", \"solana:0\") */\n chainId: string;\n\n /** The connector instance ID that manages this chain */\n connectorId: string;\n\n /** RPC endpoint for this chain */\n rpcUrl: string;\n\n /** Native currency metadata */\n nativeCurrency: {\n name: string;\n symbol: string;\n decimals: number;\n };\n\n /** Block explorer URL (optional) */\n blockExplorer?: string;\n\n /** Last known fee values (cached) */\n lastKnownFees?: FeeValues;\n\n /** Timestamp of last successful fee estimation */\n lastFeeUpdatedAt?: string;\n}\n\n// ─── Active Session Bundle ──────────────────────────────────────────────\n\n/**\n * Active session bundle: wraps a UniversalWalletSession with\n * its constituent ChainSessions for multi-chain visibility.\n */\nexport interface ActiveSessionBundle {\n /** The persistent UniversalWalletSession */\n walletSession: UniversalWalletSession;\n\n /** Chain-specific sessions derived from namespaces */\n chainSessions: Map<string, ChainSession>;\n\n /** The currently \"active\" chain ID (the chain being transacted on) */\n activeChainId: string;\n\n /** When this session was last used */\n lastActiveAt: string;\n}\n\n// ─── Persistence ───────────────────────────────────────────────────────\n\n/**\n * Serialized format for session persistence.\n * Map is serialized as Record for JSON compatibility.\n */\nexport interface PersistedSessionData {\n walletSession: UniversalWalletSession;\n lastActiveChainId: string;\n chainSessions: Record<string, ChainSession>;\n lastConnectedAt: string;\n}\n\n// ─── User Fee Overrides ────────────────────────────────────────────────\n\n/**\n * User-configured fee overrides, preserved across chain switches.\n * Keyed by CAIP-2 chainId.\n */\nexport interface UserFeeOverrides {\n [chainId: string]: {\n type?: \"eip1559\" | \"legacy\";\n maxPriorityFeePerGas?: bigint;\n baseFeeMultiplier?: bigint;\n };\n}\n\n// ─── Session Manager Config ────────────────────────────────────────────\n\nexport interface SessionManagerConfig {\n /** Default RPC URLs keyed by chainId */\n defaultRpcUrls?: Record<string, string>;\n /** Default native currency metadata keyed by chainId */\n defaultCurrencies?: Record<\n string,\n { name: string; symbol: string; decimals: number }\n >;\n /** Default block explorers keyed by chainId */\n defaultExplorers?: Record<string, string>;\n /** Whether to auto-refresh fee estimation on chain switch (default: true) */\n autoRefreshFeeOnSwitch?: boolean;\n /** Maximum active session bundles (default: 10) */\n maxActiveSessions?: number;\n /** Optional AES-GCM encryption key for session persistence */\n encryptionKey?: string;\n}\n\n// ─── Refresh Fees Options ──────────────────────────────────────────────\n\nexport interface RefreshFeesOptions {\n force?: boolean;\n userOverrides?: Partial<FeeEstimationConfig>;\n}\n\n// ─── Constructor Helpers ───────────────────────────────────────────────\n\n/**\n * Parse a CAIP-2 chain ID into namespace and reference parts.\n * e.g., \"eip155:1\" → { namespace: \"eip155\", reference: \"1\" }\n * e.g., \"solana:0\" → { namespace: \"solana\", reference: \"0\" }\n */\nexport function parseChainId(chainId: string): {\n namespace: string;\n reference: string;\n} {\n const parts = chainId.split(\":\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new Error(\n `Invalid CAIP-2 chain ID: \"${chainId}\". Expected format: \"namespace:reference\"`,\n );\n }\n return { namespace: parts[0], reference: parts[1] };\n}\n\n/**\n * Validate a CAIP-2 chain ID format.\n * Supported namespaces: eip155, solana, xrpl\n */\nexport function validateChainId(chainId: string): void {\n const { namespace, reference } = parseChainId(chainId);\n const supported = [\"eip155\", \"solana\", \"xrpl\"];\n if (!supported.includes(namespace)) {\n throw new Error(\n `Unsupported namespace \"${namespace}\" in chain ID \"${chainId}\". Supported: ${supported.join(\", \")}`,\n );\n }\n if (!/^\\d+$/.test(reference)) {\n throw new Error(\n `Invalid reference \"${reference}\" in chain ID \"${chainId}\". Reference must be numeric.`,\n );\n }\n}\n","/**\n * SessionManager\n *\n * Unified multi-chain session management system.\n * Wraps ConnectorManager to add chain-aware session lifecycle,\n * fee estimation sync, event emission, and persistence.\n *\n * @see SRS-009 §3-6\n */\n\nimport type { UniversalConnector, UniversalWalletSession } from \"../connector\";\nimport type { ConnectorManager } from \"../connector-manager\";\nimport type { FeeEstimationConfig, FeeValues } from \"../fee-estimation\";\nimport { estimateFees } from \"../fee-estimation\";\nimport { logger } from \"../logger\";\nimport { DEFAULT_RPC_URLS } from \"../rpc\";\nimport type { SessionNamespace } from \"../session\";\nimport { createSessionError } from \"./errors\";\nimport type {\n SessionEvent,\n SessionEventHandler,\n SessionEventPayloads,\n} from \"./events\";\nimport { SessionEventEmitter } from \"./events\";\nimport {\n createSessionPersistence,\n type SessionPersistence,\n} from \"./persistence\";\nimport type {\n ActiveSessionBundle,\n ChainSession,\n RefreshFeesOptions,\n SessionManagerConfig,\n UserFeeOverrides,\n} from \"./types\";\nimport { parseChainId, validateChainId } from \"./types\";\n\n// ─── Default Chain Metadata ────────────────────────────────────────────\n\nconst DEFAULT_CHAIN_METADATA: Record<\n string,\n { name: string; symbol: string; decimals: number }\n> = {\n \"eip155:1\": { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n \"eip155:137\": { name: \"MATIC\", symbol: \"MATIC\", decimals: 18 },\n \"eip155:10\": { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n \"eip155:42161\": { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n \"eip155:8453\": { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n \"eip155:11155111\": { name: \"Sepolia Ether\", symbol: \"ETH\", decimals: 18 },\n \"solana:0\": { name: \"SOL\", symbol: \"SOL\", decimals: 9 },\n \"solana:1\": { name: \"SOL\", symbol: \"SOL\", decimals: 9 },\n};\n\nconst DEFAULT_EXPLORERS: Record<string, string> = {\n \"eip155:1\": \"https://etherscan.io\",\n \"eip155:137\": \"https://polygonscan.com\",\n \"eip155:10\": \"https://optimistic.etherscan.io\",\n \"eip155:42161\": \"https://arbiscan.io\",\n \"eip155:8453\": \"https://basescan.org\",\n \"eip155:11155111\": \"https://sepolia.etherscan.io\",\n};\n\n// ─── SessionManager ────────────────────────────────────────────────────\n\nexport class SessionManager extends SessionEventEmitter {\n private bundles: Map<string, ActiveSessionBundle> = new Map();\n private activeBundleId: string | null = null;\n private userFeeOverrides: UserFeeOverrides = {};\n private config: Required<\n Pick<SessionManagerConfig, \"autoRefreshFeeOnSwitch\" | \"maxActiveSessions\">\n > &\n Omit<SessionManagerConfig, \"autoRefreshFeeOnSwitch\" | \"maxActiveSessions\">;\n private persistence: SessionPersistence;\n\n constructor(\n private connectorManager: ConnectorManager,\n config?: SessionManagerConfig,\n ) {\n super();\n this.config = {\n autoRefreshFeeOnSwitch: config?.autoRefreshFeeOnSwitch ?? true,\n maxActiveSessions: config?.maxActiveSessions ?? 10,\n defaultRpcUrls: config?.defaultRpcUrls,\n defaultCurrencies: config?.defaultCurrencies,\n defaultExplorers: config?.defaultExplorers,\n };\n this.persistence = createSessionPersistence();\n }\n\n // ── Core API ────────────────────────────────────────────────────────\n\n /**\n * Connect to a wallet on a specific chain.\n * Delegates to the connector's connect method and wraps the result\n * in an ActiveSessionBundle.\n */\n async connect(\n walletType: string,\n chainId: string,\n input?: unknown,\n ): Promise<ActiveSessionBundle> {\n validateChainId(chainId);\n\n if (this.bundles.size >= this.config.maxActiveSessions) {\n // LRU evict: remove oldest bundle\n const oldest = Array.from(this.bundles.entries()).reduce((a, b) =>\n a[1].lastActiveAt < b[1].lastActiveAt ? a : b,\n );\n this.bundles.delete(oldest[0]);\n }\n\n // Let connectorManager auto-select or specify the connector\n const session = await this.connectorManager.connect(input as any);\n const bundle = this.buildBundle(session, chainId, walletType);\n\n const bundleId = this.getBundleId(session);\n this.bundles.set(bundleId, bundle);\n this.activeBundleId = bundleId;\n\n await this.persistBundle(bundle);\n\n this.emit(\"sessionConnected\", { bundle });\n return bundle;\n }\n\n /**\n * Switch the active chain for the current session.\n * Delegates to the appropriate connector's switchChain method.\n * After successful switch, auto-refreshes fee estimation.\n */\n async switchChain(chainId: string): Promise<void> {\n validateChainId(chainId);\n\n const bundle = this.getActiveBundle();\n if (!bundle) {\n throw createSessionError(\"no_active_session\");\n }\n\n const previousChainId = bundle.activeChainId;\n\n // No-op if already on the requested chain\n if (previousChainId === chainId) {\n return;\n }\n\n const connector = this.resolveConnector(bundle.walletSession);\n if (!connector.switchChain) {\n throw createSessionError(\"method_unsupported\");\n }\n\n try {\n await connector.switchChain(bundle.walletSession, chainId);\n } catch (error: any) {\n // Map user rejection\n if (error?.code === 4001 || error?.message?.includes(\"rejected\")) {\n throw createSessionError(\"chain_switch_rejected\");\n }\n throw createSessionError(\"chain_unsupported\");\n }\n\n // Ensure the chain session exists (create if first time)\n if (!bundle.chainSessions.has(chainId)) {\n const chainSession = this.createChainSession(\n chainId,\n bundle.walletSession.walletType,\n );\n bundle.chainSessions.set(chainId, chainSession);\n this.emit(\"chainSessionAdded\", { bundle, chainSession });\n }\n\n bundle.activeChainId = chainId;\n bundle.lastActiveAt = new Date().toISOString();\n\n // Update wallet session namespaces\n this.updateSessionNamespace(bundle.walletSession, chainId);\n\n this.emit(\"chainChanged\", { bundle, previousChainId, newChainId: chainId });\n\n // Auto-refresh fee estimation\n if (this.config.autoRefreshFeeOnSwitch) {\n try {\n await this.refreshFees(chainId);\n } catch (error) {\n // Non-blocking: fee refresh failure should not block chain switch\n logger.warn(\n \"session-manager\",\n `Fee refresh failed after chain switch to ${chainId}:`,\n error,\n );\n }\n }\n\n await this.persistBundle(bundle);\n }\n\n /**\n * Disconnect the active session.\n * Cleans up all chain sessions and clears storage.\n */\n async disconnect(): Promise<void> {\n const bundle = this.getActiveBundle();\n if (!bundle) return;\n\n const connector = this.resolveConnector(bundle.walletSession);\n try {\n await connector.disconnect(bundle.walletSession);\n } catch (error) {\n logger.warn(\"session-manager\", \"Disconnect error:\", error);\n }\n\n const connectorId = bundle.walletSession.walletType;\n const topic = bundle.walletSession.topic;\n const bundleId = this.activeBundleId;\n\n if (bundleId) {\n this.bundles.delete(bundleId);\n }\n this.activeBundleId = null;\n\n await this.persistence.clear();\n\n this.emit(\"sessionDisconnected\", { connectorId, topic });\n }\n\n /**\n * Disconnect a specific chain session within the active bundle.\n * Does not disconnect the entire wallet.\n */\n async disconnectChain(chainId: string): Promise<void> {\n const bundle = this.getActiveBundle();\n if (!bundle) {\n throw createSessionError(\"no_active_session\");\n }\n\n const removed = bundle.chainSessions.delete(chainId);\n if (removed) {\n this.emit(\"chainSessionRemoved\", { bundle, chainId });\n\n // If the active chain was removed, move to the first available\n if (bundle.activeChainId === chainId) {\n const remaining = Array.from(bundle.chainSessions.keys());\n bundle.activeChainId = remaining[0] ?? bundle.activeChainId;\n }\n\n await this.persistBundle(bundle);\n }\n }\n\n /**\n * Get the active chain session.\n */\n getActiveChainSession(): ChainSession | undefined {\n const bundle = this.getActiveBundle();\n if (!bundle) return undefined;\n return bundle.chainSessions.get(bundle.activeChainId);\n }\n\n /**\n * Get all active chain sessions across all connected bundles.\n */\n getAllChainSessions(): ChainSession[] {\n const sessions: ChainSession[] = [];\n for (const bundle of this.bundles.values()) {\n bundle.chainSessions.forEach((session) => {\n sessions.push(session);\n });\n }\n return sessions;\n }\n\n /**\n * Get all active session bundles.\n */\n getAllActiveSessions(): ActiveSessionBundle[] {\n return Array.from(this.bundles.values());\n }\n\n /**\n * Get the currently active session bundle.\n */\n getActiveBundle(): ActiveSessionBundle | null {\n if (!this.activeBundleId) return null;\n return this.bundles.get(this.activeBundleId) ?? null;\n }\n\n // ── Fee Estimation Sync ─────────────────────────────────────────────\n\n /**\n * Refresh fee estimation for a specific chain.\n * Called automatically on switchChain if autoRefreshFeeOnSwitch is enabled.\n */\n async refreshFees(\n chainId?: string,\n options?: RefreshFeesOptions,\n ): Promise<FeeValues | null> {\n const bundle = this.getActiveBundle();\n if (!bundle) {\n throw createSessionError(\"no_active_session\");\n }\n\n const targetChainId = chainId ?? bundle.activeChainId;\n const chainSession = bundle.chainSessions.get(targetChainId);\n if (!chainSession) return null;\n\n try {\n const feeConfig: FeeEstimationConfig = {\n rpcUrl: chainSession.rpcUrl,\n chainId: targetChainId,\n };\n\n // Apply user fee overrides if present for this chain\n const overrides = this.userFeeOverrides[targetChainId];\n if (overrides) {\n if (overrides.type) feeConfig.type = overrides.type;\n if (overrides.maxPriorityFeePerGas !== undefined) {\n feeConfig.maxPriorityFeePerGas = overrides.maxPriorityFeePerGas;\n }\n if (overrides.baseFeeMultiplier !== undefined) {\n feeConfig.baseFeeMultiplier = overrides.baseFeeMultiplier;\n }\n }\n\n // Apply per-call overrides from options\n if (options?.userOverrides) {\n Object.assign(feeConfig, options.userOverrides);\n }\n\n const fees = await estimateFees(feeConfig);\n\n chainSession.lastKnownFees = fees;\n chainSession.lastFeeUpdatedAt = new Date().toISOString();\n\n this.emit(\"feesUpdated\", { chainId: targetChainId, fees });\n\n return fees;\n } catch (error: any) {\n // If RPC fails, keep cached values and emit warning\n logger.warn(\n \"session-manager\",\n `Fee refresh failed for ${targetChainId}:`,\n error,\n );\n return chainSession.lastKnownFees ?? null;\n }\n }\n\n // ── User Fee Overrides ──────────────────────────────────────────────\n\n /**\n * Set user fee overrides for a specific chain.\n * Overrides are preserved across chain switches.\n */\n setUserFeeOverrides(\n chainId: string,\n overrides: Partial<UserFeeOverrides[string]>,\n ): void {\n const existing = this.userFeeOverrides[chainId] ?? {};\n this.userFeeOverrides[chainId] = { ...existing, ...overrides };\n }\n\n /**\n * Get the current user fee overrides for a specific chain.\n */\n getUserFeeOverrides(chainId: string): UserFeeOverrides[string] | undefined {\n return this.userFeeOverrides[chainId];\n }\n\n /**\n * Clear user fee overrides for a specific chain.\n */\n clearUserFeeOverrides(chainId?: string): void {\n if (chainId) {\n delete this.userFeeOverrides[chainId];\n } else {\n this.userFeeOverrides = {};\n }\n }\n\n // ── Persistence ─────────────────────────────────────────────────────\n\n /**\n * Attempt to restore a session from persistence.\n * Returns true if a session was restored, false otherwise.\n */\n async restoreFromPersistence(): Promise<boolean> {\n const data = await this.persistence.load();\n if (!data) return false;\n\n const bundle = this.persistence.deserializeToBundle(data);\n if (!bundle) {\n await this.persistence.clear();\n return false;\n }\n\n const bundleId = this.getBundleId(bundle.walletSession);\n this.bundles.set(bundleId, bundle);\n this.activeBundleId = bundleId;\n\n this.emit(\"sessionConnected\", { bundle });\n return true;\n }\n\n // ── Event Emitter (re-expose for public API) ────────────────────────\n\n override on<E extends SessionEvent>(\n event: E,\n handler: SessionEventHandler<E>,\n ): void {\n super.on(event, handler);\n }\n\n override off<E extends SessionEvent>(\n event: E,\n handler: SessionEventHandler<E>,\n ): void {\n super.off(event, handler);\n }\n\n // ── Internal Helpers ────────────────────────────────────────────────\n\n /**\n * Build a bundle from a wallet session, marking the given chain as active.\n */\n private buildBundle(\n session: UniversalWalletSession,\n activeChainId: string,\n walletType: string,\n ): ActiveSessionBundle {\n const chainSessions = new Map<string, ChainSession>();\n\n // Parse existing session namespaces to build chain sessions\n for (const [, namespace] of Object.entries(session.namespaces)) {\n const ns = namespace as SessionNamespace;\n for (const chain of ns.chains) {\n if (!chainSessions.has(chain)) {\n chainSessions.set(chain, this.createChainSession(chain, walletType));\n }\n }\n }\n\n // If the requested chain isn't in the namespaces yet, add it\n if (!chainSessions.has(activeChainId)) {\n chainSessions.set(\n activeChainId,\n this.createChainSession(activeChainId, walletType),\n );\n }\n\n return {\n walletSession: session,\n chainSessions,\n activeChainId,\n lastActiveAt: new Date().toISOString(),\n };\n }\n\n /**\n * Create a ChainSession for the given chain ID.\n * Resolves RPC URL, native currency, and block explorer from config\n * or defaults.\n */\n private createChainSession(\n chainId: string,\n connectorId: string,\n ): ChainSession {\n const { namespace } = parseChainId(chainId);\n\n const nativeCurrency = this.config.defaultCurrencies?.[chainId] ??\n DEFAULT_CHAIN_METADATA[chainId] ?? {\n name: chainId,\n symbol: chainId.includes(\":\") ? chainId.split(\":\")[1] : chainId,\n decimals: 18,\n };\n\n const rpcUrl =\n this.config.defaultRpcUrls?.[chainId] ?? DEFAULT_RPC_URLS[chainId] ?? \"\";\n\n const blockExplorer =\n this.config.defaultExplorers?.[chainId] ?? DEFAULT_EXPLORERS[chainId];\n\n return {\n chainId,\n connectorId,\n rpcUrl,\n nativeCurrency,\n blockExplorer,\n };\n }\n\n /**\n * Update the UniversalWalletSession namespaces to reflect\n * the current active chain.\n */\n private updateSessionNamespace(\n session: UniversalWalletSession,\n chainId: string,\n ): void {\n const { namespace, reference } = parseChainId(chainId);\n\n if (!session.namespaces[namespace]) {\n session.namespaces[namespace] = {\n chains: [],\n accounts: [],\n methods: [],\n events: [],\n };\n }\n\n const ns = session.namespaces[namespace];\n if (!ns.chains.includes(chainId)) {\n ns.chains.push(chainId);\n }\n }\n\n /**\n * Resolve the appropriate connector for a given wallet session.\n */\n private resolveConnector(\n session: UniversalWalletSession,\n ): UniversalConnector {\n const connector = this.connectorManager.get(session.walletType);\n if (!connector) {\n throw createSessionError(\n \"chain_unsupported\",\n `No connector found for wallet type: ${session.walletType}`,\n );\n }\n return connector;\n }\n\n /**\n * Get a unique bundle ID from a wallet session.\n */\n private getBundleId(session: UniversalWalletSession): string {\n return session.topic ?? session.id;\n }\n\n /**\n * Persist the active bundle to storage.\n */\n private async persistBundle(bundle: ActiveSessionBundle): Promise<void> {\n const data = this.persistence.serializeBundle(bundle);\n await this.persistence.save(data);\n }\n}\n\n/**\n * Create a SessionManager instance.\n */\nexport function createSessionManager(\n connectorManager: ConnectorManager,\n config?: SessionManagerConfig,\n): SessionManager {\n return new SessionManager(connectorManager, config);\n}\n","/**\n * BlowfishProvider — Blowfish API integration for transaction simulation\n * and security scanning.\n *\n * This is an **adapter stub** (Layer 2 / P1). When configured with an\n * API key, it provides:\n * - Full balance change detection\n * - Human-readable simulation summaries\n * - Risk scoring (suggestedAction: NONE / WARN / BLOCK)\n * - Phishing detection\n *\n * Implementation notes:\n * - API key is provided by the wallet host (not end-user)\n * - Falls back to basic simulation on rate-limit / 500\n * - Sensitive transaction data is sent to Blowfish servers\n *\n * @see https://docs.blowfish.xyz\n * @see /docs/features/transaction-simulation.md §5.2\n */\n\nimport type {\n ApprovalChange,\n BalanceChange,\n GasInfo,\n RiskLevel,\n RiskWarning,\n SimulationProviderName,\n SimulationResult,\n TransactionDescriptor,\n} from \"../types\";\nimport type { SimulationProvider } from \"./types\";\n\n// ── Supported EVM chains (per Blowfish docs) ──────────────────────\n\nconst SUPPORTED_CHAINS = [1, 137, 42161, 10, 56, 43114, 8453, 250, 25, 324];\n\nconst CHAIN_NAMES: Record<number, string> = {\n 1: \"ethereum\",\n 137: \"polygon\",\n 42161: \"arbitrum\",\n 10: \"optimism\",\n 56: \"bsc\",\n 43114: \"avalanche\",\n 8453: \"base\",\n 250: \"fantom\",\n 25: \"cronos\",\n 324: \"zksync\",\n};\n\nconst BLOWFISH_API_BASE = \"https://api.blowfish.xyz\";\n\nfunction getChainName(chainId: number): string {\n return CHAIN_NAMES[chainId] ?? `eip155:${chainId}`;\n}\n\n// ── Helper: Map Blowfish suggestedAction to RiskLevel ─────────────\n\nfunction mapSuggestedAction(action: string | undefined | null): RiskLevel {\n switch (action) {\n case \"NONE\":\n return \"safe\";\n case \"WARN\":\n return \"warning\";\n case \"BLOCK\":\n return \"malicious\";\n default:\n return \"unknown\";\n }\n}\n\n// ── Helper: Build warnings from Blowfish scan results ────────────\n\nfunction buildWarnings(scanResults: any[] | undefined): RiskWarning[] {\n if (!scanResults || !Array.isArray(scanResults)) return [];\n\n const warnings: RiskWarning[] = [];\n\n for (const scan of scanResults) {\n if (scan?.kind === \"APPROVAL_TO_EOA\") {\n warnings.push({\n category: \"phishing\",\n severity: \"critical\",\n message:\n scan.description ?? \"Approval to an Externally Owned Account (EOA)\",\n });\n }\n\n if (scan?.kind === \"UNLIMITED_ALLOWANCE\") {\n warnings.push({\n category: \"unlimited_approval\",\n severity: \"high\",\n message: scan.description ?? \"Unlimited token approval requested\",\n });\n }\n\n if (scan?.kind === \"MALICIOUS_DOMAIN\") {\n warnings.push({\n category: \"malicious_domain\",\n severity: \"critical\",\n message: scan.description ?? \"Suspicious domain detected\",\n });\n }\n\n if (scan?.kind === \"KNOWN_MALICIOUS\") {\n warnings.push({\n category: \"phishing\",\n severity: \"critical\",\n message: scan.description ?? \"Known malicious contract detected\",\n });\n }\n\n if (scan?.kind === \"SIMULATION_ERROR\") {\n warnings.push({\n category: \"simulation_failed\",\n severity: \"medium\",\n message: scan.description ?? \"Simulation encountered an error\",\n });\n }\n\n if (\n scan?.kind &&\n ![\n \"APPROVAL_TO_EOA\",\n \"UNLIMITED_ALLOWANCE\",\n \"MALICIOUS_DOMAIN\",\n \"KNOWN_MALICIOUS\",\n \"SIMULATION_ERROR\",\n ].includes(scan.kind)\n ) {\n warnings.push({\n category: \"other\",\n severity:\n scan.severity === \"CRITICAL\"\n ? \"critical\"\n : scan.severity === \"HIGH\"\n ? \"high\"\n : scan.severity === \"MEDIUM\"\n ? \"medium\"\n : \"low\",\n message: scan.description ?? `Unexpected scan result: ${scan.kind}`,\n });\n }\n }\n\n return warnings;\n}\n\n// ── Helper: Parse Blowfish state changes into BalanceChanges ──────\n\nfunction parseBalanceChanges(changes: any[] | undefined): BalanceChange[] {\n if (!changes || !Array.isArray(changes)) return [];\n\n const results: BalanceChange[] = [];\n\n for (const change of changes) {\n if (!change?.contractInfo) continue;\n\n // Blowfish can return humanReadableDiff like \"Send 1.5 USDC\"\n // Raw amount info comes in rawInfo or amount fields\n const match = change.humanReadableDiff?.match(\n /^(Send|Receive|Approve|Revoke)\\s+(.+?)(?:\\s+\\(([^)]+)\\))?\\s*(.+)?$/i,\n );\n\n let direction: \"in\" | \"out\" = \"out\";\n const humanReadable = change.humanReadableDiff ?? \"\";\n if (/^Receive/i.test(humanReadable)) {\n direction = \"in\";\n }\n\n const rawAmount = change.rawInfo?.amount ?? change.amount ?? \"0\";\n\n const tokenSymbol = change.contractInfo.name ?? \"\";\n const tokenAddress = (change.contractInfo.address ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`;\n const tokenDecimals = change.contractInfo.decimals ?? 18;\n\n results.push({\n tokenAddress,\n tokenSymbol,\n tokenDecimals,\n amount:\n typeof rawAmount === \"bigint\"\n ? rawAmount.toString()\n : String(rawAmount),\n direction,\n from: (change.from ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`,\n to: (change.to ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`,\n humanReadable,\n });\n }\n\n return results;\n}\n\n// ── Helper: Parse Approval changes ────────────────────────────────\n\nfunction parseApprovalChanges(changes: any[] | undefined): ApprovalChange[] {\n if (!changes || !Array.isArray(changes)) return [];\n\n const results: ApprovalChange[] = [];\n\n for (const change of changes) {\n if (!change?.humanReadableDiff) continue;\n\n // Detect approval patterns\n const isApproval = /^Approve/i.test(change.humanReadableDiff);\n if (!isApproval) continue;\n\n const rawAmount = change.rawInfo?.amount ?? change.amount ?? \"0\";\n const isUnlimited =\n rawAmount ===\n \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\" ||\n rawAmount ===\n \"115792089237316195423570985008687907853269984665640564039457584007913129639935\";\n\n results.push({\n tokenAddress: (change.contractInfo?.address ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`,\n tokenSymbol: change.contractInfo?.name ?? \"\",\n owner: (change.from ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`,\n spender: (change.to ??\n \"0x0000000000000000000000000000000000000000\") as `0x${string}`,\n amount: String(rawAmount),\n isUnlimited,\n humanReadable: change.humanReadableDiff,\n });\n }\n\n return results;\n}\n\n// ── Helper: Parse gas info ────────────────────────────────────────\n\nfunction parseGasInfo(gasInfo: any | undefined): GasInfo | undefined {\n if (!gasInfo) return undefined;\n\n return {\n gasLimit: gasInfo.gasLimit ? BigInt(gasInfo.gasLimit) : 0n,\n gasPrice: gasInfo.gasPrice ? BigInt(gasInfo.gasPrice) : undefined,\n estimatedFeeEth: gasInfo.estimatedFeeEth,\n estimatedFeeUsd: gasInfo.estimatedFeeUsd,\n };\n}\n\n// ── Helper: Build summary from simulation result description ─────\n\nfunction buildSummary(\n simulationResult: any | undefined,\n balanceChanges: BalanceChange[],\n): string {\n if (simulationResult?.description) {\n return simulationResult.description;\n }\n\n if (balanceChanges.length > 0) {\n const changes = balanceChanges\n .slice(0, 3)\n .map((c) => c.humanReadable)\n .join(\", \");\n return changes.length > 0 ? changes : \"State changes detected\";\n }\n\n return \"No significant state changes detected\";\n}\n\n// ── BlowfishProvider ──────────────────────────────────────────────\n\nexport class BlowfishProvider implements SimulationProvider {\n readonly name: SimulationProviderName = \"blowfish\";\n readonly supportedChains: number[] = SUPPORTED_CHAINS;\n\n private apiKey: string;\n\n constructor(apiKey: string) {\n if (!apiKey || apiKey.trim().length === 0) {\n throw new Error(\n \"BlowfishProvider requires an API key. Get one at https://blowfish.xyz\",\n );\n }\n this.apiKey = apiKey;\n }\n\n async simulate(\n tx: TransactionDescriptor,\n from: `0x${string}`,\n options?: {\n origin?: string;\n rpcUrl?: string;\n },\n ): Promise<SimulationResult> {\n // Note: This is an adapter stub. The actual Blowfish API integration\n // requires a specific API endpoint + request format per version.\n // The structure below follows the documented Blowfish API format.\n //\n // When implementing, replace the fetch call with the actual\n // endpoint and request body from Blowfish docs.\n\n try {\n const chainName = options?.origin\n ? getChainName(this._inferChainId(options.origin))\n : \"ethereum\";\n\n const response = await fetch(\n `${BLOWFISH_API_BASE}/v1/solana/mainnet/transaction/simulate`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n transactions: [tx.data],\n userAccount: from,\n metadata: {\n origin: options?.origin ?? \"\",\n },\n }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 429) {\n // Rate limited — return unavailable, caller can fall back\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"low\",\n message:\n \"Blowfish: Rate limited. Falling back to basic simulation.\",\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable (rate limited)\",\n changesDetected: false,\n };\n }\n\n if (response.status >= 500) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"medium\",\n message: `Blowfish: Server error (${response.status}). Falling back to basic simulation.`,\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable (server error)\",\n changesDetected: false,\n };\n }\n\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"medium\",\n message: `Blowfish: HTTP ${response.status}. Falling back.`,\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable\",\n changesDetected: false,\n };\n }\n\n const json: any = await response.json();\n const simResult = json.simulationResult ?? json;\n\n const balanceChanges = parseBalanceChanges(\n simResult.expectedStateChanges,\n );\n const approvalChanges = parseApprovalChanges(\n simResult.expectedStateChanges,\n );\n const suggestedAction = simResult.suggestedAction ?? \"NONE\";\n const riskLevel = mapSuggestedAction(suggestedAction);\n\n const scanResults = simResult.scanResults ?? [];\n const warnings = buildWarnings(scanResults);\n\n // Compute risk score\n let score = 0;\n if (riskLevel === \"warning\") score = 40;\n if (riskLevel === \"malicious\") score = 80;\n for (const w of warnings) {\n if (w.severity === \"critical\") score += 20;\n else if (w.severity === \"high\") score += 10;\n else if (w.severity === \"medium\") score += 5;\n }\n score = Math.min(score, 100);\n\n return {\n status: simResult.status === \"REVERTED\" ? \"reverted\" : \"success\",\n revertReason: simResult.error?.message,\n balanceChanges,\n approvalChanges,\n riskAssessment: {\n level: riskLevel,\n score,\n warnings,\n },\n gasInfo: parseGasInfo(simResult.gasInfo),\n provider: this.name,\n summary: buildSummary(simResult, balanceChanges),\n changesDetected:\n simResult.status === \"CHANGES_DETECTED\" || balanceChanges.length > 0,\n raw: simResult,\n };\n } catch (err) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"medium\",\n message: `Blowfish: Network error: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable (network error)\",\n changesDetected: false,\n };\n }\n }\n\n isAvailable(chainId: number): boolean {\n return SUPPORTED_CHAINS.includes(chainId);\n }\n\n /**\n * Best-effort infer chain ID from origin or other context.\n * Defaults to 1 (Ethereum mainnet).\n */\n private _inferChainId(_origin: string): number {\n return 1;\n }\n}\n","/**\n * EthCallProvider — Basic simulation using the eth_call RPC method.\n *\n * Provides Layer 1 (P0) simulation: checks for revert, returns revert\n * reason if the transaction would fail. Cannot resolve balance changes,\n * approval changes, or risk scores since eth_call only returns the\n * function output, not state diffs.\n *\n * Uses raw fetch to call JSON-RPC (no ethers/viem dependency).\n *\n * @see /docs/features/transaction-simulation.md §5.1\n */\n\nimport type {\n SimulationProviderName,\n SimulationResult,\n TransactionDescriptor,\n} from \"../types\";\nimport type { SimulationProvider } from \"./types\";\n\n// ── Constants ─────────────────────────────────────────────────────\n\nconst NATIVE_ASSET = {\n address: \"0x0000000000000000000000000000000000000000\" as `0x${string}`,\n symbol: \"ETH\",\n decimals: 18,\n};\n\nconst ETH_NATIVE_CHAINS = [1, 5, 11155111, 10, 42161, 421614, 8453, 84532];\nconst MATIC_NATIVE_CHAINS = [137, 80002];\nconst BNB_NATIVE_CHAINS = [56, 97];\n\n// ── Helper: Parse revert reason from error data ───────────────────\n\n/**\n * Attempt to extract a human-readable revert reason from eth_call error data.\n *\n * Solidity errors follow: Error(string) → 4 byte selector + offset(32B) + length(32B) + data\n * Panic follows: Panic(uint256) → 4 byte selector + code(32B)\n */\nfunction parseRevertReason(errorData: string): string | undefined {\n const clean = errorData.startsWith(\"0x\") ? errorData.slice(2) : errorData;\n\n // Check for Error(string) selector: 08c379a0\n if (clean.length >= 10 && clean.startsWith(\"08c379a0\")) {\n try {\n const dataHex = clean.slice(8);\n // ABI-encoded Error(string): offset(32B), length(32B), data\n const lengthHex = dataHex.slice(64, 128);\n const length = parseInt(lengthHex, 16);\n if (length > 0 && length * 2 <= dataHex.length - 128) {\n const msgHex = dataHex.slice(128, 128 + length * 2);\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = parseInt(msgHex.slice(i * 2, i * 2 + 2), 16);\n }\n return new TextDecoder().decode(bytes);\n }\n } catch {\n // Fall through to raw hex\n }\n }\n\n // Check for Panic(uint256) selector: 4e487b71\n if (clean.length >= 10 && clean.startsWith(\"4e487b71\")) {\n const codeHex = clean.slice(8, 72);\n const code = BigInt(`0x${codeHex}`);\n const panicMessages: Record<string, string> = {\n \"0\": \"Generic panic\",\n \"1\": \"Assert failed\",\n \"17\": \"Arithmetic overflow/underflow\",\n \"18\": \"Division by zero\",\n \"33\": \"Enum conversion out of bounds\",\n \"34\": \"Storage array access out of bounds\",\n \"49\": \"pop() on empty array\",\n \"50\": \"Index out of bounds\",\n \"65\": \"Allocate too much memory\",\n \"81\": \"Call to non-existent function\",\n };\n return panicMessages[code.toString()] ?? `Panic code ${code}`;\n }\n\n // Raw hex (no known selector)\n if (clean.length > 0) return clean;\n\n return undefined;\n}\n\n/**\n * Determine the native gas token symbol for a given chain.\n */\nfunction getNativeSymbol(chainId: number): string {\n if (ETH_NATIVE_CHAINS.includes(chainId)) return \"ETH\";\n if (MATIC_NATIVE_CHAINS.includes(chainId)) return \"MATIC\";\n if (BNB_NATIVE_CHAINS.includes(chainId)) return \"BNB\";\n return \"ETH\";\n}\n\n/**\n * Build a basic safe SimulationResult when eth_call does not revert.\n */\nfunction buildSuccessResult(\n providerName: SimulationProviderName,\n from: `0x${string}`,\n chainId: number,\n): SimulationResult {\n const nativeSymbol = getNativeSymbol(chainId);\n return {\n status: \"success\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [],\n },\n provider: providerName,\n summary: \"Transaction simulation succeeded (basic revert check only)\",\n changesDetected: true,\n };\n}\n\n/**\n * Build a SimulationResult for a reverted transaction.\n */\nfunction buildRevertedResult(\n revertReason: string | undefined,\n providerName: SimulationProviderName,\n): SimulationResult {\n return {\n status: \"reverted\",\n revertReason,\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"high\",\n message: revertReason\n ? `Transaction would revert: ${revertReason}`\n : \"Transaction would revert (no reason provided)\",\n },\n ],\n },\n provider: providerName,\n summary: revertReason\n ? `Transaction reverted: ${revertReason}`\n : \"Transaction reverted\",\n changesDetected: false,\n };\n}\n\n// ── EthCallProvider ───────────────────────────────────────────────\n\nexport class EthCallProvider implements SimulationProvider {\n readonly name: SimulationProviderName = \"eth_call\";\n readonly supportedChains: number[] = []; // empty = all EVM chains\n\n private defaultRpcUrl?: string;\n\n constructor(defaultRpcUrl?: string) {\n this.defaultRpcUrl = defaultRpcUrl;\n }\n\n /**\n * Simulate a transaction via eth_call.\n *\n * eth_call returns only the function return data — it does not expose\n * state diffs. Therefore this provider can only determine:\n * - Is the transaction going to revert?\n * - What is the revert reason?\n *\n * It CANNOT resolve balance changes or approval changes.\n */\n async simulate(\n tx: TransactionDescriptor,\n from: `0x${string}`,\n options?: {\n origin?: string;\n rpcUrl?: string;\n },\n ): Promise<SimulationResult> {\n const rpcUrl = options?.rpcUrl ?? this.defaultRpcUrl;\n if (!rpcUrl) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"medium\",\n message: \"EthCallProvider: No RPC URL configured\",\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable: no RPC URL\",\n changesDetected: false,\n };\n }\n\n const callParams: Record<string, string> = {\n to: tx.to,\n from: from,\n data: tx.data,\n value: tx.value || \"0x0\",\n };\n\n if (tx.gas) {\n callParams.gas = tx.gas;\n }\n\n try {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: Date.now(),\n method: \"eth_call\",\n params: [callParams, \"latest\"],\n }),\n });\n\n const json: any = await response.json();\n\n if (json.error) {\n const revertReason = parseRevertReason(\n json.error.data ?? json.error.message,\n );\n return buildRevertedResult(revertReason, this.name);\n }\n\n // eth_call succeeded\n return buildSuccessResult(\n this.name,\n from,\n this._extractChainId(options?.rpcUrl ?? this.defaultRpcUrl),\n );\n } catch (err) {\n // Network error or unexpected failure\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n level: \"unknown\",\n score: 0,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"medium\",\n message: `EthCallProvider: Network error during simulation: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n },\n ],\n },\n provider: this.name,\n summary: \"Simulation unavailable due to network error\",\n changesDetected: false,\n };\n }\n }\n\n isAvailable(_chainId: number): boolean {\n return true; // eth_call is available on all EVM chains\n }\n\n /**\n * Attempt to infer chain ID from the RPC URL (best-effort).\n * Returns 0 if unknown.\n */\n private _extractChainId(rpcUrl?: string): number {\n if (!rpcUrl) return 0;\n // This is intentionally simplistic — chain detection via net_version\n // would add an extra RPC call. We default to 0 since eth_call provider\n // doesn't deeply depend on chain ID.\n return 0;\n }\n}\n","/**\n * abortable-fetch\n *\n * Shared helpers for fetch + AbortController timeout patterns.\n * Replaces duplicated AbortController + setTimeout boilerplate across the codebase.\n */\n\n// ─── abortableFetch ────────────────────────────────────────────────────\n\n/**\n * Fetch with timeout via AbortController.\n * Returns the Response on success, throws on timeout or network error.\n */\nexport async function abortableFetch(\n url: string,\n options: RequestInit & { timeoutMs?: number } = {},\n): Promise<Response> {\n const timeoutMs = options.timeoutMs ?? 10_000;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n// ─── rpcCall ───────────────────────────────────────────────────────────\n\n/**\n * Make a JSON-RPC call with abort/timeout support.\n */\nexport async function rpcCall<T>(\n rpcUrl: string,\n method: string,\n params: unknown[],\n options?: { timeoutMs?: number; headers?: Record<string, string> },\n): Promise<T> {\n const response = await abortableFetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...options?.headers },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method, params }),\n timeoutMs: options?.timeoutMs ?? 10_000,\n });\n\n if (!response.ok) {\n throw new Error(`RPC returned status ${response.status}`);\n }\n\n const json = (await response.json()) as {\n result?: T;\n error?: { code: number; message: string };\n };\n\n if (json.error) {\n throw new Error(json.error.message);\n }\n\n return json.result as T;\n}\n","/**\n * Minimal ERC-20 ABI — only the 9 function selectors we need.\n *\n * Designed to be used with viem's readContract / simulateContract,\n * or with our manual ABI encoding for raw transaction building.\n *\n * Specifications:\n * - EIP-20: https://eips.ethereum.org/EIPS/eip-20\n * - Solidity ABI: https://docs.soliditylang.org/en/latest/abi-spec.html\n */\n\nexport type AbiFunction = {\n name: string;\n type: \"function\";\n stateMutability: \"view\" | \"nonpayable\" | \"payable\";\n inputs: { name: string; type: string }[];\n outputs: { name: string; type: string }[];\n};\n\n/** Full minimal ABI as const for viem compatibility */\nexport const ERC20_MIN_ABI = [\n // ── State-changing ──────────────────────────────────\n {\n name: \"transfer\",\n type: \"function\" as const,\n stateMutability: \"nonpayable\" as const,\n inputs: [\n { name: \"to\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"success\", type: \"bool\" }],\n },\n {\n name: \"approve\",\n type: \"function\" as const,\n stateMutability: \"nonpayable\" as const,\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"success\", type: \"bool\" }],\n },\n {\n name: \"transferFrom\",\n type: \"function\" as const,\n stateMutability: \"nonpayable\" as const,\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"success\", type: \"bool\" }],\n },\n // ── Read-only ───────────────────────────────────────\n {\n name: \"allowance\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ name: \"remaining\", type: \"uint256\" }],\n },\n {\n name: \"balanceOf\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [{ name: \"owner\", type: \"address\" }],\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n },\n {\n name: \"decimals\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [],\n outputs: [{ name: \"decimals\", type: \"uint8\" }],\n },\n {\n name: \"symbol\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [],\n outputs: [{ name: \"symbol\", type: \"string\" }],\n },\n {\n name: \"name\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [],\n outputs: [{ name: \"name\", type: \"string\" }],\n },\n {\n name: \"totalSupply\",\n type: \"function\" as const,\n stateMutability: \"view\" as const,\n inputs: [],\n outputs: [{ name: \"totalSupply\", type: \"uint256\" }],\n },\n] as const;\n\n/**\n * Canonical function signatures (for manual keccak256-based encoding).\n */\nexport const ERC20_FUNCTION_SIGNATURES = {\n transfer: \"transfer(address,uint256)\",\n approve: \"approve(address,uint256)\",\n transferFrom: \"transferFrom(address,address,uint256)\",\n allowance: \"allowance(address,address)\",\n balanceOf: \"balanceOf(address)\",\n decimals: \"decimals()\",\n symbol: \"symbol()\",\n name: \"name()\",\n totalSupply: \"totalSupply()\",\n} as const;\n\n/**\n * Type helper — extract the ABI items for a given function name.\n */\nexport type AbiItem<TName extends (typeof ERC20_MIN_ABI)[number][\"name\"]> =\n (typeof ERC20_MIN_ABI)[number] & { name: TName };\n","/**\n * ERC20TokenHelper — ABI encoding, RPC queries, and transaction building\n * for ERC-20 tokens.\n *\n * Design:\n * - Zero dependency on viem/ethers for ABI encoding\n * - Uses @noble/hashes/keccak_256 (already in monorepo) for selector computation\n * - All methods are static (composition over inheritance)\n * - Transaction builder methods return raw TransactionRequest objects\n *\n * @see SRS-007\n */\n\nimport { rpcCall } from \"../abortable-fetch\";\nimport { DEFAULT_RPC_URLS } from \"../rpc\";\nimport { ERC20_FUNCTION_SIGNATURES } from \"./abi\";\nimport { ERC20TokenError } from \"./errors\";\nimport type {\n ERC20ApproveTxParams,\n ERC20CallOptions,\n ERC20TransferFromTxParams,\n ERC20TransferTxParams,\n TokenConfig,\n TokenInfo,\n} from \"./types\";\nimport { parseUnits } from \"./units\";\n\n// ── Hex/Padding Utilities ──────────────────────────────────────────\n\n/** Strip 0x prefix from a hex string */\nfunction strip0x(hex: string): string {\n return hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n}\n\n/** Left-pad a hex string (without 0x) to 64 hex chars (32 bytes) */\nfunction padLeftTo32Bytes(hex: string): string {\n return hex.padStart(64, \"0\");\n}\n\n/**\n * Compute keccak256 hash from raw bytes and return as hex string.\n * Uses dynamic import of @noble/hashes to keep no direct import side-effect.\n */\nasync function keccak256Hex(data: Uint8Array): Promise<string> {\n const { keccak_256 } = await import(\"@noble/hashes/sha3\");\n const { bytesToHex } = await import(\"@noble/hashes/utils\");\n return bytesToHex(keccak_256(data));\n}\n\n// ── ABI Encoding ───────────────────────────────────────────────────\n\n/**\n * ABI-encode an address: left-pad to 32 bytes.\n * \"0xabc\" → \"0x0000...000abc\"\n */\nexport function abiEncodeAddress(addr: `0x${string}`): `0x${string}` {\n if (!/^0x[0-9a-fA-F]{40}$/.test(addr)) {\n throw new ERC20TokenError(\n \"invalid_address\",\n `Invalid EVM address: \"${addr}\". Expected 0x-prefixed 40-char hex.`,\n );\n }\n return `0x${padLeftTo32Bytes(strip0x(addr.toLowerCase()))}` as `0x${string}`;\n}\n\n/**\n * ABI-encode a uint256: left-pad to 32 bytes.\n */\nexport function abiEncodeUint256(value: bigint): `0x${string}` {\n if (value < 0n) {\n throw new ERC20TokenError(\n \"invalid_amount\",\n `Cannot encode negative uint256: ${value}`,\n );\n }\n const hex = value.toString(16);\n // Ensure even-length hex\n const paddedHex = hex.length % 2 === 0 ? hex : `0${hex}`;\n return `0x${padLeftTo32Bytes(paddedHex)}` as `0x${string}`;\n}\n\n/**\n * Compute a 4-byte function selector from a canonical function signature.\n *\n * @example\n * abiFunctionSelector(\"transfer(address,uint256)\")\n * // → \"0xa9059cbb\"\n */\nexport async function abiFunctionSelector(\n signature: string,\n): Promise<`0x${string}`> {\n const hash = await keccak256Hex(new TextEncoder().encode(signature));\n return `0x${hash.slice(0, 8)}` as `0x${string}`;\n}\n\n/**\n * Full ABI function call encoding: 4-byte selector + packed args.\n *\n * @example\n * const data = await abiEncodeFunctionCall(\n * \"transfer(address,uint256)\",\n * \"0xRecipientAddress...\",\n * \"0x0000...0001e240\" // already-encoded uint256\n * );\n */\nexport async function abiEncodeFunctionCall(\n signature: string,\n ...encodedArgs: string[]\n): Promise<`0x${string}`> {\n const selector = await abiFunctionSelector(signature);\n const data = encodedArgs.map((a) => strip0x(a)).join(\"\");\n return `${selector}${data}` as `0x${string}`;\n}\n\n/**\n * Convenience: encode a transfer(address,uint256) call.\n */\nasync function encodeTransfer(\n to: `0x${string}`,\n rawAmount: bigint,\n): Promise<`0x${string}`> {\n return abiEncodeFunctionCall(\n ERC20_FUNCTION_SIGNATURES.transfer,\n abiEncodeAddress(to),\n abiEncodeUint256(rawAmount),\n );\n}\n\n/**\n * Convenience: encode an approve(address,uint256) call.\n */\nasync function encodeApprove(\n spender: `0x${string}`,\n rawAmount: bigint,\n): Promise<`0x${string}`> {\n return abiEncodeFunctionCall(\n ERC20_FUNCTION_SIGNATURES.approve,\n abiEncodeAddress(spender),\n abiEncodeUint256(rawAmount),\n );\n}\n\n/**\n * Convenience: encode a transferFrom(address,address,uint256) call.\n */\nasync function encodeTransferFrom(\n from: `0x${string}`,\n to: `0x${string}`,\n rawAmount: bigint,\n): Promise<`0x${string}`> {\n return abiEncodeFunctionCall(\n ERC20_FUNCTION_SIGNATURES.transferFrom,\n abiEncodeAddress(from),\n abiEncodeAddress(to),\n abiEncodeUint256(rawAmount),\n );\n}\n\n// ── RPC Helpers ────────────────────────────────────────────────────\n\n/**\n * Get the RPC URL for a given chain ID.\n */\nfunction getRpcUrl(chainId: number, options?: ERC20CallOptions): string {\n if (options?.rpcUrl) return options.rpcUrl;\n const url = DEFAULT_RPC_URLS[`eip155:${chainId}`];\n if (!url) {\n throw new ERC20TokenError(\n \"rpc_error\",\n `No default RPC URL for chain ID ${chainId}. Provide options.rpcUrl.`,\n );\n }\n return url;\n}\n\n/**\n * Make a JSON-RPC eth_call with 10s timeout.\n */\nasync function ethCall(\n rpcUrl: string,\n to: `0x${string}`,\n data: `0x${string}`,\n): Promise<string> {\n try {\n return await rpcCall<string>(rpcUrl, \"eth_call\", [{ to, data }, \"latest\"]);\n } catch (err) {\n throw new ERC20TokenError(\"rpc_error\", `RPC eth_call error: ${err}`, err);\n }\n}\n\n/**\n * Decode a hex-encoded bytes32 or string result from eth_call.\n * For simple uint256/address returns, just return the raw hex.\n */\nfunction decodeUint256(hex: string): bigint {\n const clean = strip0x(hex);\n return BigInt(`0x${clean}`);\n}\n\nfunction decodeString(hex: string): string {\n const clean = strip0x(hex);\n // ABI-encoded string: offset (32 bytes) + length (32 bytes) + data\n if (clean.length < 128) return \"\";\n const lengthHex = clean.slice(64, 128);\n const length = parseInt(lengthHex, 16);\n const dataHex = clean.slice(128, 128 + length * 2);\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = parseInt(dataHex.slice(i * 2, i * 2 + 2), 16);\n }\n return new TextDecoder().decode(bytes);\n}\n\nfunction decodeUint8(hex: string): number {\n return Number(decodeUint256(hex));\n}\n\n// ── Selector Cache ────────────────────────────────────────────────\n\nconst selectorCache = new Map<string, `0x${string}`>();\n\nasync function getSelector(signature: string): Promise<`0x${string}`> {\n const cached = selectorCache.get(signature);\n if (cached) return cached;\n const selector = await abiFunctionSelector(signature);\n selectorCache.set(signature, selector);\n return selector;\n}\n\n// ── ERC20TokenHelper ──────────────────────────────────────────────\n\nexport class ERC20TokenHelper {\n /**\n * Build a raw ERC-20 transfer TransactionRequest.\n *\n * The returned object can be fed into PocketWallet.sendTransaction()\n * or signed offline.\n */\n static async buildTransferTx(\n params: ERC20TransferTxParams,\n decimals: number,\n ): Promise<{\n to: `0x${string}`;\n from: `0x${string}`;\n data: `0x${string}`;\n value: \"0x0\";\n }> {\n const rawAmount =\n typeof params.amount === \"string\"\n ? parseUnits(params.amount, decimals)\n : params.amount;\n\n const data = await encodeTransfer(params.to, rawAmount);\n\n return {\n to: params.token.address,\n from: params.from,\n data,\n value: \"0x0\",\n };\n }\n\n /**\n * Build a raw ERC-20 approve TransactionRequest.\n */\n static async buildApproveTx(\n params: ERC20ApproveTxParams,\n decimals: number,\n ): Promise<{\n to: `0x${string}`;\n from: `0x${string}`;\n data: `0x${string}`;\n value: \"0x0\";\n }> {\n const rawAmount =\n typeof params.amount === \"string\"\n ? parseUnits(params.amount, decimals)\n : params.amount;\n\n const data = await encodeApprove(params.spender, rawAmount);\n\n return {\n to: params.token.address,\n from: params.owner,\n data,\n value: \"0x0\",\n };\n }\n\n /**\n * Build a raw ERC-20 transferFrom TransactionRequest.\n * Requires the caller to have been approved first.\n */\n static async buildTransferFromTx(\n params: ERC20TransferFromTxParams,\n decimals: number,\n ): Promise<{\n to: `0x${string}`;\n from: `0x${string}`;\n data: `0x${string}`;\n value: \"0x0\";\n }> {\n const rawAmount =\n typeof params.amount === \"string\"\n ? parseUnits(params.amount, decimals)\n : params.amount;\n\n const data = await encodeTransferFrom(params.from, params.to, rawAmount);\n\n return {\n to: params.token.address,\n from: params.from,\n data,\n value: \"0x0\",\n };\n }\n\n /**\n * Call allowance(address,address) on-chain.\n * Returns remaining allowance in smallest unit (bigint).\n */\n static async getAllowance(\n token: TokenConfig,\n owner: `0x${string}`,\n spender: `0x${string}`,\n options?: ERC20CallOptions,\n ): Promise<bigint> {\n const rpcUrl = getRpcUrl(token.chainId, options);\n\n const selector = await getSelector(ERC20_FUNCTION_SIGNATURES.allowance);\n const data =\n `${selector}${strip0x(abiEncodeAddress(owner))}${strip0x(abiEncodeAddress(spender))}` as `0x${string}`;\n\n const result = await ethCall(rpcUrl, token.address, data);\n return decodeUint256(result);\n }\n\n /**\n * Fetch token metadata (name, symbol, decimals, totalSupply) from chain.\n * Makes 4 parallel RPC calls.\n */\n static async getTokenInfo(\n token: TokenConfig,\n options?: ERC20CallOptions,\n ): Promise<TokenInfo> {\n const rpcUrl = getRpcUrl(token.chainId, options);\n const to = token.address;\n\n const nameSelector = await getSelector(ERC20_FUNCTION_SIGNATURES.name);\n const symbolSelector = await getSelector(ERC20_FUNCTION_SIGNATURES.symbol);\n const decimalsSelector = await getSelector(\n ERC20_FUNCTION_SIGNATURES.decimals,\n );\n const totalSupplySelector = await getSelector(\n ERC20_FUNCTION_SIGNATURES.totalSupply,\n );\n\n const call = async (data: `0x${string}`) => ethCall(rpcUrl, to, data);\n\n try {\n const [nameRaw, symbolRaw, decimalsRaw, totalSupplyRaw] =\n await Promise.all([\n call(nameSelector),\n call(symbolSelector),\n call(decimalsSelector),\n call(totalSupplySelector),\n ]);\n\n const name = decodeString(nameRaw);\n const symbol = decodeString(symbolRaw);\n const decimals = decodeUint8(decimalsRaw);\n const totalSupply = decodeUint256(totalSupplyRaw);\n\n return { name, symbol, decimals, totalSupply };\n } catch (err) {\n if (err instanceof ERC20TokenError) throw err;\n throw new ERC20TokenError(\n \"token_info_fetch_failed\",\n \"Failed to fetch token metadata from chain.\",\n err,\n );\n }\n }\n\n /**\n * Check if a token is deployed on the target chain.\n * Returns true if the contract has code (extcodesize > 0).\n */\n static async isTokenDeployed(\n token: TokenConfig,\n options?: ERC20CallOptions,\n ): Promise<boolean> {\n const rpcUrl = getRpcUrl(token.chainId, options);\n\n try {\n const code = await rpcCall<string>(rpcUrl, \"eth_getCode\", [\n token.address,\n \"latest\",\n ]);\n return code !== \"0x\" && code !== \"0x0\";\n } catch (err) {\n throw new ERC20TokenError(\n \"rpc_error\",\n `RPC eth_getCode error: ${err}`,\n err,\n );\n }\n }\n\n /**\n * Fetch token decimals from chain (or return cached value).\n */\n static async getDecimals(\n token: TokenConfig,\n options?: ERC20CallOptions,\n ): Promise<number> {\n if (token.decimals !== undefined) {\n return token.decimals;\n }\n\n const rpcUrl = getRpcUrl(token.chainId, options);\n const selector = await getSelector(ERC20_FUNCTION_SIGNATURES.decimals);\n const data = selector;\n\n try {\n const result = await ethCall(rpcUrl, token.address, data);\n return decodeUint8(result);\n } catch (err) {\n throw new ERC20TokenError(\n \"decimals_fetch_failed\",\n `Failed to fetch decimals for token ${token.address} on chain ${token.chainId}.`,\n err,\n );\n }\n }\n\n /**\n * Convenience: parse a human-readable amount to raw units using the token's decimals.\n */\n static async parseToRawAmount(\n token: TokenConfig,\n amount: string | number,\n options?: ERC20CallOptions,\n ): Promise<bigint> {\n const decimals = await ERC20TokenHelper.getDecimals(token, options);\n return parseUnits(amount, decimals);\n }\n\n /**\n * Convenience: format a raw bigint amount to a human-readable string using the token's decimals.\n */\n static async formatRawAmount(\n token: TokenConfig,\n rawAmount: bigint,\n options?: ERC20CallOptions,\n ): Promise<string> {\n const decimals = await ERC20TokenHelper.getDecimals(token, options);\n const { formatUnits } = await import(\"./units\");\n return formatUnits(rawAmount, decimals);\n }\n}\n","/**\n * SimulationManager — Central orchestrator for transaction simulation.\n *\n * Dispatches simulation requests to the appropriate provider based on\n * configuration and chain support. Handles:\n * - Provider selection (auto / eth_call / blowfish)\n * - Graceful fallback when a provider is unavailable\n * - Convenience methods like simulateERC20Transfer\n *\n * Integration points:\n * - wallet-engine: PocketWallet.simulateTransaction()\n * - Token helper (SRS-007): Builds calldata for ERC-20 transfers\n * - TxMonitor (SRS-008): Compares simulation vs actual results\n *\n * @see /docs/features/transaction-simulation.md §6.3\n */\n\nimport { DEFAULT_RPC_URLS } from \"../rpc\";\nimport { ERC20TokenHelper } from \"../token/ERC20TokenHelper\";\nimport type { TokenConfig } from \"../token/types\";\nimport { BlowfishProvider } from \"./providers/BlowfishProvider\";\nimport { EthCallProvider } from \"./providers/EthCallProvider\";\nimport type { SimulationProvider } from \"./providers/types\";\nimport type {\n ApprovalChange,\n BalanceChange,\n GasInfo,\n RiskAssessment,\n SimulationConfig,\n SimulationProviderName,\n SimulationResult,\n TransactionDescriptor,\n} from \"./types\";\n\n// ── Default Risk Assessment for Unavailable State ─────────────────\n\nconst DEFAULT_UNAVAILABLE_RISK: RiskAssessment = {\n level: \"unknown\",\n score: 0,\n warnings: [],\n};\n\n// ── SimulationManager ─────────────────────────────────────────────\n\nexport class SimulationManager {\n private providers: Map<SimulationProviderName, SimulationProvider> =\n new Map();\n private _defaultProvider: SimulationProviderName;\n private _enabled: boolean;\n private blowfishApiKey?: string;\n\n constructor(config?: SimulationConfig) {\n this._enabled = config?.enabled ?? true;\n this._defaultProvider = config?.defaultProvider ?? \"auto\";\n this.blowfishApiKey = config?.blowfishApiKey;\n\n // Always register eth_call provider\n this.providers.set(\"eth_call\", new EthCallProvider(config?.rpcUrl));\n\n // Register Blowfish if API key is provided\n if (this.blowfishApiKey) {\n this.providers.set(\"blowfish\", new BlowfishProvider(this.blowfishApiKey));\n }\n }\n\n // ── Public API ──────────────────────────────────────────────────\n\n /**\n * Main simulation entry point.\n *\n * Routes to the best available provider based on config and chain support.\n * Falls back to eth_call if Blowfish is unavailable for the chain.\n *\n * @param tx - Transaction to simulate\n * @param from - Sender address\n * @param options - Optional chainId, rpcUrl, origin\n */\n async simulate(\n tx: TransactionDescriptor,\n from: `0x${string}`,\n options?: {\n chainId?: number;\n origin?: string;\n rpcUrl?: string;\n },\n ): Promise<SimulationResult> {\n if (!this._enabled) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: { ...DEFAULT_UNAVAILABLE_RISK },\n provider: \"auto\",\n summary: \"Simulation is disabled\",\n changesDetected: false,\n };\n }\n\n const chainId = options?.chainId ?? this._estimateChainId(from);\n const provider = this._selectProvider(chainId);\n\n if (!provider) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n ...DEFAULT_UNAVAILABLE_RISK,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"low\",\n message: \"No simulation provider available for this chain\",\n },\n ],\n },\n provider: \"auto\",\n summary: \"No simulation provider available\",\n changesDetected: false,\n };\n }\n\n const rpcUrl = options?.rpcUrl ?? this._resolveRpcUrl(chainId);\n\n // Try primary provider\n const result = await provider.simulate(tx, from, {\n origin: options?.origin,\n rpcUrl,\n });\n\n // If primary provider is unavailable and we have a fallback, retry\n if (result.status === \"unavailable\" && provider.name !== \"eth_call\") {\n const fallback = this.providers.get(\"eth_call\");\n if (fallback) {\n const fallbackResult = await fallback.simulate(tx, from, { rpcUrl });\n return {\n ...fallbackResult,\n // Preserve the unavailable warnings from the primary provider\n riskAssessment: {\n ...fallbackResult.riskAssessment,\n warnings: [\n ...result.riskAssessment.warnings,\n ...fallbackResult.riskAssessment.warnings,\n ],\n },\n };\n }\n }\n\n return result;\n }\n\n /**\n * Convenience: simulate an ERC-20 token transfer.\n *\n * Builds the transfer calldata using ERC20TokenHelper (SRS-007),\n * then runs the simulation.\n *\n * @param token - Token to transfer\n * @param from - Sender address\n * @param to - Recipient address\n * @param amount - Amount in human-readable units (e.g. \"1.50\")\n * @param chainId - Chain ID\n */\n async simulateERC20Transfer(\n token: TokenConfig,\n from: `0x${string}`,\n to: `0x${string}`,\n amount: string,\n chainId: number,\n ): Promise<SimulationResult> {\n try {\n // Build transfer calldata using ERC20TokenHelper\n const decimals =\n token.decimals ?? (await ERC20TokenHelper.getDecimals(token));\n const tx = await ERC20TokenHelper.buildTransferTx(\n { token, from, to, amount },\n decimals,\n );\n\n // Simulate the transfer\n return this.simulate(\n {\n to: tx.to,\n data: tx.data,\n value: \"0x0\",\n from,\n },\n from,\n { chainId },\n );\n } catch (err) {\n return {\n status: \"unavailable\",\n balanceChanges: [],\n approvalChanges: [],\n riskAssessment: {\n ...DEFAULT_UNAVAILABLE_RISK,\n warnings: [\n {\n category: \"simulation_failed\",\n severity: \"low\",\n message: `Failed to build transfer calldata: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n },\n provider: \"auto\",\n summary: \"Failed to prepare simulation\",\n changesDetected: false,\n };\n }\n }\n\n /**\n * Check whether simulation is available for a given chain.\n */\n isAvailable(chainId: number): boolean {\n if (!this._enabled) return false;\n const provider = this._selectProvider(chainId);\n return provider !== undefined;\n }\n\n /**\n * Enable or disable simulation globally.\n */\n setEnabled(enabled: boolean): void {\n this._enabled = enabled;\n }\n\n /**\n * Get whether simulation is currently enabled.\n */\n get enabled(): boolean {\n return this._enabled;\n }\n\n // ── Provider Management ─────────────────────────────────────────\n\n /**\n * Register a custom provider.\n * Useful for testing or third-party providers.\n */\n registerProvider(\n name: SimulationProviderName,\n provider: SimulationProvider,\n ): void {\n this.providers.set(name, provider);\n }\n\n /**\n * Add or update a Blowfish API key at runtime.\n */\n setBlowfishApiKey(apiKey: string): void {\n this.blowfishApiKey = apiKey;\n this.providers.set(\"blowfish\", new BlowfishProvider(apiKey));\n }\n\n /**\n * Remove a registered provider.\n */\n unregisterProvider(name: SimulationProviderName): void {\n this.providers.delete(name);\n }\n\n // ── Internal: Provider Selection ────────────────────────────────\n\n /**\n * Select the best provider for the given chain.\n *\n * Selection rules:\n * - \"auto\": Try blowfish first (if registered + chain supported),\n * fall back to eth_call\n * - \"blowfish\": Use blowfish if available\n * - \"eth_call\": Always available on EVM\n */\n private _selectProvider(chainId: number): SimulationProvider | undefined {\n if (this._defaultProvider === \"eth_call\") {\n return this.providers.get(\"eth_call\");\n }\n\n if (this._defaultProvider === \"blowfish\") {\n return this.providers.get(\"blowfish\");\n }\n\n // \"auto\" mode: prefer Blowfish, fall back to eth_call\n const blowfish = this.providers.get(\"blowfish\");\n if (blowfish && blowfish.isAvailable(chainId)) {\n return blowfish;\n }\n\n return this.providers.get(\"eth_call\");\n }\n\n /**\n * Estimate chain ID from the from address or config.\n * Best-effort; returns 0 if unknown.\n */\n private _estimateChainId(_from: `0x${string}`): number {\n // In a full implementation, this would check the session manager\n // or chain registry. For now, return 0 to match \"all chains\".\n return 0;\n }\n\n /**\n * Resolve an RPC URL for the eth_call fallback provider.\n */\n private _resolveRpcUrl(chainId: number): string | undefined {\n if (chainId > 0) {\n return DEFAULT_RPC_URLS[`eip155:${chainId}`];\n }\n return undefined;\n }\n}\n\n// ── Simulation vs Actual Comparison (SRS-008 Integration) ─────────\n\n/**\n * Compare simulation results with actual transaction receipt.\n *\n * Used by TxMonitor to detect discrepancies between simulated and\n * actual transaction outcomes.\n *\n * @param simulation - The simulation result\n * @param actualStatus - Actual tx receipt status (\"success\" | \"reverted\")\n * @returns Match result\n */\nexport function compareSimulationVsActual(\n simulation: SimulationResult,\n actualStatus: \"success\" | \"reverted\",\n): { match: boolean; discrepancies?: string[] } {\n const discrepancies: string[] = [];\n\n if (simulation.status === \"success\" && actualStatus === \"reverted\") {\n discrepancies.push(\"Simulation predicted success but transaction reverted\");\n }\n\n if (simulation.status === \"reverted\" && actualStatus === \"success\") {\n discrepancies.push(\"Simulation predicted revert but transaction succeeded\");\n }\n\n return {\n match: discrepancies.length === 0,\n discrepancies: discrepancies.length > 0 ? discrepancies : undefined,\n };\n}\n","/**\n * Token Module — ERC-20 transaction building, amount formatting, and queries.\n *\n * @see SRS-007\n */\n\nexport type { AbiItem } from \"./abi\";\nexport { ERC20_FUNCTION_SIGNATURES, ERC20_MIN_ABI } from \"./abi\";\nexport {\n abiEncodeAddress,\n abiEncodeFunctionCall,\n abiEncodeUint256,\n abiFunctionSelector,\n ERC20TokenHelper,\n} from \"./ERC20TokenHelper\";\nexport type { ERC20TokenErrorCode } from \"./errors\";\n\nexport { ERC20TokenError, isERC20TokenError } from \"./errors\";\nexport type {\n ERC20ApproveTxParams,\n ERC20CallOptions,\n ERC20TransferFromTxParams,\n ERC20TransferTxParams,\n TokenConfig,\n TokenInfo,\n} from \"./types\";\nexport { formatUnits, parseUnits } from \"./units\";\n","/**\n * Auto-detect — fetch token metadata from chain and cache to localStorage.\n *\n * Uses ERC20TokenHelper.getTokenInfo() to retrieve name, symbol, decimals.\n * Results are cached in localStorage to avoid repeated RPC calls.\n */\n\nimport { createStorageAdapter, type StorageAdapter } from \"../storage\";\nimport type { TokenListEntry } from \"./types\";\n\nconst CACHE_KEY = \"naculus_auto_detected_tokens\";\nconst DEFAULT_CACHE_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days\n\ninterface CachedEntry {\n token: TokenListEntry;\n timestamp: number;\n}\n\n/**\n * A minimal on-chain token fetcher compatible with Node and browser.\n *\n * Makes eth_call RPC requests to invoke standard ERC-20 functions:\n * name(), symbol(), decimals()\n */\nexport async function detectTokenInfo(\n address: string,\n chainId: number,\n rpcUrl: string,\n options?: { skipCache?: boolean },\n): Promise<TokenListEntry> {\n // Check cache first\n if (!options?.skipCache) {\n const cached = await getFromCache(address, chainId);\n if (cached) return cached;\n }\n\n // Normalize address\n const addr = address.startsWith(\"0x\")\n ? (address as `0x${string}`)\n : `0x${address}`;\n\n // Build selectors and eth_call data for name, symbol, decimals\n const nameData = \"0x06fdde03\"; // keccak256(\"name()\")[0:4]\n const symbolData = \"0x95d89b41\"; // keccak256(\"symbol()\")[0:4]\n const decimalsData = \"0x313ce567\"; // keccak256(\"decimals()\")[0:4]\n\n const [nameRaw, symbolRaw, decimalsRaw] = await Promise.all([\n ethCall(rpcUrl, addr as `0x${string}`, nameData),\n ethCall(rpcUrl, addr as `0x${string}`, symbolData),\n ethCall(rpcUrl, addr as `0x${string}`, decimalsData),\n ]);\n\n const token: TokenListEntry = {\n address: addr,\n chainId,\n name: decodeString(nameRaw),\n symbol: decodeString(symbolRaw),\n decimals: decodeUint8(decimalsRaw),\n source: \"auto-detect\",\n tags: [\"custom\"],\n };\n\n // Cache the result\n await saveToCache(token);\n\n return token;\n}\n\n/**\n * Clear the auto-detect cache.\n */\nexport async function clearAutoDetectCache(): Promise<void> {\n const storage = createStorageAdapter(\"local\", \"\");\n await storage.remove(CACHE_KEY);\n}\n\n// ── Cache Helpers ─────────────────────────────────────────────────\n\nasync function getFromCache(\n address: string,\n chainId: number,\n): Promise<TokenListEntry | null> {\n const storage = createStorageAdapter(\"local\", \"\");\n try {\n const data = await storage.get<Record<string, CachedEntry>>(CACHE_KEY);\n if (!data) return null;\n\n const key = `${chainId}:${address.toLowerCase()}`;\n const entry = data[key];\n if (!entry) return null;\n\n // Check TTL\n if (Date.now() - entry.timestamp > DEFAULT_CACHE_TTL) {\n return null;\n }\n\n return entry.token;\n } catch {\n return null;\n }\n}\n\nasync function saveToCache(token: TokenListEntry): Promise<void> {\n const storage = createStorageAdapter(\"local\", \"\");\n try {\n const data =\n (await storage.get<Record<string, CachedEntry>>(CACHE_KEY)) ?? {};\n const key = `${token.chainId}:${token.address.toLowerCase()}`;\n data[key] = { token, timestamp: Date.now() };\n await storage.set(CACHE_KEY, data);\n } catch {\n // Non-fatal\n }\n}\n\n// ── RPC Helpers ───────────────────────────────────────────────────\n\nasync function ethCall(\n rpcUrl: string,\n to: `0x${string}`,\n data: `0x${string}`,\n): Promise<string> {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"eth_call\",\n params: [{ to, data }, \"latest\"],\n }),\n });\n\n if (!res.ok) {\n throw new Error(`RPC call failed: HTTP ${res.status}`);\n }\n\n const json: any = await res.json();\n if (json.error) {\n throw new Error(`RPC error: ${json.error.message}`);\n }\n\n return json.result as string;\n}\n\nfunction decodeString(hex: string): string {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n\n // ABI-encoded string: offset (32 bytes) + length (32 bytes) + data\n if (clean.length < 128) {\n // Try raw bytes decoding as fallback\n try {\n const bytes = Buffer.from(clean, \"hex\");\n return new TextDecoder().decode(bytes).replace(/\\0/g, \"\");\n } catch {\n return \"\";\n }\n }\n\n const lengthHex = clean.slice(64, 128);\n const length = parseInt(lengthHex, 16);\n if (length <= 0 || length * 2 > clean.length - 128) return \"\";\n\n const dataHex = clean.slice(128, 128 + length * 2);\n const bytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n bytes[i] = parseInt(dataHex.slice(i * 2, i * 2 + 2), 16);\n }\n return new TextDecoder().decode(bytes);\n}\n\nfunction decodeUint8(hex: string): number {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n return parseInt(clean || \"0\", 16);\n}\n","/**\n * Built-in default token lists.\n *\n * Only includes the most common tokens to keep the bundle small.\n * Full lists (Uniswap, Coinbase, Jupiter) are loaded from remote sources.\n */\n\nimport type { TokenListEntry, TokenListSource } from \"./types\";\n\n/**\n * Popular Ethereum mainnet tokens (chainId = 1).\n */\nexport const ETHEREUM_MAINNET_TOKENS: TokenListEntry[] = [\n {\n chainId: 1,\n address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n name: \"Wrapped Ether\",\n symbol: \"WETH\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/ethereum-eth-logo.png\",\n tags: [\"wrapped\", \"gas-token\"],\n },\n {\n chainId: 1,\n address: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n name: \"USD Coin\",\n symbol: \"USDC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 1,\n address: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n name: \"Tether USD\",\n symbol: \"USDT\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/tether-usdt-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 1,\n address: \"0x6B175474E89094C44Da98b954EedeAC495271d0F\",\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 1,\n address: \"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599\",\n name: \"Wrapped Bitcoin\",\n symbol: \"WBTC\",\n decimals: 8,\n logoURI: \"https://cryptologos.cc/logos/wrapped-bitcoin-wbtc-logo.png\",\n tags: [\"wrapped\", \"btc\"],\n },\n {\n chainId: 1,\n address: \"0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9\",\n name: \"Aave\",\n symbol: \"AAVE\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/aave-aave-logo.png\",\n tags: [\"defi\"],\n },\n {\n chainId: 1,\n address: \"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984\",\n name: \"Uniswap\",\n symbol: \"UNI\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/uniswap-uni-logo.png\",\n tags: [\"defi\"],\n },\n {\n chainId: 1,\n address: \"0x514910771AF9Ca656af840dff83E8264EcF986CA\",\n name: \"ChainLink Token\",\n symbol: \"LINK\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/chainlink-link-logo.png\",\n tags: [\"oracle\"],\n },\n {\n chainId: 1,\n address: \"0x853d955aCEf822Db058eb8505911ED77F175b99e\",\n name: \"Frax\",\n symbol: \"FRAX\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/frax-frax-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 1,\n address: \"0x4Fabb145d64652a948d72533023f6E7A623C7C53\",\n name: \"Binance USD\",\n symbol: \"BUSD\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/binance-usd-busd-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 1,\n address: \"0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b\",\n name: \"Cronos Token\",\n symbol: \"CRO\",\n decimals: 8,\n logoURI: \"https://cryptologos.cc/logos/crypto-com-coin-cro-logo.png\",\n tags: [],\n },\n {\n chainId: 1,\n address: \"0x3845badAde8e6dFF049820680d1F14bD3903a5d0\",\n name: \"The Sandbox\",\n symbol: \"SAND\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/the-sandbox-sand-logo.png\",\n tags: [\"gaming\"],\n },\n {\n chainId: 1,\n address: \"0x0D8775F648430679A709E98d2b0Cb6250d2887EF\",\n name: \"Basic Attention Token\",\n symbol: \"BAT\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/basic-attention-token-bat-logo.png\",\n tags: [\"privacy\"],\n },\n {\n chainId: 1,\n address: \"0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0\",\n name: \"Polygon\",\n symbol: \"MATIC\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/polygon-matic-logo.png\",\n tags: [\"layer2\"],\n },\n];\n\n/**\n * Popular Polygon (chainId 137) tokens.\n */\nexport const POLYGON_TOKENS: TokenListEntry[] = [\n {\n chainId: 137,\n address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\",\n name: \"Wrapped MATIC\",\n symbol: \"WMATIC\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/polygon-matic-logo.png\",\n tags: [\"wrapped\", \"gas-token\"],\n },\n {\n chainId: 137,\n address: \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\n name: \"USD Coin (PoS)\",\n symbol: \"USDC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 137,\n address: \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\",\n name: \"Tether USD (PoS)\",\n symbol: \"USDT\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/tether-usdt-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 137,\n address: \"0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063\",\n name: \"Dai Stablecoin (PoS)\",\n symbol: \"DAI\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 137,\n address: \"0x1BFd67037B42Cf73acF2047067bd4F2C47D9BfD6\",\n name: \"Wrapped BTC (PoS)\",\n symbol: \"WBTC\",\n decimals: 8,\n logoURI: \"https://cryptologos.cc/logos/wrapped-bitcoin-wbtc-logo.png\",\n tags: [\"wrapped\", \"btc\"],\n },\n {\n chainId: 137,\n address: \"0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619\",\n name: \"Wrapped Ether (PoS)\",\n symbol: \"WETH\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/ethereum-eth-logo.png\",\n tags: [\"wrapped\"],\n },\n {\n chainId: 137,\n address: \"0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39\",\n name: \"ChainLink Token (PoS)\",\n symbol: \"LINK\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/chainlink-link-logo.png\",\n tags: [\"oracle\"],\n },\n];\n\n/**\n * Optimism (chainId 10) tokens.\n */\nexport const OPTIMISM_TOKENS: TokenListEntry[] = [\n {\n chainId: 10,\n address: \"0x4200000000000000000000000000000000000006\",\n name: \"Wrapped Ether\",\n symbol: \"WETH\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/ethereum-eth-logo.png\",\n tags: [\"wrapped\", \"gas-token\"],\n },\n {\n chainId: 10,\n address: \"0x7F5c764cBc14f9669B88837ca1490cCa17c31607\",\n name: \"USD Coin (Optimism)\",\n symbol: \"USDC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 10,\n address: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n name: \"Tether USD (Optimism)\",\n symbol: \"USDT\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/tether-usdt-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 10,\n address: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n name: \"Dai Stablecoin (Optimism)\",\n symbol: \"DAI\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 10,\n address: \"0x4200000000000000000000000000000000000042\",\n name: \"Optimism\",\n symbol: \"OP\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/optimism-ethereum-op-logo.png\",\n tags: [\"layer2\"],\n },\n];\n\n/**\n * Arbitrum (chainId 42161) tokens.\n */\nexport const ARBITRUM_TOKENS: TokenListEntry[] = [\n {\n chainId: 42161,\n address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\",\n name: \"Wrapped Ether\",\n symbol: \"WETH\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/ethereum-eth-logo.png\",\n tags: [\"wrapped\", \"gas-token\"],\n },\n {\n chainId: 42161,\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin (Arbitrum)\",\n symbol: \"USDC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 42161,\n address: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n name: \"Tether USD (Arbitrum)\",\n symbol: \"USDT\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/tether-usdt-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 42161,\n address: \"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1\",\n name: \"Dai Stablecoin (Arbitrum)\",\n symbol: \"DAI\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 42161,\n address: \"0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f\",\n name: \"Wrapped BTC (Arbitrum)\",\n symbol: \"WBTC\",\n decimals: 8,\n logoURI: \"https://cryptologos.cc/logos/wrapped-bitcoin-wbtc-logo.png\",\n tags: [\"wrapped\", \"btc\"],\n },\n {\n chainId: 42161,\n address: \"0x912CE59144191C1204E64559FE8253a0e49E6548\",\n name: \"Arbitrum\",\n symbol: \"ARB\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/arbitrum-arb-logo.png\",\n tags: [\"layer2\"],\n },\n];\n\n/**\n * Base (chainId 8453) tokens.\n */\nexport const BASE_TOKENS: TokenListEntry[] = [\n {\n chainId: 8453,\n address: \"0x4200000000000000000000000000000000000006\",\n name: \"Wrapped Ether\",\n symbol: \"WETH\",\n decimals: 18,\n logoURI: \"https://cryptologos.cc/logos/ethereum-eth-logo.png\",\n tags: [\"wrapped\", \"gas-token\"],\n },\n {\n chainId: 8453,\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin (Base)\",\n symbol: \"USDC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\"],\n },\n {\n chainId: 8453,\n address: \"0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA\",\n name: \"USD Base Coin\",\n symbol: \"USDbC\",\n decimals: 6,\n logoURI: \"https://cryptologos.cc/logos/usd-coin-usdc-logo.png\",\n tags: [\"stablecoin\", \"bridged\"],\n },\n];\n\n/**\n * All built-in tokens aggregated by chain ID.\n */\nexport const DEFAULT_BUILTIN_TOKENS: Record<number, TokenListEntry[]> = {\n 1: ETHEREUM_MAINNET_TOKENS,\n 137: POLYGON_TOKENS,\n 10: OPTIMISM_TOKENS,\n 42161: ARBITRUM_TOKENS,\n 8453: BASE_TOKENS,\n};\n\n/**\n * All built-in tokens as a flat array.\n */\nexport function getAllBuiltinTokens(): TokenListEntry[] {\n return Object.values(DEFAULT_BUILTIN_TOKENS).flat();\n}\n\n/**\n * Default sources for TokenListManager.\n *\n * - Built-in (inline): always available, no network fetch needed\n * - Uniswap Default: loaded from remote URL on first use\n * - Coinbase: loaded from remote URL on first use\n */\nexport const DEFAULT_SOURCES: TokenListSource[] = [\n {\n name: \"built-in\",\n tokens: getAllBuiltinTokens(),\n enabled: true,\n },\n {\n name: \"uniswap-default\",\n url: \"https://tokens.uniswap.org\",\n enabled: true,\n refreshInterval: 24 * 60 * 60 * 1000, // 24h\n },\n {\n name: \"coinbase\",\n url: \"https://api.coinbase.com/v2/tokens\",\n enabled: false,\n refreshInterval: 24 * 60 * 60 * 1000,\n },\n];\n","/**\n * TokenListManager — load, merge, cache, and search token lists.\n *\n * Supports multiple sources (built-in, Uniswap, Coinbase, custom).\n * Deduplicates by (chainId, address) with configurable source priority.\n * Caches merged results to localStorage.\n */\n\nimport { createStorageAdapter, type StorageAdapter } from \"../storage\";\nimport { DEFAULT_SOURCES } from \"./lists\";\nimport type {\n TokenList,\n TokenListEntry,\n TokenListManagerConfig,\n TokenListSource,\n TokenListSourceStatus,\n TokenMatch,\n TokenSearchResult,\n} from \"./types\";\n\nconst DEFAULT_CACHE_KEY = \"naculus_token_list_cache\";\nconst DEFAULT_CACHE_TTL = 24 * 60 * 60 * 1000; // 24h\nconst DEFAULT_FETCH_TIMEOUT = 10000; // 10s\n\ninterface CachedData {\n timestamp: number;\n tokens: TokenListEntry[];\n}\n\nexport class TokenListManager {\n private config: TokenListManagerConfig;\n private tokens: TokenListEntry[] = [];\n private sourceStatus: Map<string, TokenListSourceStatus> = new Map();\n private storage: StorageAdapter;\n\n constructor(config?: Partial<TokenListManagerConfig>) {\n this.config = {\n sources: config?.sources ?? DEFAULT_SOURCES,\n cacheKey: config?.cacheKey ?? DEFAULT_CACHE_KEY,\n cacheTtl: config?.cacheTtl ?? DEFAULT_CACHE_TTL,\n sourcePriority: config?.sourcePriority,\n fetchTimeout: config?.fetchTimeout ?? DEFAULT_FETCH_TIMEOUT,\n };\n\n this.storage = createStorageAdapter(\"local\", \"\");\n\n // Initialize source statuses\n for (const source of this.config.sources) {\n this.sourceStatus.set(source.name, {\n name: source.name,\n enabled: source.enabled,\n state: \"loading\",\n tokenCount: 0,\n lastUpdated: null,\n });\n }\n }\n\n /**\n * Load all enabled sources.\n * Checks cache first, falls back to in-memory or failed-source stale data.\n */\n async load(): Promise<TokenListEntry[]> {\n // 1. Check cache\n const cached = await this.loadFromCache();\n if (cached && !this.isCacheExpired(cached.timestamp)) {\n this.tokens = cached.tokens;\n this.updateSourceStatuses(\"loaded\");\n return this.tokens;\n }\n\n // 2. Fetch from all enabled sources in parallel\n const enabledSources = this.config.sources.filter((s) => s.enabled);\n const results = await Promise.allSettled(\n enabledSources.map((source) => this.fetchSource(source)),\n );\n\n // 3. Merge results\n const allTokens: TokenListEntry[] = [];\n for (let i = 0; i < enabledSources.length; i++) {\n const result = results[i];\n const source = enabledSources[i];\n if (result.status === \"fulfilled\") {\n allTokens.push(...result.value);\n this.sourceStatus.set(source.name, {\n name: source.name,\n enabled: source.enabled,\n state: \"loaded\",\n tokenCount: result.value.length,\n lastUpdated: Date.now(),\n });\n } else {\n // Source failed — use stale cache tokens for this source if available\n const stale = await this.loadFromCache();\n const staleTokens =\n stale?.tokens.filter((t) => t.source === source.name) ?? [];\n allTokens.push(...staleTokens);\n\n this.sourceStatus.set(source.name, {\n name: source.name,\n enabled: source.enabled,\n state: \"error\",\n tokenCount: staleTokens.length,\n lastUpdated: stale?.timestamp ?? null,\n error:\n result.reason instanceof Error\n ? result.reason.message\n : String(result.reason),\n });\n }\n }\n\n // 4. Deduplicate and store\n this.tokens = this.deduplicate(allTokens);\n\n // 5. Cache\n await this.saveToCache(this.tokens);\n\n return this.tokens;\n }\n\n /**\n * Force-refresh all sources, bypassing cache.\n */\n async refresh(): Promise<TokenListEntry[]> {\n // Clear in-memory cache so load re-fetches\n this.tokens = [];\n return this.load();\n }\n\n /**\n * Get all loaded tokens, optionally filtered.\n */\n getTokens(options?: { chainId?: number; source?: string }): TokenListEntry[] {\n let result = this.tokens;\n\n if (options?.chainId !== undefined) {\n result = result.filter((t) => t.chainId === options.chainId);\n }\n\n if (options?.source !== undefined) {\n result = result.filter((t) => t.source === options.source);\n }\n\n return result;\n }\n\n /**\n * Search tokens by symbol, name, or address.\n */\n search(\n query: string,\n options?: { chainId?: number; limit?: number },\n ): TokenSearchResult {\n const limit = options?.limit ?? 20;\n const q = query.trim().toLowerCase();\n\n if (!q) {\n return { exact: [], fuzzy: [], hasMore: false };\n }\n\n const exact: TokenMatch[] = [];\n const fuzzy: TokenMatch[] = [];\n\n let candidates = this.tokens;\n if (options?.chainId !== undefined) {\n candidates = candidates.filter((t) => t.chainId === options.chainId);\n }\n\n // Check if query looks like an address\n const isAddress =\n /^0x[0-9a-fA-F]{40}$/.test(q) || /^0x[0-9a-fA-F]{40}$/.test(query.trim());\n\n for (const token of candidates) {\n if (isAddress) {\n // Exact address match (case-insensitive)\n if (token.address.toLowerCase() === q) {\n exact.push({\n token,\n score: 1.0,\n matchField: \"address\",\n });\n }\n continue;\n }\n\n const sym = token.symbol.toLowerCase();\n const name = token.name.toLowerCase();\n\n // Exact symbol match (case-insensitive)\n if (sym === q) {\n exact.push({\n token,\n score: 1.0,\n matchField: \"symbol\",\n });\n continue;\n }\n\n // Exact name match\n if (name === q) {\n exact.push({\n token,\n score: 0.95,\n matchField: \"name\",\n });\n continue;\n }\n\n // Fuzzy: symbol starts with query\n if (sym.startsWith(q)) {\n fuzzy.push({\n token,\n score: 0.8,\n matchField: \"symbol\",\n });\n continue;\n }\n\n // Fuzzy: name includes query (word boundary)\n if (name.includes(q)) {\n fuzzy.push({\n token,\n score: 0.6,\n matchField: \"name\",\n });\n continue;\n }\n\n // Fuzzy: symbol includes query\n if (sym.includes(q)) {\n fuzzy.push({\n token,\n score: 0.4,\n matchField: \"symbol\",\n });\n }\n }\n\n // Sort: exact first, then fuzzy by score descending\n exact.sort((a, b) => b.score - a.score);\n fuzzy.sort((a, b) => b.score - a.score);\n\n const total = exact.length + fuzzy.length;\n const hasMore = total > limit;\n\n // Slice both arrays proportionally\n const exactSlice = exact.slice(\n 0,\n Math.min(exact.length, Math.ceil(limit / 2)),\n );\n const remaining = limit - exactSlice.length;\n const fuzzySlice = fuzzy.slice(0, remaining);\n\n return { exact: exactSlice, fuzzy: fuzzySlice, hasMore };\n }\n\n /**\n * Get a single token by address and chain ID.\n */\n getToken(address: string, chainId: number): TokenListEntry | undefined {\n return this.tokens.find(\n (t) =>\n t.address.toLowerCase() === address.toLowerCase() &&\n t.chainId === chainId,\n );\n }\n\n /**\n * Clear all caches.\n */\n clearCache(): void {\n this.tokens = [];\n this.storage.remove(this.config.cacheKey!);\n this.sourceStatus.clear();\n }\n\n /**\n * Get status of all registered sources.\n */\n getSourcesStatus(): TokenListSourceStatus[] {\n return Array.from(this.sourceStatus.values());\n }\n\n // ── Private ─────────────────────────────────────────────────────\n\n private async fetchSource(\n source: TokenListSource,\n ): Promise<TokenListEntry[]> {\n // Inline tokens — no network fetch needed\n if (source.tokens && source.tokens.length > 0) {\n return source.tokens.map((t) => ({ ...t, source: source.name }));\n }\n\n if (!source.url) {\n return [];\n }\n\n // Remote URL fetch\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n this.config.fetchTimeout,\n );\n\n try {\n const res = await fetch(source.url, { signal: controller.signal });\n\n if (!res.ok) {\n throw new Error(\n `Failed to fetch token list \"${source.name}\": HTTP ${res.status}`,\n );\n }\n\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n let raw: unknown;\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/plain\")\n ) {\n raw = await res.json();\n } else {\n // Try parsing as JSON regardless\n const text = await res.text();\n raw = JSON.parse(text);\n }\n\n // Uniswap Token List format: { tokens: [...] } or plain array\n let tokens: TokenListEntry[];\n\n if (Array.isArray(raw)) {\n tokens = raw as TokenListEntry[];\n } else if (raw && typeof raw === \"object\") {\n const list = raw as TokenList;\n tokens = list.tokens ?? [];\n } else {\n tokens = [];\n }\n\n // Apply chain filter if configured\n if (source.chainFilter && source.chainFilter.length > 0) {\n tokens = tokens.filter((t) => source.chainFilter!.includes(t.chainId));\n }\n\n // Tag with source name\n return tokens.map((t) => ({ ...t, source: source.name }));\n } finally {\n clearTimeout(timeout);\n }\n }\n\n /**\n * Deduplicate tokens by (chainId, address).\n * Source priority controls which record wins for colliding tokens.\n */\n private deduplicate(tokens: TokenListEntry[]): TokenListEntry[] {\n const seen = new Map<string, TokenListEntry>();\n const priority =\n this.config.sourcePriority ?? this.config.sources.map((s) => s.name);\n\n for (const token of tokens) {\n const key = `${token.chainId}:${token.address.toLowerCase()}`;\n const existing = seen.get(key);\n\n if (!existing) {\n seen.set(key, token);\n continue;\n }\n\n // Existing has higher priority → keep it\n const existingIdx = priority.indexOf(existing.source ?? \"\");\n const currentIdx = priority.indexOf(token.source ?? \"\");\n\n if (currentIdx >= 0 && (existingIdx < 0 || currentIdx < existingIdx)) {\n // Current token has higher priority → replace\n seen.set(key, token);\n }\n // Otherwise keep existing\n }\n\n return Array.from(seen.values());\n }\n\n private async loadFromCache(): Promise<CachedData | null> {\n try {\n return await this.storage.get<CachedData>(this.config.cacheKey!);\n } catch {\n return null;\n }\n }\n\n private async saveToCache(tokens: TokenListEntry[]): Promise<void> {\n try {\n await this.storage.set<CachedData>(this.config.cacheKey!, {\n timestamp: Date.now(),\n tokens,\n });\n } catch {\n // Cache write failure is non-fatal\n }\n }\n\n private isCacheExpired(timestamp: number): boolean {\n return Date.now() - timestamp > (this.config.cacheTtl ?? DEFAULT_CACHE_TTL);\n }\n\n private updateSourceStatuses(state: \"loading\" | \"loaded\" | \"error\"): void {\n for (const [name, status] of this.sourceStatus) {\n status.state = state;\n status.tokenCount = this.tokens.filter((t) => t.source === name).length;\n status.lastUpdated = Date.now();\n }\n }\n}\n","/**\n * Chainlink price feed decimals for ETH/USD and similar pairs.\n * Feeds return the price as an integer scaled by 10^8 (e.g., 30000000000 = 3000.00 USD).\n *\n * Precision limit: uint256 answer is converted via Number() for the return type.\n * Number.MAX_SAFE_INTEGER (2^53) / 10^8 ≈ 90,039,254 — well above realistic crypto prices.\n * If prices ever exceed ~$90M per unit, this will need a BigInt-based decimal division.\n */\nconst CHAINLINK_DECIMALS = 8;\n\nimport { CHAINS } from \"./chain-registry\";\n\nfunction caip2ToChainId(caip2: string): number {\n return parseInt(caip2.split(\":\")[1] ?? \"0\", 10);\n}\n\n/**\n * Get the USD price of a native token (e.g. ETH, MATIC) by chain ID.\n *\n * This function was missing from the source but exists in the dist build.\n * It was added to the Ladle Vite bridge to unblock storybook-based testing.\n *\n * @param chain - EIP-155 chain ID (e.g. \"eip155:1\")\n * @param rpcUrl - Optional RPC URL for on-chain price lookup\n * @returns USD price as a number, or null if unavailable\n */\nexport async function getNativeTokenPriceUsd(\n chain: string,\n _rpcUrl?: string,\n): Promise<number | null> {\n const chainId = caip2ToChainId(chain);\n const info = CHAINS[chainId];\n const feedAddress = info?.chainlinkEthUsdFeed;\n if (!feedAddress || !_rpcUrl) return null;\n\n // Use Chainlink price feed ABI to get latest price\n const abi = [\n {\n inputs: [],\n name: \"latestRoundData\",\n outputs: [\n { name: \"roundId\", type: \"uint80\" },\n { name: \"answer\", type: \"int256\" },\n { name: \"startedAt\", type: \"uint256\" },\n { name: \"updatedAt\", type: \"uint256\" },\n { name: \"answeredInRound\", type: \"uint80\" },\n ],\n stateMutability: \"view\",\n type: \"function\",\n },\n ];\n\n try {\n const response = await fetch(_rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"eth_call\",\n params: [\n {\n to: feedAddress,\n data: \"0xfeaf968c\", // latestRoundData function selector\n },\n \"latest\",\n ],\n }),\n signal: AbortSignal.timeout(5_000),\n });\n\n if (!response.ok) return null;\n\n const json = await response.json();\n if (json.error) return null;\n\n // Parse the result: the price comes back as a 256-bit value\n // (typically with 8 decimals for Chainlink ETH/USD price feeds)\n const result = json.result;\n if (!result) return null;\n\n // Decode the hex result — answer is the 2nd 32-byte word\n const hex = result.startsWith(\"0x\") ? result.slice(2) : result;\n const answer = BigInt(\"0x\" + hex.slice(64, 128));\n\n // Chainlink feeds use 8 decimals for price\n // Number() is safe here: MAX_SAFE_INTEGER / 10^8 ≈ 90M, well above realistic prices\n return Number(answer) / 10 ** CHAINLINK_DECIMALS;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["exports","add","fromBig","split","U32_MASK64","_32n","le","lst","len","Ah","Al","i","h","l","toBig","shrSH","_l","s","shrSL","rotrSH","rotrSL","rotrBH","rotrBL","rotr32H","_h","rotr32L","rotlSH","rotlSL","rotlBH","rotlBL","Bh","Bl","add3L","Cl","add3H","low","Ch","add4L","Dl","add4H","Dh","add5L","El","add5H","Eh","u64","nc","exports","exports","isBytes","anumber","abytes","ahash","aexists","aoutput","u8","u32","clean","createView","rotr","rotl","byteSwap","byteSwap32","bytesToHex","hexToBytes","asyncLoop","utf8ToBytes","bytesToUtf8","toBytes","kdfInputToBytes","concatBytes","checkOpts","createHasher","createOptHasher","createXOFer","randomBytes","crypto_1","a","b","lengths","h","instance","checkFinished","out","min","arr","arrays","i","word","shift","u","hasHexBuiltin","hexes","_","bytes","hex","asciis","asciiToBase16","ch","hl","al","array","ai","hi","n1","n2","char","nextTick","iters","tick","cb","ts","diff","str","data","sum","res","pad","defaults","opts","Hash","hashCons","hashC","msg","tmp","bytesLength","exports","keccakP","_u64_ts_1","utils_ts_1","_0n","_1n","_2n","_7n","_256n","_0x71n","SHA3_PI","SHA3_ROTL","_SHA3_IOTA","round","R","x","y","t","j","IOTAS","SHA3_IOTA_H","SHA3_IOTA_L","rotlH","h","l","s","rotlL","rounds","B","idx1","idx0","B0","B1","Th","Tl","curH","curL","shift","PI","Keccak","_Keccak","blockLen","suffix","outputLen","enableXOF","data","state","len","pos","take","i","out","bufferOut","bytes","to","gen","genShake","opts","fromBig","le","U32_MASK64","_32n","split","lst","len","Ah","Al","i","h","l","rotlSH","rotlSL","rotlBH","rotlBL","init_u64","__esmMin","s","nc","crypto","init_cryptoNode","__esmMin","utils_exports","__export","Hash","abytes","aexists","ahash","anumber","aoutput","asyncLoop","byteSwap","byteSwap32","byteSwapIfBE","bytesToHex","bytesToUtf8","checkOpts","clean","concatBytes","createHasher","createOptHasher","createView","createXOFer","hexToBytes","isBytes","isLE","kdfInputToBytes","nextTick","randomBytes","rotl","rotr","swap32IfBE","swap8IfBE","toBytes","u32","u8","utf8ToBytes","wrapConstructor","wrapConstructorWithOpts","wrapXOFConstructorWithOpts","a","b","lengths","h","instance","checkFinished","out","min","arr","arrays","i","word","shift","bytes","hasHexBuiltin","hex","hexes","asciiToBase16","ch","asciis","hl","al","array","ai","hi","n1","n2","char","iters","tick","cb","ts","diff","str","data","sum","res","pad","defaults","opts","hashCons","hashC","msg","tmp","bytesLength","crypto","init_utils","__esmMin","init_cryptoNode","u","_","sha3_exports","__export","Keccak","keccakP","keccak_224","keccak_256","keccak_384","keccak_512","sha3_224","sha3_256","sha3_384","sha3_512","shake128","shake256","s","rounds","B","round","x","idx1","idx0","B0","B1","Th","rotlH","Tl","rotlL","y","curH","curL","t","shift","SHA3_ROTL","PI","SHA3_PI","SHA3_IOTA_H","SHA3_IOTA_L","clean","_0n","_1n","_2n","_7n","_256n","_0x71n","_SHA3_IOTA","IOTAS","gen","genShake","init_sha3","__esmMin","init_u64","init_utils","R","j","split","h","l","rotlBH","rotlSH","rotlBL","rotlSL","_Keccak","Hash","blockLen","suffix","outputLen","enableXOF","anumber","u32","swap32IfBE","data","aexists","toBytes","abytes","state","len","pos","take","i","out","bufferOut","bytes","aoutput","to","createHasher","createXOFer","opts","isERC20TokenError","e","ERC20TokenError","ERC20_TOKEN_ERROR_MESSAGES","init_errors","__esmMin","code","message","cause","units_exports","__export","formatUnits","parseUnits","amount","decimals","ERC20TokenError","str","dotIndex","integerPart","fractionalPart","combined","negative","padded","dotPos","init_units","__esmMin","init_errors","index_exports","__export","AA_ERROR_MESSAGES","AA_SUPPORTED_CHAINS","ARBITRUM_TOKENS","AUTO_RECONNECT_TIMEOUT_MS","AccountAbstractionError","AutoReconnectManager","AxelarProvider","BASE_TOKENS","BlowfishProvider","CHAINS","CONNECTOR_ERROR_MESSAGES","ChainAbstractionError","ConnectorManager","DEFAULT_BUILTIN_TOKENS","DEFAULT_CALL_GAS_LIMIT","DEFAULT_ENTRY_POINT","DEFAULT_EVM_CHAIN","DEFAULT_NONCE_LENGTH","DEFAULT_PRE_VERIFICATION_GAS","DEFAULT_RPC_URLS","DEFAULT_SESSION_KEY_CONFIG","DEFAULT_SOLANA_CLUSTER","DEFAULT_SOURCES","DEFAULT_VERIFICATION_GAS_LIMIT","DEFAULT_XRPL_NETWORK","EIP155_ARBITRUM","EIP155_ARBITRUM_GOERLI","EIP155_BASE","EIP155_GOERLI","EIP155_MAINNET","EIP155_MUMBAI","EIP155_OPTIMISM","EIP155_OPTIMISM_GOERLI","EIP155_POLYGON","EIP155_SEPOLIA","ENSProvider","ENTRY_POINT_V0_6","ENTRY_POINT_V0_7","ERC20TokenError","ERC20TokenHelper","ERC20_FUNCTION_SIGNATURES","ERC20_MIN_ABI","ETHEREUM_MAINNET_TOKENS","EthCallProvider","FEE_ERROR_MESSAGES","FeeEstimationError","InAppChannel","LiFiProvider","LocalStorageAdapter","LocalStorageSessionStorage","MemoryStorageAdapter","NAMESPACE_EIP155","NAMESPACE_SOLANA","NAMESPACE_XRPL","NameResolver","NoopChannel","NoopStorageAdapter","Notifier","OPTIMISM_TOKENS","POLYGON_TOKENS","PaymasterService","ResolutionError","ResolverCache","RouteEngine","SESSION_ERROR_MESSAGES","SESSION_KEY_ERROR_MESSAGES","SESSION_TIMEOUT_MS","SIMPLE_ACCOUNT_FACTORY","SNSProvider","SOLANA_DEVNET","SOLANA_MAINNET","SOLANA_TESTNET","STORAGE_KEYS","SUPPORTED_NAMESPACES","SessionEventEmitter","SessionKeyManager","SessionKeyStorage","SessionManager","SessionPersistence","SessionStorageAdapter","SimulationManager","SmartAccountManager","StorageError","TelegramChannel","TokenListManager","WC_DISCONNECT_SESSION_EXPIRED","WC_DISCONNECT_TIMEOUT","WC_DISCONNECT_USER","WalletError","XRPL_DEVNET","XRPL_MAINNET","XRPL_TESTNET","abiEncodeAddress","abiEncodeFunctionCall","abiEncodeUint256","abiFunctionSelector","buildCallData","buildUserOperation","clearAutoDetectCache","clearChainFeeEstimators","compareSimulationVsActual","createAutoReconnectManager","createConnectorManager","createEmptySession","createPaymasterService","createRouteEngine","createSessionError","createSessionKeyError","createSessionManager","createSessionPersistence","createStorageAdapter","decodeGasLimits","decryptPrivateKey","detectPlatform","detectTokenInfo","encodeGasLimits","encryptPrivateKey","estimateFees","estimateMaxPriorityFeePerGas","estimateUserOperationGas","extractAccounts","extractAccountsFromPermissions","formatUnits","getAllBuiltinTokens","getChainId","getChainsFromNamespaces","getEventsFromNamespaces","getFeeData","getGasPrice","getLatestBaseFee","getMethodsFromNamespaces","getNativeTokenPriceUsd","getPermissions","getRpcUrl","hasPermission","hashUserOperation","isAAError","isBurnAddress","isChainAbstractionError","isERC20TokenError","isFeeEstimationError","isMobileBrowser","isSessionExpired","isValidAddress","isWalletError","isZeroAddress","logger","parseBigInt","parseChainId","parseUnits","registerChainFeeEstimator","requestPermissions","sendUserOperation","setLogLevel","setLogSink","signUserOperation","toDecString","toHumanReadable","unregisterChainFeeEstimator","updateSession","validateChainId","__toCommonJS","AA_ERROR_MESSAGES","AccountAbstractionError","code","message","cause","isAAError","e","PaymasterService","config","userOp","AccountAbstractionError","data","serializedOp","headers","controller","timeoutId","response","json","result","error","extraParams","createPaymasterService","ENTRY_POINT_V0_6","ENTRY_POINT_V0_7","DEFAULT_ENTRY_POINT","SIMPLE_ACCOUNT_FACTORY","DEFAULT_CALL_GAS_LIMIT","DEFAULT_VERIFICATION_GAS_LIMIT","DEFAULT_PRE_VERIFICATION_GAS","AA_SUPPORTED_CHAINS","buildUserOperation","params","encodeGasLimits","DEFAULT_VERIFICATION_GAS_LIMIT","DEFAULT_CALL_GAS_LIMIT","DEFAULT_PRE_VERIFICATION_GAS","buildCallData","calls","AccountAbstractionError","encodeExecute","encodeExecuteBatch","to","value","data","selector","toArg","valueArg","rawData","dataLen","bytesOffset","dataLenHex","paddedLen","paddedData","n","nWord","toArray","c","valuesArray","datasEntries","datasArray","toLen","valuesLen","datasLen","headSize","toOffset","valuesOffset","datasOffset","computeDomainSeparator","entryPoint","chainId","concat","arrays","total","a","b","result","offset","arr","toBytes","hex","raw","bytes","i","stringToBytes","s","padded32","domainTypeHash","keccak256Sync","nameHash","versionHash","chainIdBytes","chainIdHex","chainIdArray","entryPointBytes","entryPointPadded","hashUserOperation","userOp","sender","nonce","initCode","callData","accountGasLimits","preVerificationGas","maxFeePerGas","maxPriorityFeePerGas","paymasterAndData","packed","packUserOp","userOpHash","domainSeparator","concatBytes","prefix","finalHash","bytesToHex","requireBytesToHex","encoder","bigintTo32Bytes","keccak_256","requireKeccak","_keccakFn","_bytesToHexFn","verificationGasLimit","callGasLimit","vglHex","cglHex","signUserOperation","signer","hash","messageHash","wrapEIP191","signature","error","rawMessage","prefixBytes","messageBytes","combined","sendUserOperation","bundlerUrl","serializedOp","controller","timeoutId","response","json","estimateUserOperationGas","getFactoryAddress","_chainId","_accountType","SIMPLE_ACCOUNT_FACTORY","getEntryPointForChain","chainId","info","AA_SUPPORTED_CHAINS","encodeCreateAccount","owner","salt","selector","ownerArg","saltArg","encodeExecute","to","value","data","toArg","valueArg","dataOffset","dataLen","offsetArg","lengthArg","dataRaw","encodeExecuteBatch","calls","numCalls","datasOffset","toPart","c","valuePart","dataLengths","dataBody","i","totalDataLength","dataPart","toArraySize","valuesArraySize","datasArraySize","toArrOffset","headSize","toArrOffset2","valuesArrOffset2","encodeExecuteBatchCalls","n","nWord","toArray","valuesArray","datDatas","rawData","datasArray","toArrayLen","valuesArrayLen","datasArrayLen","toOffset","valuesOffset","isContractDeployed","rpcUrl","address","rpcCall","method","params","controller","timeoutId","response","AccountAbstractionError","json","SmartAccountManager","config","chainId","AA_SUPPORTED_CHAINS","entryPoint","factory","callData","result","raw","isDeployed","options","initCode","deployData","nonce","gasEstimate","DEFAULT_CALL_GAS_LIMIT","DEFAULT_VERIFICATION_GAS_LIMIT","DEFAULT_PRE_VERIFICATION_GAS","callGasLimit","verificationGasLimit","preVerificationGas","maxFeePerGas","maxPriorityFeePerGas","baseFee","priorityFee","accountGasLimits","encodeGasLimits","userOp","buildUserOperation","paymasterConfig","paymasterData","PaymasterService","sender","key","senderArg","keyArg","keyArg32","partialUserOp","bundlerUrl","bigintToEvenHex","hex","serializedOp","userOpHash","maxRetries","intervalMs","resolve","block","ep","getEntryPointForChain","accountType","getFactoryAddress","vglHex","cglHex","decodeGasLimits","BURN_PREFIXES","ZERO_ADDR","EVM_ADDR_RE","isZeroAddress","address","isBurnAddress","clean","p","isValidAddress","chainNamespace","AutoReconnectManager","config","session","reconnectFn","error","delay","resolve","success","createAutoReconnectManager","LEVELS","currentLevel","currentSink","setLogLevel","level","setLogSink","sink","shouldLog","log","ns","args","prefix","createNamespace","logger","AXELAR_CHAIN_MAP","REVERSE_AXELAR_MAP","k","v","toAxelarChain","chainId","SUPPORTED_AXELAR_CHAINS","KNOWN_TOKENS","resolveTokenAddress","chain","token","chainTokens","AxelarProvider","config","fromChain","toChain","fromToken","toToken","amount","resolvedFromToken","resolvedToToken","routes","error","logger","response","_fromToken","_toToken","axelarFrom","axelarTo","gmpResponse","gmpData","baseFee","destGasFee","_route","_sender","_recipient","bridgeReference","data","axelarStatus","route","recipient","recipientPadded","LIFI_CHAIN_MAP","REVERSE_LIFI_MAP","k","v","toLiFiChainId","chainId","match","SUPPORTED_CHAINS","KNOWN_TOKENS","resolveTokenAddress","chain","token","chainTokens","LiFiProvider","config","fromChain","toChain","fromToken","toToken","amount","lifiFromChain","toLiFiChainId","lifiToChain","resolvedFromToken","resolvedToToken","routes","error","logger","response","headers","params","data","route","sender","recipient","txs","crossChainStep","s","approveStep","bridgeReference","lifiStatus","normalized","v","k","init_units","ChainAbstractionError","code","message","details","isChainAbstractionError","e","candidate","DEFAULT_QUOTE_CACHE_TTL","DEFAULT_STATUS_POLL_INTERVAL","DEFAULT_SLIPPAGE","NATIVE_TOKEN_SYMBOLS","NATIVE_TOKEN_DECIMALS","RouteEngine","config","provider","logger","providerId","fromChain","toChain","token","amount","options","ChainAbstractionError","cacheKey","cached","allRoutes","errors","activeProviders","results","err","result","e","route","quote","recipient","resolvedRecipient","txParams","approveTx","tx","error","operation","chains","comparisons","chain","i","b","bridgeReference","candidates","p","preferredSet","excludeSet","routes","fromDecimals","toDecimals","quotes","toAmount","toAmountMin","fromAmount","expiry","exchangeRate","scaled","whole","remainder","priceImpact","fromFormatted","formatUnits","toFormatted","toMinFormatted","s","sortBy","sorted","a","gasDiff","aNet","chainId","tokens","KNOWN_TOKEN_LIST","symbol","address","protocolFee","integrationFee","total","seconds","now","key","entry","chainName","nativeSymbol","gasUnits","gasCost","nativePriceUsd","gasCostUsd","fee","totalCost","_operation","blockTimes","blocksNeeded","blockTime","createRouteEngine","CHAINS","extractAccounts","namespaces","namespace","getChainsFromNamespaces","chains","chain","getMethodsFromNamespaces","methods","method","getEventsFromNamespaces","events","event","CONNECTOR_ERROR_MESSAGES","WalletError","code","message","details","isWalletError","e","candidate","detectPlatform","ua","isMobileBrowser","ConnectorManager","config","id","connector","priority","a","b","support","entry","input","session","connectorId","newSession","chainId","request","WalletError","calls","available","preferredId","isMobile","isMobileBrowser","createConnectorManager","NAMESPACE_EIP155","NAMESPACE_SOLANA","NAMESPACE_XRPL","SUPPORTED_NAMESPACES","EIP155_MAINNET","EIP155_GOERLI","EIP155_SEPOLIA","EIP155_POLYGON","EIP155_MUMBAI","EIP155_ARBITRUM","EIP155_ARBITRUM_GOERLI","EIP155_OPTIMISM","EIP155_OPTIMISM_GOERLI","EIP155_BASE","SOLANA_MAINNET","SOLANA_DEVNET","SOLANA_TESTNET","XRPL_MAINNET","XRPL_TESTNET","XRPL_DEVNET","DEFAULT_EVM_CHAIN","DEFAULT_SOLANA_CLUSTER","DEFAULT_XRPL_NETWORK","WC_DISCONNECT_USER","WC_DISCONNECT_TIMEOUT","WC_DISCONNECT_SESSION_EXPIRED","STORAGE_KEYS","DEFAULT_NONCE_LENGTH","SESSION_TIMEOUT_MS","AUTO_RECONNECT_TIMEOUT_MS","toDecString","value","parseBigInt","toHumanReadable","wei","decimals","unit","divisor","whole","remainder","trimmed","FeeEstimationError","code","message","details","isFeeEstimationError","e","candidate","FEE_ERROR_MESSAGES","chainEstimators","registerChainFeeEstimator","estimator","unregisterChainFeeEstimator","chainId","clearChainFeeEstimators","rpcCall","rpcUrl","method","params","controller","timeoutId","response","FeeEstimationError","json","estimateMaxPriorityFeePerGas","result","getLatestBaseFee","block","getGasPrice","getChainId","getFeeData","baseFee","recommendedPriorityFee","findRegisteredEstimator","resolveType","config","buildEIP1559Fees","priorityFee","multiplier","maxPriorityFeePerGas","estimateFees","error","logger","FEE_ERROR_MESSAGES","STORAGE_KEY_PREFIX","InAppChannel","options","payload","item","id","found","n","saved","TelegramChannel","config","formatted","hash","status","NoopChannel","_payload","_notifIdCounter","generateId","STORAGE_KEY_PREFS","STORAGE_KEY_WATCHES","STORAGE_KEY_MUTE_RULES","DEFAULT_PREFERENCES","Notifier","options","channel","channelId","c","hash","chainId","userId","prefs","watch","callback","status","receipt","userMuteRules","payload","callbacks","callbackPayload","cb","channels","fullPayload","targetChannels","current","rule","rules","ruleId","r","metadata","now","p","watches","w","muteRules","obj","frequency","confirmations","label","channelIds","results","result","getPermissions","provider","result","requestPermissions","extractAccountsFromPermissions","permissions","ethAccountsPerm","p","caveat","c","hasPermission","capability","DEFAULT_RPC_URLS","getRpcUrl","chainId","fallback","init_sha3","init_utils","ResolutionError","code","message","cause","ResolverCache","ttlMs","key","entry","value","now","textEncoder","stringToBytes","str","ENS_REGISTRY_ADDRESS","ENS_REGISTRY_ABI","RESOLVER_ABI","EMPTY_ADDR","namehash","name","node","labels","i","labelHash","keccak_256","stringToBytes","concatBytes","bytesToHex","encodeFunctionCall","abi","fnName","args","abiEntry","f","inputs","i","signature","selector","keccak_256","stringToBytes","encodedArgs","arg","hex","hexToBytes","bytes","offset","lengthBytes","paddedLen","padded","concatBytes","encoded","bytesToHex","decodeAddress","data","ResolutionError","addrBytes","decodeString","len","strBytes","ethCall","rpcUrl","params","response","json","ENSProvider","name","cleanName","node","namehash","resolverAddr","addrData","RESOLVER_ABI","result","address","cleanAddr","reverseNode","nameData","ENS_REGISTRY_ABI","ENS_REGISTRY_ADDRESS","init_utils","setBigUint64","view","byteOffset","value","isLE","_32n","_u32_max","wh","wl","h","Chi","a","b","c","Maj","HashMD","Hash","blockLen","outputLen","padOffset","createView","data","aexists","toBytes","abytes","buffer","len","pos","take","dataView","out","aoutput","clean","i","oview","outLen","state","res","to","length","finished","destroyed","SHA256_IV","init_utils","SHA256_K","SHA256_W","SHA256","HashMD","outputLen","SHA256_IV","A","B","C","D","E","F","G","H","view","offset","i","W15","W2","s0","rotr","s1","sigma1","T1","Chi","T2","Maj","clean","sha256","createHasher","SHA256","sha256","init_utils","textEncoder","stringToBytes","str","SNS_PROGRAM_ID","SOL_TLD_DOMAIN","NAME_RECORD_SEED","ALPHABET","BASE","base58Decode","input","num","char","idx","ALPHABET","BASE","hex","hexPadded","bytes","hexToBytes","leadingZeros","result","findProgramAddress","seeds","programId","bump","seedsBytes","concatBytes","hash","sha256","parseAccountInfo","rawData","bytes","base58Decode","header","bytesToHex","content","getAccountInfo","rpcUrl","pubkey","response","ResolutionError","json","deriveDomainKey","name","tldBytes","SOL_TLD_DOMAIN","nameBytes","stringToBytes","programBytes","SNS_PROGRAM_ID","NAME_RECORD_SEED","address","SNSProvider","cleanName","domainKey","accountInfo","ownerHex","err","hex","normalizedHex","hexToBytes","num","i","chars","remainder","BASE","ALPHABET","leadingOnes","b","defaultEnsRpc","DEFAULT_RPC_URLS","defaultSnsRpc","detectNameService","name","lower","isValidName","suffix","label","NameResolver","config","ResolverCache","ensRpcUrl","ENSProvider","snsRpcUrl","SNSProvider","provider","cleanName","ResolutionError","cacheKey","cached","result","address","chainId","cleanAddr","chainType","names","results","errors","err","ns","promise","_","reject","StorageError","message","code","cause","getGlobalStorage","key","candidate","isStorageAvailable","type","storage","testKey","resolveLocalStorage","LocalStorageAdapter","prefix","key","resolveLocalStorage","isStorageAvailable","store","item","e","StorageError","value","keys","k","SessionStorageAdapter","MemoryStorageAdapter","NoopStorageAdapter","_key","_value","createStorageAdapter","type","createEmptySession","input","now","updateSession","session","patch","isSessionExpired","LocalStorageSessionStorage","key","LocalStorageAdapter","error","logger","SESSION_KEY_ERROR_MESSAGES","createSessionKeyError","code","details","WalletError","init_utils","HMAC","Hash","hash","_key","ahash","key","toBytes","blockLen","pad","clean","buf","aexists","out","abytes","to","oHash","iHash","finished","destroyed","outputLen","hmac","message","init_utils","init_utils","_0n","_1n","_abool2","value","title","prefix","_abytes2","length","bytes","isBytes","len","needsLen","ofLen","got","numberToHexUnpadded","num","hex","hexToNumber","_0n","bytesToNumberBE","bytesToHex","bytesToNumberLE","abytes","numberToBytesBE","hexToBytes","numberToBytesLE","ensureBytes","title","hex","expectedLength","res","hexToBytes","e","isBytes","len","isPosBig","_0n","inRange","min","max","aInRange","title","n","bitLen","len","_1n","bitMask","_1n","createHmacDrbg","hashLen","qByteLen","hmacFn","u8n","len","u8of","byte","v","k","i","reset","h","b","reseed","seed","gen","out","sl","concatBytes","pred","res","_validateObject","object","fields","optFields","checkField","fieldName","expectedType","isOpt","val","current","k","v","memoized","fn","map","arg","args","val","computed","_0n","_1n","_2n","_3n","_4n","_5n","_7n","_8n","_9n","_16n","mod","a","b","result","pow2","x","power","modulo","res","_0n","invert","number","a","mod","b","y","_1n","u","v","q","r","m","n","assertIsSquare","Fp","root","sqrt3mod4","p1div4","_4n","sqrt5mod8","p5div8","_5n","_8n","n2","_2n","nv","sqrt9mod16","P","Fp_","Field","tn","tonelliShanks","c1","c2","c3","c4","_7n","_16n","tv1","tv2","tv3","tv4","e1","e2","e3","_3n","Q","S","Z","_Fp","FpLegendre","cc","Q1div2","M","c","t","R","i","t_tmp","exponent","FpSqrt","_9n","FIELD_FIELDS","validateField","field","initial","opts","map","val","_validateObject","FpPow","Fp","num","power","_0n","_1n","p","d","FpInvertBatch","nums","passZero","inverted","multipliedAcc","acc","i","invertedAcc","FpLegendre","Fp","n","p1mod2","_1n","_2n","powered","yes","zero","no","nLength","nBitLength","anumber","_nBitLength","nByteLength","Field","ORDER","bitLenOrOpts","isLE","opts","_0n","_nbitLength","_sqrt","modFromBytes","allowedLengths","_opts","BITS","BYTES","sqrtP","f","bitMask","_1n","num","mod","lhs","rhs","power","FpPow","invert","n","FpSqrt","numberToBytesLE","numberToBytesBE","bytes","skipValidation","padded","scalar","bytesToNumberLE","bytesToNumberBE","lst","FpInvertBatch","a","b","c","getFieldBytesLength","fieldOrder","bitLength","getMinHashLength","length","mapHashToField","key","isLE","len","fieldLen","minLen","num","bytesToNumberLE","bytesToNumberBE","reduced","mod","_1n","numberToBytesLE","numberToBytesBE","_0n","_1n","negateCt","condition","item","neg","normalizeZ","c","points","invertedZs","FpInvertBatch","p","i","validateW","W","bits","calcWOpts","scalarBits","windows","windowSize","maxNumber","mask","bitMask","shiftBy","calcOffsets","window","wOpts","wbits","nextN","offsetStart","offset","isZero","isNeg","isNegF","validateMSMPoints","validateMSMScalars","scalars","field","s","pointPrecomputes","pointWindowSizes","getW","P","assert0","wNAF","Point","elm","n","d","point","base","precomputes","f","wo","offsetF","acc","transform","comp","scalar","prev","mulEndoUnsafe","k1","k2","p1","p2","pippenger","fieldN","plength","slength","zero","bitLen","MASK","buckets","lastBits","sum","j","resI","sumI","createField","order","field","isLE","validateField","Field","_createCurveFields","type","CURVE","curveOpts","FpFnLE","p","val","_0n","Fp","Fn","params","divNearest","num","den","_2n","_splitEndoScalar","k","basis","n","a1","b1","a2","b2","c1","c2","k1","k2","k1neg","_0n","k2neg","MAX_NUM","bitMask","bitLen","_1n","validateSigFormat","format","validateSigOpts","opts","def","optsn","optName","_abool2","DERErr","m","DER","tag","data","E","dataLen","len","numberToHexUnpadded","lenLen","pos","first","isLong","length","lengthBytes","b","v","hex","bytesToNumberBE","int","tlv","ensureBytes","seqBytes","seqLeftBytes","rBytes","rLeftBytes","sBytes","sLeftBytes","sig","rs","ss","seq","_3n","_4n","_normFnElement","Fn","key","expected","bytes","weierstrassN","params","extraOpts","validated","_createCurveFields","Fp","CURVE","cofactor","CURVE_ORDER","_validateObject","endo","lengths","getWLengths","assertCompressionIsSupported","pointToBytes","_c","point","isCompressed","x","y","bx","hasEvenY","concatBytes","pprefix","pointFromBytes","_abytes2","comp","uncomp","head","tail","y2","weierstrassEquation","sqrtError","err","isYOdd","L","isValidXY","encodePoint","decodePoint","x2","x3","left","right","_4a3","_27b2","acoord","title","banZero","aprjpoint","other","Point","splitEndoScalarN","toAffineMemo","memoized","p","iz","X","Y","Z","is0","zz","assertValidMemo","finishEndo","endoBeta","k1p","k2p","negateCt","P","windowSize","isLazy","wnaf","X1","Y1","Z1","X2","Y2","Z2","U1","U2","a","b3","X3","Y3","Z3","t0","t1","t2","t3","t4","t5","scalar","fake","mul","normalizeZ","k1f","k2f","f","sc","p1","p2","mulEndoUnsafe","Q","sum","invertedZ","isTorsionFree","clearCofactor","bytesToHex","points","scalars","pippenger","privateKey","bits","wNAF","getWLengths","Fp","Fn","ecdh","Point","ecdhOpts","randomBytes_","randomBytes","lengths","getMinHashLength","isValidSecretKey","secretKey","_normFnElement","isValidPublicKey","publicKey","isCompressed","comp","publicKeyUncompressed","l","randomSecretKey","seed","mapHashToField","_abytes2","getPublicKey","keygen","isProbPub","item","ensureBytes","getSharedSecret","secretKeyA","publicKeyB","s","key","windowSize","point","ecdsa","hash","ecdsaOpts","ahash","_validateObject","hmac","msgs","concatBytes","CURVE_ORDER","fnBits","utils","defaultSigOpts","defaultSigOpts_format","isBiggerThanHalfOrder","number","HALF","_1n","validateRS","title","num","validateSigLength","bytes","format","validateSigFormat","size","sizer","Signature","r","recovery","recid","DER","L","hex","hexToBytes","messageHash","FIELD_ORDER","rec","_2n","radj","x","R","pprefix","ir","h","bits2int_modN","u1","u2","Q","bytesToHex","bits2int","bytesToNumberBE","delta","ORDER_MASK","bitMask","int2octets","aInRange","_0n","validateMsgAndHash","message","prehash","prepSig","privateKey","opts","k","lowS","extraEntropy","validateSigOpts","h1int","d","seedArgs","e","m","k2sig","kBytes","ik","q","normS","sign","createHmacDrbg","tryParsingSig","sg","sig","isHex","isBytes","isObj","derError","verify","signature","P","is","recoverPublicKey","_weierstrass_legacy_opts_to_new","c","CURVE","Fp","allowedLengths","l","Fn","Field","curveOpts","_ecdsa_legacy_opts_to_new","ecdsaOpts","_ecdsa_new_output_to_legacy","c","_ecdsa","Point","nLength","weierstrass","CURVE","curveOpts","hash","ecdsaOpts","_ecdsa_legacy_opts_to_new","weierstrassN","signs","ecdsa","createCurve","curveDef","defHash","create","hash","weierstrass","secp256k1_CURVE","secp256k1_ENDO","_2n","sqrtMod","y","P","secp256k1_CURVE","_3n","_6n","_11n","_22n","_23n","_44n","_88n","b2","b3","b6","pow2","b9","b11","b22","b44","b88","b176","b220","b223","t1","t2","root","Fpk1","Field","secp256k1","createCurve","secp256k1_ENDO","sha256","init_utils","init_utils","pbkdf2Init","hash","_password","_salt","_opts","ahash","opts","checkOpts","c","dkLen","asyncTick","anumber","password","kdfInputToBytes","salt","DK","PRF","hmac","PRFSalt","pbkdf2Output","prfW","u","clean","pbkdf2","arr","view","createView","ti","pos","Ti","ui","i","init_utils","KEY_LENGTH","IV_LENGTH","SALT_LENGTH","DEFAULT_PBKDF2_ITERATIONS","STORAGE_KEY","deriveEncryptionKey","password","salt","iterations","pbkdf2","sha256","DEFAULT_PBKDF2_ITERATIONS","KEY_LENGTH","aes256ctrEncrypt","plaintext","key","iv","numBlocks","keystream","counter","ctrValue","i","b","counterBytes","blockCtr","input","blockKey","hmac","ciphertext","authData","tag","aes256ctrDecrypt","expectedTag","tagValid","createSessionKeyError","encryptPrivateKey","privateKeyHex","publicKeyHex","pkBytes","hexToBytes","actualSalt","randomBytes","SALT_LENGTH","IV_LENGTH","combined","bytesToHex","decryptPrivateKey","encrypted","bigintReplacer","_key","value","bigintReviver","SessionKeyStorage","adapter","MemoryStorageAdapter","raw","STORAGE_KEY","keys","serialized","index","k","id","filtered","status","DEFAULT_SESSION_KEY_CONFIG","uuidv4","bytes","randomBytes","hex","bytesToHex","deriveEncryptionPassword","config","base","DEFAULT_SESSION_KEY_CONFIG","sha256","s","b","SessionKeyManager","storageAdapter","SessionKeyStorage","scope","signerAddress","fullScope","createSessionKeyError","privateKeyBytes","secp256k1","publicKeyBytes","publicKeyHex","privateKeyHex","encrypted","encryptPrivateKey","now","stored","k","sessionId","privateKey","decryptPrivateKey","bundle","messageHash","hashBytes","hexToBytes","sig","signature","v","r","vHex","tx","e","authorization","defaultExpiry","nowSec","currentUseCount","result","txValue","txGas","txToLower","c","methodId","keys","changed","key","SESSION_ERROR_MESSAGES","createSessionError","code","details","WalletError","SessionEventEmitter","event","handler","handlers","payload","error","DEFAULT_KEY","SessionPersistence","key","adapter","LocalStorageAdapter","error","logger","data","bundle","chainSessions","session","chainId","isSessionExpired","createSessionPersistence","MemoryStorageAdapter","parseChainId","chainId","parts","validateChainId","namespace","reference","supported","DEFAULT_CHAIN_METADATA","DEFAULT_EXPLORERS","SessionManager","SessionEventEmitter","connectorManager","config","createSessionPersistence","walletType","chainId","input","validateChainId","oldest","a","b","session","bundle","bundleId","createSessionError","previousChainId","connector","error","chainSession","logger","connectorId","topic","remaining","sessions","options","targetChainId","feeConfig","overrides","fees","estimateFees","existing","data","event","handler","activeChainId","chainSessions","namespace","ns","chain","parseChainId","nativeCurrency","rpcUrl","DEFAULT_RPC_URLS","blockExplorer","reference","createSessionManager","SUPPORTED_CHAINS","CHAIN_NAMES","BLOWFISH_API_BASE","getChainName","chainId","mapSuggestedAction","action","buildWarnings","scanResults","warnings","scan","parseBalanceChanges","changes","results","change","match","direction","humanReadable","rawAmount","tokenSymbol","tokenAddress","tokenDecimals","parseApprovalChanges","isUnlimited","parseGasInfo","gasInfo","buildSummary","simulationResult","balanceChanges","c","BlowfishProvider","apiKey","tx","from","options","chainName","response","json","simResult","approvalChanges","suggestedAction","riskLevel","score","w","err","_origin","ETH_NATIVE_CHAINS","MATIC_NATIVE_CHAINS","BNB_NATIVE_CHAINS","parseRevertReason","errorData","clean","dataHex","lengthHex","length","msgHex","bytes","i","codeHex","code","getNativeSymbol","chainId","buildSuccessResult","providerName","from","nativeSymbol","buildRevertedResult","revertReason","EthCallProvider","defaultRpcUrl","tx","options","rpcUrl","callParams","json","err","_chainId","abortableFetch","url","options","timeoutMs","controller","timeoutId","rpcCall","rpcUrl","method","params","response","json","ERC20_MIN_ABI","ERC20_FUNCTION_SIGNATURES","init_errors","init_units","strip0x","hex","padLeftTo32Bytes","keccak256Hex","data","keccak_256","bytesToHex","abiEncodeAddress","addr","ERC20TokenError","abiEncodeUint256","value","paddedHex","abiFunctionSelector","signature","abiEncodeFunctionCall","encodedArgs","selector","a","encodeTransfer","to","rawAmount","ERC20_FUNCTION_SIGNATURES","encodeApprove","spender","encodeTransferFrom","from","getRpcUrl","chainId","options","url","DEFAULT_RPC_URLS","ethCall","rpcUrl","rpcCall","err","decodeUint256","clean","decodeString","lengthHex","length","dataHex","bytes","decodeUint8","selectorCache","getSelector","cached","ERC20TokenHelper","_ERC20TokenHelper","params","decimals","parseUnits","token","owner","result","nameSelector","symbolSelector","decimalsSelector","totalSupplySelector","call","nameRaw","symbolRaw","decimalsRaw","totalSupplyRaw","name","symbol","totalSupply","code","amount","formatUnits","DEFAULT_UNAVAILABLE_RISK","SimulationManager","config","EthCallProvider","BlowfishProvider","tx","from","options","chainId","provider","rpcUrl","result","fallback","fallbackResult","token","to","amount","decimals","ERC20TokenHelper","err","enabled","name","apiKey","blowfish","_from","DEFAULT_RPC_URLS","compareSimulationVsActual","simulation","actualStatus","discrepancies","init_errors","init_units","CACHE_KEY","DEFAULT_CACHE_TTL","detectTokenInfo","address","chainId","rpcUrl","options","cached","getFromCache","addr","nameData","symbolData","decimalsData","nameRaw","symbolRaw","decimalsRaw","ethCall","token","decodeString","decodeUint8","saveToCache","clearAutoDetectCache","createStorageAdapter","storage","data","key","entry","to","res","json","hex","clean","bytes","lengthHex","length","dataHex","ETHEREUM_MAINNET_TOKENS","POLYGON_TOKENS","OPTIMISM_TOKENS","ARBITRUM_TOKENS","BASE_TOKENS","DEFAULT_BUILTIN_TOKENS","getAllBuiltinTokens","DEFAULT_SOURCES","DEFAULT_CACHE_KEY","DEFAULT_CACHE_TTL","DEFAULT_FETCH_TIMEOUT","TokenListManager","config","DEFAULT_SOURCES","createStorageAdapter","source","cached","enabledSources","s","results","allTokens","i","result","stale","staleTokens","t","options","query","limit","q","exact","fuzzy","candidates","isAddress","token","sym","name","a","b","hasMore","exactSlice","remaining","fuzzySlice","address","chainId","controller","timeout","res","contentType","raw","text","tokens","seen","priority","key","existing","existingIdx","currentIdx","timestamp","state","status","CHAINLINK_DECIMALS","caip2ToChainId","caip2","getNativeTokenPriceUsd","chain","_rpcUrl","chainId","feedAddress","CHAINS","abi","response","json","result","hex","answer"]}