@anywalletkit/extension-kit 0.3.6 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/vault.ts","../src/codec.ts","../src/session.ts","../src/relay.ts","../src/chrome.ts","../src/keyring.ts","../src/networks.ts","../src/storage.ts","../src/permissions.ts","../src/approvals.ts","../src/router.ts","../src/siwe.ts","../src/signing.ts","../src/gate.ts","../src/swap.ts","../src/swaps.ts","../src/earn.ts","../src/tonconnect.ts","../src/phishing.ts","../src/webauthn.ts","../src/poison.ts"],"sourcesContent":["export * from './errors.js'\nexport * from './vault.js'\nexport * from './session.js'\nexport * from './relay.js'\nexport * from './chrome.js'\nexport * from './keyring.js'\nexport * from './networks.js'\nexport * from './storage.js'\nexport * from './permissions.js'\nexport * from './approvals.js'\nexport * from './router.js'\nexport * from './signing.js'\nexport * from './gate.js'\nexport * from './swap.js'\nexport * from './swaps.js'\nexport * from './earn.js'\nexport * from './tonconnect.js'\nexport * from './phishing.js'\nexport * from './webauthn.js'\nexport * from './siwe.js'\nexport * from './poison.js'\n","/** A vault or session rule was broken. Messages are safe to show the user and never contain secrets. */\nexport class VaultError extends Error {\n readonly code: VaultErrorCode\n constructor(message: string, code: VaultErrorCode) {\n super(message)\n this.name = 'VaultError'\n this.code = code\n }\n}\n\nexport type VaultErrorCode =\n /** The password did not open the vault (or the envelope was tampered with — AES-GCM cannot tell the two apart). */\n | 'wrong-password'\n /** `create` was called while a vault already exists — an existing wallet is never overwritten. */\n | 'exists'\n /** `unlock` / `getSecret` on a storage area that holds no vault. */\n | 'missing'\n /** The stored envelope has a version or shape this build does not read. */\n | 'unsupported-envelope'\n /** The session is locked: the unlocked key is gone (auto-lock, browser exit, explicit lock). */\n | 'locked'\n /** Bad input (empty or too-short password, bad key length, bad id). */\n | 'invalid-input'\n /** The stored envelope's KDF parameters are below the floor this build accepts (edited on disk). */\n | 'weak-kdf'\n","/**\n * The vault: every secret (seed phrase, imported private key, TON words) at rest\n * in `chrome.storage.local`, encrypted with WebCrypto plus one audited pure-JS\n * primitive (`@noble/hashes` scrypt) — no WASM, no third-party crypto in the\n * key path beyond that.\n *\n * Two layers of keys, so that unlocking does not keep the password around and\n * other unlock paths (passkeys) do not re-encrypt the secrets:\n *\n * ```text\n * password ──scrypt (N=2^17, r=8, p=1)──▶ KEK ──AES-256-GCM──▶ wraps the DEK (envelope v2)\n * passkey PRF ──HKDF-SHA256 (salt = credential id)──▶ KEK ──AES-256-GCM──▶ wraps the DEK, one box per passkey\n * DEK (32 random bytes) ──AES-256-GCM, AAD = secret id──▶ each secret\n * ```\n *\n * What the session holds while unlocked is the DEK (see {@link Session}); the\n * password and the PRF output never leave {@link Vault.create} / {@link Vault.unlock} /\n * {@link Vault.unlockWithPasskey}. Every ciphertext carries its own 96-bit IV; the\n * AAD binds a secret to its id (so two entries cannot be swapped inside the\n * envelope) and binds the DEK box to the exact KDF parameters (so an envelope whose\n * salt or cost was edited on disk fails to open instead of deriving a weaker key).\n * Wrong password and tampering are indistinguishable (GCM tag failure) and both\n * surface as `wrong-password`.\n *\n * Envelope versions: v1 = PBKDF2-SHA256 (≥ 600 000 iterations), still opened and\n * re-sealed as v2 on the next successful unlock (MetaMask's `updateVault` pattern);\n * v2 = scrypt (OWASP parameters, memory-hard: an attacker who copied the Chrome\n * profile cannot run the search on GPUs the way PBKDF2 allows) + optional passkey\n * boxes. Anything else is refused (`unsupported-envelope`) instead of guessed.\n * Passwords: at least {@link VAULT_MIN_PASSWORD_LENGTH} characters, enforced here\n * and not only in a UI.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport { scryptAsync } from '@noble/hashes/scrypt.js'\nimport { fromBase64, toArrayBuffer, toBase64, withSecretBuffer } from './codec.js'\nimport { VaultError } from './errors.js'\n\n/** PBKDF2-SHA256 iterations (v1 envelopes): OWASP 2023 floor for SHA-256; anything lower is refused. */\nexport const VAULT_MIN_ITERATIONS = 600_000\nexport const VAULT_DEFAULT_ITERATIONS = 600_000\n/** scrypt for v2 envelopes: OWASP's recommended cost (128 MiB, ~1 s in a service worker). */\nexport const VAULT_SCRYPT = { N: 1 << 17, r: 8, p: 1 } as const\n/** The weakest scrypt an envelope may carry and still open (16 MiB). Tests use this; `create` uses {@link VAULT_SCRYPT}. */\nexport const VAULT_MIN_SCRYPT = { N: 1 << 14, r: 8, p: 1 } as const\n/** Shortest password `create` / `changePassword` accept. `unlock` takes whatever opens the vault. */\nexport const VAULT_MIN_PASSWORD_LENGTH = 8\n/**\n * Upper bounds on what an envelope (and the options) may carry, checked before any KDF runs: an\n * envelope edited on disk must not make unlock hang (PBKDF2 iterations) or exhaust the worker's\n * memory (scrypt N × r), and its size stays within what `chrome.storage.local` holds.\n */\nexport const VAULT_LIMITS = Object.freeze({\n /** scrypt cost: 2^20 × 16 = 2 GiB is the most any envelope may ask for. */\n scrypt: Object.freeze({ N: 1 << 20, r: 16, p: 4 }),\n /** PBKDF2-SHA256 iterations (v1 envelopes). */\n iterations: 5_000_000,\n /** Sealed secrets in one vault. */\n secrets: 1_000,\n /** Registered passkeys. */\n passkeys: 32,\n /** Plaintext bytes of one secret (`setSecret`). */\n secretBytes: 16 * 1024,\n /** base64 characters of one sealed box (iv or data). */\n boxChars: 32 * 1024,\n /** JSON characters of the whole envelope. */\n envelopeChars: 4 * 1024 * 1024,\n})\nconst SALT_BYTES = 32\nconst IV_BYTES = 12\nconst DEK_BYTES = 32\n/** PRF outputs are 32 bytes (WebAuthn `prf` extension, `first`). */\nconst PRF_BYTES = 32\n\nexport interface SealedBox {\n /** 96-bit AES-GCM nonce, base64. */\n iv: string\n /** ciphertext ‖ 128-bit tag, base64. */\n data: string\n}\n\nexport interface VaultEnvelopeV1 {\n v: 1\n kdf: { name: 'PBKDF2-SHA256'; iterations: number; salt: string }\n /** The DEK, sealed under the password-derived key. AAD = version + kdf. */\n dek: SealedBox\n /** One box per key source (keyring source id), sealed under the DEK. AAD `forgewallet-vault/secret/<id>`. */\n secrets: Record<string, SealedBox>\n /** A fixed value sealed under the DEK (AAD `forgewallet-vault/dek-check`): proves a key is this vault's while it holds no secret. Absent in envelopes written before it existed. */\n dekCheck?: SealedBox\n createdAt: number\n}\n\nexport interface VaultPasskey {\n /** WebAuthn credential id, base64url. */\n id: string\n label: string\n createdAt: number\n /** The DEK sealed under HKDF(PRF output, salt = credential id). AAD = `forgewallet-vault/2/passkey/<id>`. */\n dek: SealedBox\n /** The credential's public key (SPKI, base64) when the authenticator gave one — lets the worker verify assertions (passkey-per-signature). */\n publicKey?: string\n /** COSE algorithm of `publicKey` (-7 = ES256). */\n alg?: number\n}\n\nexport interface VaultEnvelopeV2 {\n v: 2\n kdf: { name: 'scrypt'; N: number; r: number; p: number; salt: string }\n dek: SealedBox\n secrets: Record<string, SealedBox>\n /** See {@link VaultEnvelopeV1.dekCheck}. */\n dekCheck?: SealedBox\n passkeys: VaultPasskey[]\n createdAt: number\n /** When a v1 envelope was re-sealed as v2. */\n upgradedAt?: number\n /** When {@link Vault.rotateVaultKey} last replaced the DEK. */\n rotatedAt?: number\n}\n\nexport type VaultEnvelope = VaultEnvelopeV1 | VaultEnvelopeV2\n\n/** Where the envelope lives. `chromeLocalVaultStorage()` for the extension, `memoryVaultStorage()` for tests. */\nexport interface VaultStorage {\n get(): Promise<VaultEnvelope | null>\n set(envelope: VaultEnvelope): Promise<void>\n clear(): Promise<void>\n}\n\nexport interface VaultOptions {\n storage: VaultStorage\n /** KDF for NEW envelopes and re-seals. Default scrypt (v2); `'pbkdf2'` writes v1 (tests, or a build that must stay FIPS-only). */\n kdf?: 'scrypt' | 'pbkdf2'\n /** PBKDF2 iterations for v1 envelopes (default and minimum {@link VAULT_DEFAULT_ITERATIONS}). */\n iterations?: number\n /** scrypt cost for v2 envelopes (default {@link VAULT_SCRYPT}; not below {@link VAULT_MIN_SCRYPT}). */\n scrypt?: { N: number; r: number; p: number }\n /** Progress of the scrypt derivation, 0..1 — the unlock screen's bar. */\n onProgress?: (fraction: number) => void\n /** Defaults to `globalThis.crypto`; injectable for tests. */\n crypto?: Crypto\n}\n\nexport interface VaultKdfInfo {\n version: 1 | 2\n name: 'PBKDF2-SHA256' | 'scrypt'\n /** Human line for the UI, e.g. \"scrypt N=2^17 r=8 p=1\". */\n summary: string\n}\n\n// AAD / HKDF labels are part of the sealed format: existing vaults open only with these exact strings.\nconst aadDekV1 = (kdf: VaultEnvelopeV1['kdf']) => `forgewallet-vault/1/dek/${kdf.name}/${kdf.iterations}/${kdf.salt}`\nconst aadDekV2 = (kdf: VaultEnvelopeV2['kdf']) => `forgewallet-vault/2/dek/scrypt/${kdf.N}/${kdf.r}/${kdf.p}/${kdf.salt}`\nconst aadPasskey = (id: string) => `forgewallet-vault/2/passkey/${id}`\nconst aadSecret = (id: string) => `forgewallet-vault/secret/${id}`\nconst AAD_DEK_CHECK = 'forgewallet-vault/dek-check'\n/** What the DEK check box holds: a fixed value, so opening it proves the key and nothing else. */\nconst DEK_CHECK = 'forgewallet-vault/dek-check/1'\nconst HKDF_INFO = 'forgewallet-vault/2/passkey'\n\n/**\n * One `Vault` per storage area: writes to the envelope are serialized inside the instance, so two\n * instances over the same area could still overwrite each other.\n */\nexport class Vault {\n private readonly _storage: VaultStorage\n /** Every read-modify-write of the envelope runs here, one after another (a parallel write would drop the other's change). */\n private _queue: Promise<unknown> = Promise.resolve()\n private readonly _kdf: 'scrypt' | 'pbkdf2'\n private readonly _iterations: number\n private readonly _scrypt: { N: number; r: number; p: number }\n private readonly _onProgress: ((fraction: number) => void) | undefined\n private readonly _crypto: Crypto\n\n constructor(options: VaultOptions) {\n this._storage = options.storage\n this._kdf = options.kdf ?? 'scrypt'\n this._iterations = options.iterations ?? VAULT_DEFAULT_ITERATIONS\n this._scrypt = options.scrypt ?? VAULT_SCRYPT\n this._onProgress = options.onProgress\n this._crypto = options.crypto ?? globalThis.crypto\n if (!Number.isInteger(this._iterations) || this._iterations < VAULT_MIN_ITERATIONS || this._iterations > VAULT_LIMITS.iterations) {\n throw new VaultError(`PBKDF2 iterations must be an integer from ${VAULT_MIN_ITERATIONS} to ${VAULT_LIMITS.iterations}`, 'invalid-input')\n }\n if (!isStrongScrypt(this._scrypt)) throw new VaultError(`scrypt cost must be at least N=${VAULT_MIN_SCRYPT.N} r=${VAULT_MIN_SCRYPT.r} p=${VAULT_MIN_SCRYPT.p} (N a power of two)`, 'invalid-input')\n if (!isBoundedScrypt(this._scrypt)) throw new VaultError(`scrypt cost must be at most N=${VAULT_LIMITS.scrypt.N} r=${VAULT_LIMITS.scrypt.r} p=${VAULT_LIMITS.scrypt.p}`, 'invalid-input')\n }\n\n async exists(): Promise<boolean> {\n return (await this._storage.get()) !== null\n }\n\n /** What protects the DEK right now (UI). `null` without a vault. */\n async kdfInfo(): Promise<VaultKdfInfo | null> {\n const e = await this._storage.get()\n if (!e) return null\n if (isEnvelopeV1(e)) return { version: 1, name: 'PBKDF2-SHA256', summary: `PBKDF2-SHA256 ${e.kdf.iterations.toLocaleString('en-US')} iterations` }\n if (isEnvelopeV2(e)) return { version: 2, name: 'scrypt', summary: `scrypt N=2^${Math.log2(e.kdf.N)} r=${e.kdf.r} p=${e.kdf.p}` }\n return null\n }\n\n /**\n * Create an empty vault protected by `password`. Returns the DEK — hand it to the\n * session, then `setSecret` the first seed. Refuses when a vault exists.\n */\n async create(password: string): Promise<Uint8Array> {\n requirePassword(password, VAULT_MIN_PASSWORD_LENGTH)\n return this._exclusive(async () => {\n if (await this.exists()) throw new VaultError('A vault already exists; unlock it or reset explicitly.', 'exists')\n const dek = this._random(DEK_BYTES)\n await this._write(await this._sealEnvelope(password, dek, {}, [], Date.now()))\n return dek\n })\n }\n\n /**\n * Derive the KEK from `password`, unseal and return the DEK. `wrong-password` on\n * failure. A v1 (PBKDF2) envelope that opens is re-sealed as v2 (scrypt) on the\n * way out, secrets untouched.\n */\n async unlock(password: string): Promise<Uint8Array> {\n requirePassword(password)\n return this._exclusive(() => this._unlock(password))\n }\n\n private async _unlock(password: string): Promise<Uint8Array> {\n const envelope = await this._load()\n if (isEnvelopeV1(envelope)) {\n if (envelope.kdf.iterations < VAULT_MIN_ITERATIONS) throw new VaultError(`The vault's KDF (${envelope.kdf.iterations} iterations) is below the floor this build accepts.`, 'weak-kdf')\n const kek = await this._derivePbkdf2(password, fromBase64(envelope.kdf.salt), envelope.kdf.iterations)\n const dek = await this._open(kek, envelope.dek, aadDekV1(envelope.kdf), 'wrong-password')\n if (this._kdf === 'scrypt') {\n // Upgrade in place: same secrets, same createdAt, scrypt-wrapped DEK.\n const next = await this._sealEnvelope(password, dek, envelope.secrets, [], envelope.createdAt)\n await this._write(isEnvelopeV2(next) ? { ...next, upgradedAt: Date.now() } : next)\n }\n return dek\n }\n if (!isStrongScrypt(envelope.kdf)) throw new VaultError(`The vault's scrypt cost (N=${envelope.kdf.N} r=${envelope.kdf.r} p=${envelope.kdf.p}) is below the floor this build accepts.`, 'weak-kdf')\n const kek = await this._deriveScrypt(password, fromBase64(envelope.kdf.salt), envelope.kdf)\n return this._open(kek, envelope.dek, aadDekV2(envelope.kdf), 'wrong-password')\n }\n\n /**\n * Re-wrap the DEK under a new password (fresh salt, current KDF). Secrets and passkeys are untouched —\n * and so is the DEK: after a suspected compromise (a copied profile, a leaked session, a lost passkey)\n * this is not enough, because whoever holds the DEK still opens every secret, old and new. Use\n * {@link Vault.rotateVaultKey} then.\n */\n async changePassword(oldPassword: string, newPassword: string): Promise<void> {\n requirePassword(newPassword, VAULT_MIN_PASSWORD_LENGTH)\n requirePassword(oldPassword)\n return this._exclusive(async () => {\n const dek = await this._unlock(oldPassword)\n try {\n const envelope = await this._load()\n const passkeys = isEnvelopeV2(envelope) ? envelope.passkeys : []\n const next = await this._sealEnvelope(newPassword, dek, envelope.secrets, passkeys, envelope.createdAt)\n await this._write(isEnvelopeV2(envelope) && envelope.upgradedAt !== undefined && isEnvelopeV2(next) ? { ...next, upgradedAt: envelope.upgradedAt } : next)\n } finally {\n zeroize(dek)\n }\n })\n }\n\n /**\n * Replace the DEK (scan 2026-10-27 modules, F30): a fresh random DEK, every secret re-sealed under it,\n * the DEK wrapped under `password` with a fresh salt — written as one envelope, so a failure leaves the\n * old vault as it was. Returns the new DEK: hand it to `session.unlock(dek)`, which overwrites the old\n * one in `chrome.storage.session`. A DEK copied before the rotation opens nothing in the new envelope,\n * and {@link Vault.setSecret} refuses it, so a stale session cannot seal new secrets under it.\n *\n * Passkeys are dropped — their boxes hold the old DEK and cannot be re-wrapped without their PRF\n * output — and must be registered again ({@link Vault.addPasskey} with the new DEK).\n */\n async rotateVaultKey(password: string): Promise<Uint8Array> {\n requirePassword(password)\n return this._exclusive(async () => {\n const oldDek = await this._unlock(password)\n const dek = this._random(DEK_BYTES)\n try {\n const envelope = await this._load()\n const [oldKey, newKey] = await Promise.all([this._importDek(oldDek), this._importDek(dek)])\n const secrets: Record<string, SealedBox> = {}\n for (const [id, box] of Object.entries(envelope.secrets)) {\n const plaintext = await this._open(oldKey, box, aadSecret(id), 'locked')\n try {\n secrets[id] = await this._seal(newKey, plaintext, aadSecret(id))\n } finally {\n zeroize(plaintext)\n }\n }\n const next = await this._sealEnvelope(password, dek, secrets, [], envelope.createdAt)\n const upgradedAt = isEnvelopeV2(envelope) ? envelope.upgradedAt : undefined\n await this._write(isEnvelopeV2(next) ? { ...next, ...(upgradedAt !== undefined ? { upgradedAt } : {}), rotatedAt: Date.now() } : next)\n return dek\n } catch (e) {\n zeroize(dek)\n throw e\n } finally {\n zeroize(oldDek)\n }\n })\n }\n\n // ---- passkeys (v2) ----\n\n /** Public view of the registered passkeys (ids, labels; whether each can verify assertions). */\n async listPasskeys(): Promise<Array<{ id: string; label: string; createdAt: number; canVerify: boolean }>> {\n const e = await this._storage.get()\n if (!e || !isEnvelopeV2(e)) return []\n return e.passkeys.map((p) => ({ id: p.id, label: p.label, createdAt: p.createdAt, canVerify: typeof p.publicKey === 'string' && p.alg === -7 }))\n }\n\n /** The SPKI public key (base64) of one passkey, for assertion verification; `null` when unknown. */\n async passkeyPublicKey(id: string): Promise<{ publicKey: string; alg: number } | null> {\n const e = await this._storage.get()\n if (!e || !isEnvelopeV2(e)) return null\n const p = e.passkeys.find((k) => k.id === id)\n return p?.publicKey && p.alg !== undefined ? { publicKey: p.publicKey, alg: p.alg } : null\n }\n\n /**\n * Register a passkey as a second unlock path: the DEK (from the unlocked session)\n * is sealed under HKDF-SHA256(`prf`, salt = credential id). The password stays\n * the recovery path; `prf` is zeroized here. A v1 envelope must be unlocked (and\n * thereby upgraded) first, and the vault must hold a secret (it proves the DEK).\n */\n async addPasskey(dek: Uint8Array, passkey: { id: string; prf: Uint8Array; label: string; publicKey?: string | undefined; alg?: number | undefined }): Promise<void> {\n try {\n requireId(passkey.id)\n if (passkey.prf.length !== PRF_BYTES) throw new VaultError(`A PRF output is ${PRF_BYTES} bytes.`, 'invalid-input')\n await this._exclusive(() => this._addPasskey(dek, passkey))\n } finally {\n zeroize(passkey.prf)\n }\n }\n\n private async _addPasskey(dek: Uint8Array, passkey: { id: string; prf: Uint8Array; label: string; publicKey?: string | undefined; alg?: number | undefined }): Promise<void> {\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) throw new VaultError('Unlock with the password once so the vault is upgraded before adding a passkey.', 'unsupported-envelope')\n if (envelope.passkeys.some((p) => p.id === passkey.id)) throw new VaultError('This passkey is already registered.', 'exists')\n // Prove the DEK is the vault's before sealing it under a new key.\n await this._requireDek(dek, envelope)\n const key = await this._derivePasskeyKek(passkey.prf, passkey.id)\n const entry: VaultPasskey = { id: passkey.id, label: passkey.label.slice(0, 64), createdAt: Date.now(), dek: await this._seal(key, dek, aadPasskey(passkey.id)) }\n if (passkey.publicKey && passkey.alg !== undefined) { entry.publicKey = passkey.publicKey; entry.alg = passkey.alg }\n await this._write({ ...envelope, passkeys: [...envelope.passkeys, entry] })\n }\n\n /** Unseal the DEK with a passkey's PRF output. `wrong-password` when the box does not open, `missing` when the id is unknown. */\n async unlockWithPasskey(id: string, prf: Uint8Array): Promise<Uint8Array> {\n try {\n requireId(id)\n if (prf.length !== PRF_BYTES) throw new VaultError(`A PRF output is ${PRF_BYTES} bytes.`, 'invalid-input')\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) throw new VaultError('This vault has no passkeys; unlock with the password.', 'missing')\n const entry = envelope.passkeys.find((p) => p.id === id)\n if (!entry) throw new VaultError('No such passkey on this vault.', 'missing')\n const key = await this._derivePasskeyKek(prf, id)\n return await this._open(key, entry.dek, aadPasskey(id), 'wrong-password')\n } finally {\n zeroize(prf)\n }\n }\n\n /** Forget one passkey's box. A DEK that passkey already unwrapped stays valid: after a lost or compromised passkey, {@link Vault.rotateVaultKey}. */\n async removePasskey(id: string): Promise<void> {\n requireId(id)\n return this._exclusive(async () => {\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) return\n await this._write({ ...envelope, passkeys: envelope.passkeys.filter((p) => p.id !== id) })\n })\n }\n\n // ---- secrets ----\n\n async listSecretIds(): Promise<string[]> {\n const envelope = await this._storage.get()\n return envelope ? Object.keys(envelope.secrets) : []\n }\n\n /**\n * Seal `secret` under the DEK as `sourceId` (overwrites an entry with the same id). The DEK must open the\n * vault's secrets (`locked` otherwise): a key retired by {@link Vault.rotateVaultKey} never seals a new one.\n */\n async setSecret(dek: Uint8Array, sourceId: string, secret: Uint8Array): Promise<void> {\n requireId(sourceId)\n if (secret.length > VAULT_LIMITS.secretBytes) throw new VaultError(`A secret is at most ${VAULT_LIMITS.secretBytes} bytes.`, 'invalid-input')\n const key = await this._importDek(dek)\n return this._exclusive(async () => {\n const envelope = await this._load()\n // Only an envelope from before the DEK check, still empty, has nothing to prove the key with.\n if (envelope.dekCheck !== undefined || Object.keys(envelope.secrets).length > 0) await this._requireDek(dek, envelope)\n if (!(sourceId in envelope.secrets) && Object.keys(envelope.secrets).length >= VAULT_LIMITS.secrets) {\n throw new VaultError(`A vault holds at most ${VAULT_LIMITS.secrets} secrets.`, 'invalid-input')\n }\n const box = await this._seal(key, secret, aadSecret(sourceId))\n await this._write({ ...envelope, secrets: { ...envelope.secrets, [sourceId]: box } })\n })\n }\n\n /** Unseal one secret. `null` when the id is unknown; the caller zeroizes the result after use. */\n async getSecret(dek: Uint8Array, sourceId: string): Promise<Uint8Array | null> {\n requireId(sourceId)\n const envelope = await this._load()\n const box = envelope.secrets[sourceId]\n if (!box) return null\n const key = await this._importDek(dek)\n return this._open(key, box, aadSecret(sourceId), 'locked')\n }\n\n async deleteSecret(sourceId: string): Promise<void> {\n requireId(sourceId)\n return this._exclusive(async () => {\n const envelope = await this._load()\n if (!(sourceId in envelope.secrets)) return\n const secrets = { ...envelope.secrets }\n delete secrets[sourceId]\n await this._write({ ...envelope, secrets })\n })\n }\n\n /** Remove the whole vault. The explicit destructive flow only (back up → wipe → create). */\n async destroy(): Promise<void> {\n return this._exclusive(() => this._storage.clear())\n }\n\n // ---- serialized writes ----\n\n private _exclusive<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn)\n this._queue = run.catch(() => undefined)\n return run\n }\n\n /** Store an envelope this build will open again (bounds checked before it is written). */\n private async _write(envelope: VaultEnvelope): Promise<void> {\n const problem = envelopeProblem(envelope)\n if (problem) throw new VaultError(`The vault would exceed its limits (${problem}); nothing was written.`, 'invalid-input')\n await this._storage.set(envelope)\n }\n\n // ---- crypto ----\n\n private _random(n: number): Uint8Array {\n return this._crypto.getRandomValues(new Uint8Array(n))\n }\n\n /** A fresh envelope (v2 by default, v1 with `kdf: 'pbkdf2'`) wrapping `dek` under `password`. */\n private async _sealEnvelope(password: string, dek: Uint8Array, secrets: Record<string, SealedBox>, passkeys: VaultPasskey[], createdAt: number): Promise<VaultEnvelope> {\n const salt = this._random(SALT_BYTES)\n if (this._kdf === 'pbkdf2') {\n const kdf: VaultEnvelopeV1['kdf'] = { name: 'PBKDF2-SHA256', iterations: this._iterations, salt: toBase64(salt) }\n const kek = await this._derivePbkdf2(password, salt, this._iterations)\n return { v: 1, kdf, dek: await this._seal(kek, dek, aadDekV1(kdf)), secrets, dekCheck: await this._sealDekCheck(dek), createdAt }\n }\n const kdf: VaultEnvelopeV2['kdf'] = { name: 'scrypt', ...this._scrypt, salt: toBase64(salt) }\n const kek = await this._deriveScrypt(password, salt, kdf)\n return { v: 2, kdf, dek: await this._seal(kek, dek, aadDekV2(kdf)), secrets, dekCheck: await this._sealDekCheck(dek), passkeys, createdAt }\n }\n\n /** The DEK check box: {@link DEK_CHECK} sealed under `dek`. */\n private async _sealDekCheck(dek: Uint8Array): Promise<SealedBox> {\n return this._seal(await this._importDek(dek), new TextEncoder().encode(DEK_CHECK), AAD_DEK_CHECK)\n }\n\n /**\n * The caller's DEK must open this envelope's DEK check (or, in an envelope written before it, its\n * first secret) — it is the key the password protects, not any 32 bytes. An old empty envelope has\n * nothing to prove it with, so it is refused rather than trusted.\n */\n private async _requireDek(dek: Uint8Array, envelope: VaultEnvelope): Promise<void> {\n const ids = Object.keys(envelope.secrets)\n const key = await this._importDek(dek)\n if (envelope.dekCheck !== undefined) {\n const check = await this._open(key, envelope.dekCheck, AAD_DEK_CHECK, 'locked')\n const ok = new TextDecoder().decode(check) === DEK_CHECK\n zeroize(check)\n if (!ok) throw new VaultError('The vault key does not open this entry; lock and unlock again.', 'locked')\n return\n }\n if (ids.length === 0) throw new VaultError('Add a secret to the vault before a passkey: an empty vault cannot prove the key is its own.', 'invalid-input')\n const probe = await this._open(key, envelope.secrets[ids[0]!]!, aadSecret(ids[0]!), 'locked')\n zeroize(probe)\n }\n\n private async _derivePbkdf2(password: string, salt: Uint8Array, iterations: number): Promise<CryptoKey> {\n const subtle = this._crypto.subtle\n const pw = new TextEncoder().encode(password.normalize('NFKC'))\n let material: CryptoKey\n try {\n material = await withSecretBuffer(pw, (b) => subtle.importKey('raw', b, 'PBKDF2', false, ['deriveKey']))\n } finally {\n zeroize(pw)\n }\n return subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-256', salt: toArrayBuffer(salt), iterations }, material, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\n }\n\n private async _deriveScrypt(password: string, salt: Uint8Array, cost: { N: number; r: number; p: number }): Promise<CryptoKey> {\n const pw = new TextEncoder().encode(password.normalize('NFKC'))\n let raw: Uint8Array\n try {\n raw = await scryptAsync(pw, salt, { N: cost.N, r: cost.r, p: cost.p, dkLen: 32, maxmem: 2 * 128 * cost.N * cost.r + 1024 * 1024, ...(this._onProgress ? { onProgress: this._onProgress } : {}) })\n } finally {\n zeroize(pw)\n }\n try {\n return await withSecretBuffer(raw, (b) => this._crypto.subtle.importKey('raw', b, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']))\n } finally {\n zeroize(raw)\n }\n }\n\n /** HKDF-SHA256(ikm = PRF output, salt = credential id bytes, info) → AES-256-GCM key. */\n private async _derivePasskeyKek(prf: Uint8Array, credentialId: string): Promise<CryptoKey> {\n const subtle = this._crypto.subtle\n const ikm = await withSecretBuffer(prf, (b) => subtle.importKey('raw', b, 'HKDF', false, ['deriveKey']))\n return subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt: toArrayBuffer(fromBase64Url(credentialId)), info: toArrayBuffer(new TextEncoder().encode(HKDF_INFO)) }, ikm, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\n }\n\n private async _importDek(dek: Uint8Array): Promise<CryptoKey> {\n if (dek.length !== DEK_BYTES) throw new VaultError('Vault key must be 32 bytes.', 'invalid-input')\n return withSecretBuffer(dek, (b) => this._crypto.subtle.importKey('raw', b, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']))\n }\n\n private async _seal(key: CryptoKey, plaintext: Uint8Array, aad: string): Promise<SealedBox> {\n const iv = this._random(IV_BYTES)\n const ct = await withSecretBuffer(plaintext, (b) => this._crypto.subtle.encrypt({ name: 'AES-GCM', iv: toArrayBuffer(iv), additionalData: toArrayBuffer(new TextEncoder().encode(aad)) }, key, b))\n return { iv: toBase64(iv), data: toBase64(new Uint8Array(ct)) }\n }\n\n private async _open(key: CryptoKey, box: SealedBox, aad: string, onFail: 'wrong-password' | 'locked'): Promise<Uint8Array> {\n try {\n const pt = await this._crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: toArrayBuffer(fromBase64(box.iv)), additionalData: toArrayBuffer(new TextEncoder().encode(aad)) },\n key,\n toArrayBuffer(fromBase64(box.data)),\n )\n return new Uint8Array(pt)\n } catch {\n throw new VaultError(onFail === 'wrong-password' ? 'Wrong password.' : 'The vault key does not open this entry; lock and unlock again.', onFail)\n }\n }\n\n private async _load(): Promise<VaultEnvelope> {\n const envelope = await this._storage.get()\n if (!envelope) throw new VaultError('No vault in this storage area.', 'missing')\n if (!isEnvelopeV1(envelope) && !isEnvelopeV2(envelope)) throw new VaultError('Unsupported vault envelope.', 'unsupported-envelope')\n const problem = envelopeProblem(envelope)\n if (problem) throw new VaultError(`The vault envelope is outside the limits this build opens (${problem}).`, 'unsupported-envelope')\n return envelope\n }\n}\n\nexport function isEnvelopeV1(x: unknown): x is VaultEnvelopeV1 {\n if (typeof x !== 'object' || x === null) return false\n const e = x as Record<string, unknown>\n const kdf = e.kdf as Record<string, unknown> | undefined\n return (\n e.v === 1 &&\n typeof kdf === 'object' && kdf !== null && kdf.name === 'PBKDF2-SHA256' && Number.isInteger(kdf.iterations) && typeof kdf.salt === 'string' &&\n isBox(e.dek) &&\n typeof e.secrets === 'object' && e.secrets !== null && Object.values(e.secrets as object).every(isBox) &&\n (e.dekCheck === undefined || isBox(e.dekCheck))\n )\n}\n\nexport function isEnvelopeV2(x: unknown): x is VaultEnvelopeV2 {\n if (typeof x !== 'object' || x === null) return false\n const e = x as Record<string, unknown>\n const kdf = e.kdf as Record<string, unknown> | undefined\n return (\n e.v === 2 &&\n typeof kdf === 'object' && kdf !== null && kdf.name === 'scrypt' && Number.isInteger(kdf.N) && Number.isInteger(kdf.r) && Number.isInteger(kdf.p) && typeof kdf.salt === 'string' &&\n isBox(e.dek) &&\n typeof e.secrets === 'object' && e.secrets !== null && Object.values(e.secrets as object).every(isBox) &&\n (e.dekCheck === undefined || isBox(e.dekCheck)) &&\n Array.isArray(e.passkeys) && e.passkeys.every((p) => typeof p === 'object' && p !== null && typeof (p as VaultPasskey).id === 'string' && typeof (p as VaultPasskey).label === 'string' && isBox((p as VaultPasskey).dek))\n )\n}\n\nfunction isBox(x: unknown): x is SealedBox {\n return typeof x === 'object' && x !== null && typeof (x as SealedBox).iv === 'string' && typeof (x as SealedBox).data === 'string'\n}\n\nfunction isBoundedScrypt(c: { N: number; r: number; p: number }): boolean {\n return c.N <= VAULT_LIMITS.scrypt.N && c.r <= VAULT_LIMITS.scrypt.r && c.p <= VAULT_LIMITS.scrypt.p\n}\n\n/** Why an envelope is outside {@link VAULT_LIMITS}, or null when it is within them. */\nfunction envelopeProblem(e: VaultEnvelope): string | null {\n if (e.v === 1 && e.kdf.iterations > VAULT_LIMITS.iterations) return `PBKDF2 iterations ${e.kdf.iterations} > ${VAULT_LIMITS.iterations}`\n if (e.v === 2 && !isBoundedScrypt(e.kdf)) return `scrypt N=${e.kdf.N} r=${e.kdf.r} p=${e.kdf.p} above N=${VAULT_LIMITS.scrypt.N} r=${VAULT_LIMITS.scrypt.r} p=${VAULT_LIMITS.scrypt.p}`\n const secrets = Object.values(e.secrets)\n if (secrets.length > VAULT_LIMITS.secrets) return `${secrets.length} secrets > ${VAULT_LIMITS.secrets}`\n const passkeys = e.v === 2 ? e.passkeys : []\n if (passkeys.length > VAULT_LIMITS.passkeys) return `${passkeys.length} passkeys > ${VAULT_LIMITS.passkeys}`\n for (const box of [e.dek, ...(e.dekCheck ? [e.dekCheck] : []), ...secrets, ...passkeys.map((p) => p.dek)]) {\n if (box.iv.length > VAULT_LIMITS.boxChars || box.data.length > VAULT_LIMITS.boxChars) return `a sealed box above ${VAULT_LIMITS.boxChars} characters`\n }\n if (JSON.stringify(e).length > VAULT_LIMITS.envelopeChars) return `envelope above ${VAULT_LIMITS.envelopeChars} characters`\n return null\n}\n\nfunction isStrongScrypt(c: { N: number; r: number; p: number }): boolean {\n return Number.isInteger(c.N) && c.N >= VAULT_MIN_SCRYPT.N && (c.N & (c.N - 1)) === 0 && Number.isInteger(c.r) && c.r >= VAULT_MIN_SCRYPT.r && Number.isInteger(c.p) && c.p >= VAULT_MIN_SCRYPT.p\n}\n\nfunction requirePassword(password: string, minLength = 1): void {\n if (typeof password !== 'string' || password.length === 0) throw new VaultError('Password must not be empty.', 'invalid-input')\n if ([...password].length < minLength) throw new VaultError(`Password must be at least ${minLength} characters.`, 'invalid-input')\n}\n\nfunction requireId(id: string): void {\n if (typeof id !== 'string' || id.length === 0 || id.length > 128) throw new VaultError('Bad source id.', 'invalid-input')\n}\n\n/** base64url (WebAuthn ids) → bytes; plain base64 is accepted too. */\nexport function fromBase64Url(text: string): Uint8Array {\n const b64 = text.replace(/-/g, '+').replace(/_/g, '/')\n return fromBase64(b64 + '='.repeat((4 - (b64.length % 4)) % 4))\n}\n\nexport function toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Envelope in memory — tests and the smoke. */\nexport function memoryVaultStorage(initial: VaultEnvelope | null = null): VaultStorage & { envelope: VaultEnvelope | null } {\n const s = {\n envelope: initial,\n async get() { return s.envelope ? structuredClone(s.envelope) : null },\n async set(envelope: VaultEnvelope) { s.envelope = structuredClone(envelope) },\n async clear() { s.envelope = null },\n }\n return s\n}\n","// base64 for the JSON envelopes — `btoa`/`atob` exist in every extension context (service worker included).\n\nexport function toBase64(bytes: Uint8Array): string {\n let s = ''\n for (let i = 0; i < bytes.length; i += 0x8000) s += String.fromCharCode(...bytes.subarray(i, i + 0x8000))\n return btoa(s)\n}\n\nexport function fromBase64(text: string): Uint8Array {\n const s = atob(text)\n const out = new Uint8Array(s.length)\n for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i)\n return out\n}\n\nexport const utf8 = {\n encode: (text: string): Uint8Array => new TextEncoder().encode(text),\n decode: (bytes: Uint8Array): string => new TextDecoder().decode(bytes),\n}\n\n/** Copy into a fresh ArrayBuffer — WebCrypto rejects views over shared / offset buffers in some engines. */\nexport function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength)\n copy.set(bytes)\n return copy.buffer\n}\n\n/**\n * {@link toArrayBuffer} for a secret (a key, a password, a plaintext): `fn` gets the copy, which is\n * zero-filled afterwards whatever happens. WebCrypto copies its input when called, so wiping after\n * the returned promise settles is safe.\n */\nexport async function withSecretBuffer<T>(bytes: Uint8Array, fn: (buffer: ArrayBuffer) => Promise<T>): Promise<T> {\n const buffer = toArrayBuffer(bytes)\n try {\n return await fn(buffer)\n } finally {\n new Uint8Array(buffer).fill(0)\n }\n}\n","/**\n * The unlocked state. An MV3 service worker dies after ~30 s idle, so the\n * unlocked vault key cannot live in a JS variable: it lives in\n * `chrome.storage.session` (memory-only, cleared when the browser exits, readable\n * by extension contexts only) together with its expiry, and a `chrome.alarms`\n * alarm locks it when the auto-lock timer (default 15 min since the last\n * activity) runs out.\n *\n * The session never sees a password or a seed — only the DEK the vault returned.\n * The popup never receives the DEK either: it asks the service worker to\n * perform operations by id.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport { fromBase64, toBase64 } from './codec.js'\nimport { VaultError } from './errors.js'\n\n/** Structural `chrome.storage.session` (or any `StorageArea`); `memorySessionStorage()` for tests. */\nexport interface SessionStorage {\n get(key: string): Promise<unknown>\n set(key: string, value: unknown): Promise<void>\n remove(key: string): Promise<void>\n}\n\n/** Structural `chrome.alarms`: one named alarm, fired once at `when` (ms since epoch). */\nexport interface SessionAlarms {\n schedule(name: string, when: number): Promise<void> | void\n clear(name: string): Promise<void> | void\n /** Register the lock callback; the chrome adapter wires `chrome.alarms.onAlarm`. */\n onFire(handler: (name: string) => void): void\n}\n\nexport interface SessionOptions {\n storage: SessionStorage\n alarms: SessionAlarms\n /** Lock this long after the last `touch` / `unlock`. Default 15 min; 0 disables the timer (lock only on browser exit or explicit lock; stored as `expiresAt: null`). */\n autoLockMs?: number\n /** Storage key and alarm name prefix. */\n name?: string\n /** Clock, injectable for tests. */\n now?: () => number\n}\n\ninterface SessionRecord {\n key: string\n /** When the auto-lock fires (ms since epoch); `null` = no auto-lock. Never `Infinity`: chrome.storage stores JSON. */\n expiresAt: number | null\n}\n\nexport const SESSION_DEFAULT_AUTOLOCK_MS = 15 * 60_000\n\nexport class Session {\n private readonly _storage: SessionStorage\n private readonly _alarms: SessionAlarms\n private _autoLockMs: number\n private readonly _key: string\n private readonly _alarm: string\n private readonly _now: () => number\n private readonly _onLock = new Set<() => void>()\n /**\n * Every operation on the stored record runs here, one after another: a `touch` that read the\n * record before a `lock` removed it would otherwise write it back and undo the lock.\n */\n private _queue: Promise<unknown> = Promise.resolve()\n /** Bumped by every lock; a `touch` writes only when no lock happened since it read the record. */\n private _epoch = 0\n\n constructor(options: SessionOptions) {\n this._storage = options.storage\n this._alarms = options.alarms\n this._autoLockMs = options.autoLockMs ?? SESSION_DEFAULT_AUTOLOCK_MS\n const name = options.name ?? 'anywalletkit-session'\n this._key = name\n this._alarm = `${name}/autolock`\n this._now = options.now ?? Date.now\n this._alarms.onFire((fired) => { if (fired === this._alarm) void this.lock() })\n }\n\n /** Store the DEK and arm the auto-lock. The caller's copy is zeroized. */\n async unlock(dek: Uint8Array): Promise<void> {\n if (dek.length !== 32) throw new VaultError('Vault key must be 32 bytes.', 'invalid-input')\n return this._serial(async () => {\n const expiresAt = this._expiry()\n await this._storage.set(this._key, { key: toBase64(dek), expiresAt } satisfies SessionRecord)\n zeroize(dek)\n await this._arm(expiresAt)\n })\n }\n\n /** Forget the DEK and cancel the alarm. Safe to call when already locked. */\n async lock(): Promise<void> {\n return this._serial(() => this._lockNow())\n }\n\n async isUnlocked(): Promise<boolean> {\n return this._serial(async () => (await this._read()) !== null)\n }\n\n /**\n * The DEK for one operation (zeroize it after). `locked` when there is none or the\n * timer ran out while the worker was asleep — the record is then removed as well, so\n * a missed alarm cannot keep the key alive.\n */\n async getKey(): Promise<Uint8Array> {\n return this._serial(async () => {\n const record = await this._read()\n if (!record) throw new VaultError('Wallet is locked.', 'locked')\n return fromBase64(record.key)\n })\n }\n\n /** User activity: push the auto-lock out again. No-op when locked. */\n async touch(): Promise<void> {\n return this._serial(async () => {\n const epoch = this._epoch\n const record = await this._read()\n if (!record || epoch !== this._epoch) return\n const expiresAt = this._expiry()\n await this._storage.set(this._key, { ...record, expiresAt } satisfies SessionRecord)\n await this._arm(expiresAt)\n })\n }\n\n get autoLockMs(): number {\n return this._autoLockMs\n }\n\n /** Change the timer (options page); re-arms from now when unlocked. 0 disables. */\n async setAutoLockMs(ms: number): Promise<void> {\n if (!Number.isFinite(ms) || ms < 0) throw new VaultError('Auto-lock must be a non-negative number of milliseconds.', 'invalid-input')\n this._autoLockMs = ms\n await this.touch()\n }\n\n onLock(callback: () => void): () => void {\n this._onLock.add(callback)\n return () => this._onLock.delete(callback)\n }\n\n private _serial<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn)\n this._queue = run.catch(() => undefined)\n return run\n }\n\n /** The lock itself; callers are already in the queue. */\n private async _lockNow(): Promise<void> {\n this._epoch++\n const was = await this._storage.get(this._key)\n await this._storage.remove(this._key)\n await this._alarms.clear(this._alarm)\n if (was !== undefined && was !== null) for (const cb of this._onLock) cb()\n }\n\n private _expiry(): number | null {\n return this._autoLockMs > 0 ? this._now() + this._autoLockMs : null\n }\n\n private async _arm(expiresAt: number | null): Promise<void> {\n if (expiresAt !== null) await this._alarms.schedule(this._alarm, expiresAt)\n else await this._alarms.clear(this._alarm)\n }\n\n /** The stored record, or `null` when locked. A record that is there but unreadable locks the wallet (removed, listeners told). */\n private async _read(): Promise<SessionRecord | null> {\n const raw = await this._storage.get(this._key)\n if (raw === undefined || raw === null) return null\n const r = raw as Partial<SessionRecord>\n const expiryOk = r.expiresAt === null || (typeof r.expiresAt === 'number' && Number.isFinite(r.expiresAt))\n if (typeof raw !== 'object' || typeof r.key !== 'string' || !expiryOk || !isKey(r.key)) { await this._lockNow(); return null }\n if (r.expiresAt !== null && r.expiresAt! <= this._now()) { await this._lockNow(); return null }\n return r as SessionRecord\n }\n}\n\n/** A stored DEK: base64 of exactly 32 bytes (the decoded copy is wiped). */\nfunction isKey(text: string): boolean {\n let bytes: Uint8Array\n try { bytes = fromBase64(text) } catch { return false }\n const ok = bytes.length === 32\n zeroize(bytes)\n return ok\n}\n\n/** In-memory `chrome.storage.session` stand-in. */\nexport function memorySessionStorage(): SessionStorage & { data: Map<string, unknown> } {\n const data = new Map<string, unknown>()\n return {\n data,\n async get(key) { return data.get(key) },\n async set(key, value) { data.set(key, structuredClone(value)) },\n async remove(key) { data.delete(key) },\n }\n}\n\n/** In-memory alarms: `fire(name)` from the test, `pending` to inspect. */\nexport function memoryAlarms(): SessionAlarms & { pending: Map<string, number>; fire(name: string): void } {\n const pending = new Map<string, number>()\n const handlers = new Set<(name: string) => void>()\n return {\n pending,\n schedule(name, when) { pending.set(name, when) },\n clear(name) { pending.delete(name) },\n onFire(handler) { handlers.add(handler) },\n fire(name) { pending.delete(name); for (const h of handlers) h(name) },\n }\n}\n","/**\n * Message shapes on the two hops between a dApp and the wallet:\n *\n * ```text\n * page (injected provider, MAIN world)\n * │ window.postMessage — PageRequest ⇄ PageResponse / PageEvent\n * content script (isolated world) — stamps `location.origin`, owns the port\n * │ chrome.runtime.connect(PORT_NAME) — RelayRequest ⇄ RelayResponse / RelayEvent\n * service worker — trusts `port.sender` (set by the browser), never the page\n * ```\n *\n * The page can forge anything it posts, so a page message carries no origin and\n * no identity: the content script adds the origin, and the service worker\n * cross-checks it against `port.sender.origin` ({@link checkSenderOrigin}) — a\n * mismatch is dropped, not answered. Request ids are opaque strings minted by\n * the page side ({@link newRequestId}); the content script does not reuse them\n * across ports.\n */\n\n/** `chrome.runtime.connect({ name })` for content-script ports. */\nexport const PORT_NAME = 'anywalletkit/relay/1'\n/** `window.postMessage` discriminators (both directions). */\nexport const PAGE_TARGET = { toContent: 'anywalletkit/content', toPage: 'anywalletkit/page' } as const\n\n/** CAIP-2 namespace of the provider that spoke. */\nexport type RelayChain = 'eip155' | 'solana' | 'ton' | 'tron' | 'bip122' | 'near'\n\nexport interface RelayError {\n /** EIP-1193 / EIP-1474 numbering for EVM; the same numbers are reused for the other providers. */\n code: number\n message: string\n data?: unknown\n}\n\nexport const RELAY_ERRORS = {\n userRejected: 4001,\n unauthorized: 4100,\n unsupportedMethod: 4200,\n disconnected: 4900,\n chainDisconnected: 4901,\n /** EIP-3326/3085: the chain is not in the wallet (`wallet_switchEthereumChain` → suggest `wallet_addEthereumChain`). */\n chainNotAdded: 4902,\n internal: -32603,\n invalidRequest: -32600,\n invalidParams: -32602,\n /** EIP-1474: a request of the same kind from this origin is already waiting (MetaMask's \"already pending\"). */\n resourceUnavailable: -32002,\n /** EIP-1474: this origin has too many requests waiting. */\n limitExceeded: -32005,\n} as const\n\n// ---- hop 1: page ⇄ content script ----\n\nexport interface PageRequest {\n target: typeof PAGE_TARGET.toContent\n id: string\n chain: RelayChain\n method: string\n params?: unknown\n}\n\nexport interface PageResponse {\n target: typeof PAGE_TARGET.toPage\n id: string\n result?: unknown\n error?: RelayError\n}\n\nexport interface PageEvent {\n target: typeof PAGE_TARGET.toPage\n chain: RelayChain\n event: string\n data?: unknown\n}\n\n// ---- hop 2: content script ⇄ service worker ----\n\nexport interface RelayRequest {\n kind: 'request'\n id: string\n /** `location.origin` of the page, stamped by the content script. */\n origin: string\n chain: RelayChain\n method: string\n params?: unknown\n}\n\nexport interface RelayResponse {\n kind: 'response'\n id: string\n result?: unknown\n error?: RelayError\n}\n\nexport interface RelayEvent {\n kind: 'event'\n chain: RelayChain\n event: string\n data?: unknown\n}\n\nexport type RelayToWorker = RelayRequest\nexport type RelayToContent = RelayResponse | RelayEvent\n\n// ---- guards ----\n\nconst CHAINS: ReadonlySet<string> = new Set<RelayChain>(['eip155', 'solana', 'ton', 'tron', 'bip122', 'near'])\n\nconst isRecord = (x: unknown): x is Record<string, unknown> => typeof x === 'object' && x !== null\nconst isId = (x: unknown): x is string => typeof x === 'string' && x.length > 0 && x.length <= 64\n/** Longest method name a request may carry. */\nexport const RELAY_METHOD_MAX = 128\n/**\n * A method name as the providers spell them (`eth_sendTransaction`, `signAndSendTransaction`,\n * `tron_requestAccounts`): letters, digits and `_`, at most {@link RELAY_METHOD_MAX}. Anything else\n * is dropped at the relay, so a megabyte \"method\" never reaches a regex, a log or an error message\n * (scan 2026-10-27 modules, F5).\n */\nexport const isRelayMethod = (x: unknown): x is string => typeof x === 'string' && x.length > 0 && x.length <= RELAY_METHOD_MAX && /^[A-Za-z0-9_]+$/.test(x)\n\nexport function isPageRequest(x: unknown): x is PageRequest {\n return isRecord(x) && x.target === PAGE_TARGET.toContent && isId(x.id) && CHAINS.has(x.chain as string) && isRelayMethod(x.method)\n}\n\nexport function isPageResponse(x: unknown): x is PageResponse {\n return isRecord(x) && x.target === PAGE_TARGET.toPage && isId(x.id)\n}\n\nexport function isPageEvent(x: unknown): x is PageEvent {\n return isRecord(x) && x.target === PAGE_TARGET.toPage && !('id' in x) && CHAINS.has(x.chain as string) && typeof x.event === 'string'\n}\n\nexport function isRelayRequest(x: unknown): x is RelayRequest {\n return isRecord(x) && x.kind === 'request' && isId(x.id) && typeof x.origin === 'string' && CHAINS.has(x.chain as string) && isRelayMethod(x.method)\n}\n\nexport function isRelayToContent(x: unknown): x is RelayToContent {\n return isRecord(x) && ((x.kind === 'response' && isId(x.id)) || (x.kind === 'event' && typeof x.event === 'string'))\n}\n\nexport function newRequestId(): string {\n return crypto.randomUUID()\n}\n\n/** What a content script's `message` listener receives (structural `MessageEvent`). */\nexport interface PageMessageEvent { data: unknown; origin: string; source: unknown }\n/** The page window the content script shares (structural `window`). */\nexport interface PageWindow { location: { origin: string } }\n\n/**\n * The page's own request, or `null`. A content script must take only messages the page itself\n * posted — `event.source` is the page window and `event.origin` its origin — or an iframe on the\n * page (an ad, an embed) would have its `parent.postMessage` stamped with the site's origin and\n * shown in the approval window as the site (round 3, H6).\n */\nexport function pageRequestFrom(event: PageMessageEvent, page: PageWindow): PageRequest | null {\n if (event.source !== page || event.origin !== page.location.origin) return null\n return isPageRequest(event.data) ? event.data : null\n}\n\n/** The content script's stamp: {@link PageRequest} + the page origin. */\nexport function stampOrigin(request: PageRequest, origin: string): RelayRequest {\n const { id, chain, method } = request\n return 'params' in request ? { kind: 'request', id, origin, chain, method, params: request.params } : { kind: 'request', id, origin, chain, method }\n}\n\n/** What `port.sender` looks like (structural `chrome.runtime.MessageSender`). */\nexport interface PortSender {\n origin?: string | undefined\n url?: string | undefined\n tab?: { id?: number | undefined } | undefined\n frameId?: number | undefined\n}\n\n/**\n * The service worker's check before it believes a stamped origin: it must equal the\n * origin the browser recorded for the port. Returns the trusted origin or `null`.\n */\nexport function checkSenderOrigin(sender: PortSender | undefined, stamped: string): string | null {\n const fromSender = sender?.origin ?? (sender?.url ? safeOrigin(sender.url) : undefined)\n if (!fromSender || fromSender === 'null') return null\n return fromSender === stamped ? fromSender : null\n}\n\nfunction safeOrigin(url: string): string | undefined {\n try { return new URL(url).origin } catch { return undefined }\n}\n\nexport const relayError = (code: number, message: string, data?: unknown): RelayError => (data === undefined ? { code, message } : { code, message, data })\n","/**\n * Adapters over the `chrome.*` APIs, typed structurally so this package needs no\n * `@types/chrome` and tests can pass fakes. Promise forms (MV3) only.\n */\nimport type { SessionAlarms, SessionStorage } from './session.js'\nimport type { VaultEnvelope, VaultStorage } from './vault.js'\n\nexport interface StorageAreaLike {\n get(keys: string | string[]): Promise<Record<string, unknown>>\n set(items: Record<string, unknown>): Promise<void>\n remove(keys: string | string[]): Promise<void>\n /** `chrome.storage.session` only. */\n setAccessLevel?(options: { accessLevel: 'TRUSTED_CONTEXTS' | 'TRUSTED_AND_UNTRUSTED_CONTEXTS' }): Promise<void>\n}\n\nexport interface AlarmsLike {\n create(name: string, info: { when: number }): Promise<void> | void\n clear(name: string): Promise<boolean> | boolean | void\n onAlarm: { addListener(callback: (alarm: { name: string }) => void): void }\n}\n\n/** Stable storage key: existing vaults live under it — never rename. */\nexport const VAULT_STORAGE_KEY = 'forgewallet.vault.v1'\n\n/** The encrypted envelope in `chrome.storage.local` (survives browser restarts; ciphertext only). */\nexport function chromeLocalVaultStorage(area: StorageAreaLike, key = VAULT_STORAGE_KEY): VaultStorage {\n return {\n async get() { const r = await area.get(key); return (r[key] as VaultEnvelope | undefined) ?? null },\n async set(envelope) { await area.set({ [key]: envelope }) },\n async clear() { await area.remove(key) },\n }\n}\n\n/**\n * `chrome.storage.session`: memory-only, gone when the browser exits. Access is\n * pinned to trusted contexts (the default; made explicit so a content script can\n * never read the unlocked key even if a later change opens the area to them).\n */\nexport function chromeSessionStorage(area: StorageAreaLike): SessionStorage {\n const ready = area.setAccessLevel ? area.setAccessLevel({ accessLevel: 'TRUSTED_CONTEXTS' }) : Promise.resolve()\n return {\n async get(key) { await ready; return (await area.get(key))[key] },\n async set(key, value) { await ready; await area.set({ [key]: value }) },\n async remove(key) { await ready; await area.remove(key) },\n }\n}\n\n/** `chrome.alarms` as one-shot named alarms. Chrome rounds alarms to ≥ 30 s in packed extensions. */\nexport function chromeAlarms(alarms: AlarmsLike): SessionAlarms {\n return {\n async schedule(name, when) { await alarms.create(name, { when }) },\n async clear(name) { await alarms.clear(name) },\n onFire(handler) { alarms.onAlarm.addListener((alarm) => handler(alarm.name)) },\n }\n}\n","/**\n * `@anywalletkit/keyring` adapters for the extension. The keyring stores public\n * metadata (names, addresses, flags) through `KeyringStorage` and one secret per\n * key source through `SecretStorage`:\n *\n * - {@link chromeKeyringStorage}: the metadata as plain JSON in `chrome.storage.local`;\n * - {@link vaultSecretStorage}: every secret sealed in the {@link Vault} under the\n * DEK the {@link Session} holds. Each call fetches the DEK, uses it once and\n * zeroizes it; a locked session surfaces as `VaultError('locked')`, which the\n * service worker turns into \"unlock first\" for the UI.\n *\n * The keyring's secret strings (JSON with the mnemonic) are immutable JS values\n * and cannot be zeroized; the keyring reads one per operation and drops it, so\n * their lifetime is one call. The byte buffers this module owns are zeroized.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport type { KeyringState, KeyringStorage, SecretStorage } from '@anywalletkit/keyring'\nimport type { StorageAreaLike } from './chrome.js'\nimport { utf8 } from './codec.js'\nimport type { Session } from './session.js'\nimport type { Vault } from './vault.js'\n\n/** Stable storage key: existing keyrings live under it — never rename. */\nexport const KEYRING_STORAGE_KEY = 'forgewallet.keyring.v1'\n\n/** Keyring metadata (no secrets) in `chrome.storage.local`. */\nexport function chromeKeyringStorage(area: StorageAreaLike, key = KEYRING_STORAGE_KEY): KeyringStorage {\n return {\n async load() { const r = await area.get(key); return (r[key] as KeyringState | undefined) ?? null },\n async save(state) { await area.set({ [key]: state }) },\n }\n}\n\n/** Keyring secrets sealed in the vault; readable only while the session is unlocked. */\nexport function vaultSecretStorage(vault: Vault, session: Session): SecretStorage {\n const withKey = async <T>(fn: (dek: Uint8Array) => Promise<T>): Promise<T> => {\n const dek = await session.getKey()\n try { return await fn(dek) } finally { zeroize(dek) }\n }\n return {\n async get(sourceId) {\n return withKey(async (dek) => {\n const bytes = await vault.getSecret(dek, sourceId)\n if (!bytes) return null\n try { return utf8.decode(bytes) } finally { zeroize(bytes) }\n })\n },\n async set(sourceId, secret) {\n const bytes = utf8.encode(secret)\n try { await withKey((dek) => vault.setSecret(dek, sourceId, bytes)) } finally { zeroize(bytes) }\n },\n async delete(sourceId) {\n await vault.deleteSecret(sourceId)\n },\n }\n}\n","/**\n * Default EVM networks for an extension built on this kit: the chains Vaulty's in-app\n * browser can read and sign on, with the same public RPC failover lists\n * (`mobile/lib/swap2.ts`), no API keys. A wallet build may prepend its own\n * endpoints; `wallet_addEthereumChain` may add a chain the asset catalog\n * (`@anywalletkit/swap2-assets`) knows — an unknown chain id is refused, so a\n * site cannot point the wallet at a look-alike network.\n */\nimport { isPublicHttpsUrl } from '@anywalletkit/networks/url'\nimport { ccChain } from '@anywalletkit/swap2-assets'\nimport { RELAY_ERRORS, relayError, type RelayError } from './relay.js'\nimport type { JsonStorage } from './storage.js'\n\nexport interface EvmNetwork {\n /** CAIP-2, `eip155:<chainId>`. */\n caip2: string\n chainId: number\n name: string\n /** Native currency symbol, 18 decimals on every chain here (on Arc that is the 18-decimal native view of USDC). */\n symbol: string\n /** Tried in order; the client fails over. */\n rpcs: string[]\n explorer?: string\n /** Set when a SITE supplied the RPC list (wallet_addEthereumChain): every sheet on this network says so and simulations are not trusted. */\n custom?: { origin: string; addedAt: number }\n}\n\nexport const DEFAULT_CHAIN = 'eip155:1'\n\nconst net = (chainId: number, name: string, symbol: string, rpcs: string[], explorer?: string): EvmNetwork =>\n explorer === undefined ? { caip2: `eip155:${chainId}`, chainId, name, symbol, rpcs } : { caip2: `eip155:${chainId}`, chainId, name, symbol, rpcs, explorer }\n\nexport const DEFAULT_NETWORKS: readonly EvmNetwork[] = Object.freeze([\n net(1, 'Ethereum', 'ETH', ['https://ethereum-rpc.publicnode.com', 'https://eth.drpc.org'], 'https://etherscan.io'),\n net(8453, 'Base', 'ETH', ['https://base-rpc.publicnode.com', 'https://mainnet.base.org', 'https://base.drpc.org'], 'https://basescan.org'),\n net(56, 'BNB Chain', 'BNB', ['https://bsc-rpc.publicnode.com', 'https://bsc-dataseed.bnbchain.org', 'https://bsc.drpc.org'], 'https://bscscan.com'),\n net(42161, 'Arbitrum', 'ETH', ['https://arbitrum-one-rpc.publicnode.com', 'https://arb1.arbitrum.io/rpc', 'https://arbitrum.drpc.org'], 'https://arbiscan.io'),\n net(10, 'Optimism', 'ETH', ['https://optimism-rpc.publicnode.com', 'https://mainnet.optimism.io', 'https://optimism.drpc.org'], 'https://optimistic.etherscan.io'),\n net(137, 'Polygon', 'POL', ['https://polygon-bor-rpc.publicnode.com', 'https://polygon.drpc.org'], 'https://polygonscan.com'),\n net(43114, 'Avalanche', 'AVAX', ['https://avalanche-c-chain-rpc.publicnode.com', 'https://api.avax.network/ext/bc/C/rpc', 'https://avalanche.drpc.org'], 'https://snowtrace.io'),\n net(999, 'HyperEVM', 'HYPE', ['https://rpc.hyperliquid.xyz/evm', 'https://hyperliquid.drpc.org', 'https://hyperliquid-json-rpc.stakely.io']),\n net(4663, 'Robinhood Chain', 'ETH', ['https://rpc.mainnet.chain.robinhood.com', 'https://robinhood.drpc.org'], 'https://robinhoodchain.blockscout.com'),\n net(324, 'zkSync Era', 'ETH', ['https://mainnet.era.zksync.io', 'https://zksync.drpc.org'], 'https://era.zksync.network'),\n net(42220, 'Celo', 'CELO', ['https://forno.celo.org', 'https://celo.drpc.org'], 'https://celoscan.io'),\n net(4326, 'MegaETH', 'ETH', ['https://mainnet.megaeth.com/rpc']),\n net(130, 'Unichain', 'ETH', ['https://mainnet.unichain.org', 'https://unichain-rpc.publicnode.com'], 'https://uniscan.xyz'),\n net(143, 'Monad', 'MON', ['https://rpc.monad.xyz']),\n net(9745, 'Plasma', 'XPL', ['https://rpc.plasma.to']),\n net(59144, 'Linea', 'ETH', ['https://rpc.linea.build', 'https://linea-rpc.publicnode.com'], 'https://lineascan.build'),\n net(100, 'Gnosis', 'xDAI', ['https://rpc.gnosischain.com', 'https://gnosis-rpc.publicnode.com'], 'https://gnosisscan.io'),\n net(146, 'Sonic', 'S', ['https://rpc.soniclabs.com', 'https://sonic-rpc.publicnode.com'], 'https://sonicscan.org'),\n net(480, 'World Chain', 'ETH', ['https://worldchain-mainnet.g.alchemy.com/public', 'https://worldchain-mainnet.gateway.tenderly.co'], 'https://worldscan.org'),\n net(1329, 'Sei', 'SEI', ['https://evm-rpc.sei-apis.com'], 'https://seitrace.com'),\n net(57073, 'Ink', 'ETH', ['https://rpc-gel.inkonchain.com'], 'https://explorer.inkonchain.com'),\n net(98866, 'Plume', 'PLUME', ['https://rpc.plume.org'], 'https://explorer.plume.org'),\n net(196, 'X Layer', 'OKB', ['https://rpc.xlayer.tech', 'https://xlayerrpc.okx.com'], 'https://www.okx.com/web3/explorer/xlayer'),\n net(534352, 'Scroll', 'ETH', ['https://rpc.scroll.io', 'https://scroll-rpc.publicnode.com'], 'https://scrollscan.com'),\n net(80094, 'Berachain', 'BERA', ['https://rpc.berachain.com', 'https://berachain-rpc.publicnode.com'], 'https://berascan.com'),\n // Arc (Circle's L1): the gas token is USDC. eth_getBalance / msg.value / gas are accounted in 18-decimal units (the\n // `symbol` here names that native view); the ERC-20 interface at 0x3600…0000 reads the SAME balance in 6 decimals\n // and is what the catalog, LI.FI and CCTP address (see swap2-assets). Balances must show one view, not both.\n net(5042, 'Arc', 'USDC', ['https://rpc.mainnet.arc.io'], 'https://explorer.arc.io'),\n net(5000, 'Mantle', 'MNT', ['https://rpc.mantle.xyz', 'https://mantle-rpc.publicnode.com'], 'https://mantlescan.xyz'),\n net(747474, 'Katana', 'ETH', ['https://rpc.katana.network'], 'https://explorer.katanarpc.com'),\n net(2818, 'Morph', 'ETH', ['https://rpc.morphl2.io', 'https://rpc-quicknode.morphl2.io'], 'https://explorer.morphl2.io'),\n net(14, 'Flare', 'FLR', ['https://flare-api.flare.network/ext/C/rpc', 'https://flare.rpc.thirdweb.com'], 'https://flare-explorer.flare.network'),\n])\n\nexport const chainHex = (caip2: string): string => `0x${Number(caip2.split(':')[1]).toString(16)}`\n\n/** `0x1` / `1` → `eip155:1`; `null` for anything that is not a positive integer chain id. */\nexport function caip2FromChainId(value: unknown): string | null {\n let n: number\n if (typeof value === 'string') {\n const s = value.trim()\n if (/^0x[0-9a-f]+$/i.test(s)) n = Number.parseInt(s, 16)\n else if (/^[0-9]+$/.test(s)) n = Number.parseInt(s, 10)\n else return null\n } else if (typeof value === 'number') n = value\n else return null\n return Number.isSafeInteger(n) && n > 0 ? `eip155:${n}` : null\n}\n\n/** Whether the asset catalog knows this chain — the gate for `wallet_addEthereumChain`. */\nexport function isCatalogChain(caip2: string): boolean {\n return ccChain(caip2) !== undefined\n}\n\n/**\n * Shipped networks plus the ones the user accepted from sites, persisted. Lookup\n * by CAIP-2; a custom entry for a shipped chain is ignored (the build's RPC list\n * wins — a site must not be able to replace Ethereum's endpoints).\n */\nexport class NetworksTable {\n private _custom: EvmNetwork[] | null = null\n private _loading: Promise<EvmNetwork[]> | null = null\n /** add/remove run one after another (scan F22, as PermissionStore). */\n private _queue: Promise<unknown> = Promise.resolve()\n\n constructor(private readonly storage: JsonStorage<EvmNetwork[]>, private readonly defaults: readonly EvmNetwork[] = DEFAULT_NETWORKS) {}\n\n async list(): Promise<EvmNetwork[]> {\n return [...this.defaults, ...(await this.custom())]\n }\n\n async get(caip2: string): Promise<EvmNetwork | null> {\n return this.defaults.find((n) => n.caip2 === caip2) ?? (await this.custom()).find((n) => n.caip2 === caip2) ?? null\n }\n\n add(network: EvmNetwork): Promise<void> {\n return this.serialize(async () => {\n if (this.defaults.some((n) => n.caip2 === network.caip2)) return\n const custom = (await this.custom()).filter((n) => n.caip2 !== network.caip2)\n custom.push(network)\n await this.write(custom)\n })\n }\n\n remove(caip2: string): Promise<void> {\n return this.serialize(async () => {\n const current = await this.custom()\n if (!current.some((n) => n.caip2 === caip2)) return\n await this.write(current.filter((n) => n.caip2 !== caip2))\n })\n }\n\n private serialize<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n /** Cache first (readers see it at once), rolled back when storage refuses. */\n private async write(custom: EvmNetwork[]): Promise<void> {\n const prev = await this.custom()\n this._custom = custom\n try {\n await this.storage.set(custom)\n } catch (e) {\n if (this._custom === custom) this._custom = prev\n throw e\n }\n }\n\n private async custom(): Promise<EvmNetwork[]> {\n if (this._custom) return this._custom\n this._loading ??= this.storage.get().then(\n (s) => (this._custom ??= s ?? []),\n (e: unknown) => { this._loading = null; throw e },\n )\n return this._loading\n }\n}\n\n/**\n * A site must not point the wallet's RPC reads at the user's own network: an RPC URL from a page is\n * kept only when it is https on a public host, with `isPublicHttpsUrl` from `@anywalletkit/networks`\n * (every IPv4 spelling, CGNAT, link-local, mapped IPv6 and `*.local` names included; scan 2026-10-27\n * modules, F37).\n */\nconst isSiteRpcUrl = (u: unknown): u is string => typeof u === 'string' && u.length <= 2048 && isPublicHttpsUrl(u)\n\n/**\n * EIP-3085 `wallet_addEthereumChain` parameter → {@link EvmNetwork}, or the error\n * to answer with. Public https RPC urls only (a private / local host is dropped); the chain id\n * must be in the catalog.\n */\nexport function parseAddChainParams(params: unknown, known: (caip2: string) => boolean = isCatalogChain): EvmNetwork | RelayError {\n const p = (Array.isArray(params) ? params[0] : params) as Record<string, unknown> | undefined\n if (!p || typeof p !== 'object') return relayError(RELAY_ERRORS.invalidParams, 'wallet_addEthereumChain expects one object parameter.')\n const caip2 = caip2FromChainId(p.chainId)\n if (!caip2) return relayError(RELAY_ERRORS.invalidParams, 'chainId must be a 0x-prefixed hex string.')\n if (!known(caip2)) return relayError(RELAY_ERRORS.chainNotAdded, `Chain ${String(p.chainId)} is not in this wallet's catalog.`)\n const rpcs = Array.isArray(p.rpcUrls) ? p.rpcUrls.filter(isSiteRpcUrl) : []\n if (rpcs.length === 0) return relayError(RELAY_ERRORS.invalidParams, 'rpcUrls must contain at least one public https URL (a site cannot add a private / local endpoint).')\n const name = typeof p.chainName === 'string' && p.chainName.trim() ? p.chainName.trim().slice(0, 64) : caip2\n const currency = p.nativeCurrency as { symbol?: unknown; decimals?: unknown } | undefined\n if (currency && currency.decimals !== undefined && currency.decimals !== 18) return relayError(RELAY_ERRORS.invalidParams, 'nativeCurrency.decimals must be 18.')\n const symbol = typeof currency?.symbol === 'string' && /^[A-Za-z0-9]{1,12}$/.test(currency.symbol) ? currency.symbol : 'ETH'\n const explorers = Array.isArray(p.blockExplorerUrls) ? p.blockExplorerUrls.filter((u): u is string => typeof u === 'string' && /^https:\\/\\//i.test(u)) : []\n const network: EvmNetwork = { caip2, chainId: Number(caip2.split(':')[1]), name, symbol, rpcs }\n return explorers[0] ? { ...network, explorer: explorers[0] } : network\n}\n\n// ---- non-EVM chains: the CAIP-2 ids the asset catalog / swap2 engine use, and public endpoints only (Vaulty's lists minus its proxies) ----\n\n/** Solana mainnet as the catalog names it (`solana:mainnet`); the wallet package also accepts the genesis-hash form. */\nexport const SOLANA_CHAIN = 'solana:mainnet'\nexport const SOLANA_RPCS: readonly string[] = Object.freeze(['https://solana-rpc.publicnode.com', 'https://api.mainnet-beta.solana.com'])\nexport const TON_CHAIN = 'ton:-239'\nexport const TON_ENDPOINTS: readonly string[] = Object.freeze(['https://ton.access.orbs.network/1/mainnet/toncenter-api-v2/jsonRPC', 'https://toncenter.com/api/v2/jsonRPC'])\nexport const TRON_CHAIN = 'tron:728126428'\nexport const TRON_PROVIDERS: readonly string[] = Object.freeze(['https://api.trongrid.io'])\nexport const BTC_CHAIN = 'bitcoin:mainnet'\nexport const BTC_ESPLORA: readonly string[] = Object.freeze(['https://mempool.space/api', 'https://blockstream.info/api'])\nexport const NEAR_CHAIN = 'near:mainnet'\nexport const NEAR_PROVIDERS: readonly string[] = Object.freeze(['https://free.rpc.fastnear.com', 'https://rpc.mainnet.near.org'])\n/** Zcash transparent (t1…) accounts over Blockchair's public API, as `@anywalletkit/wallet-zcash` reads and broadcasts them. */\nexport const ZCASH_CHAIN = 'zcash:mainnet'\nexport const ZCASH_BLOCKCHAIR = 'https://api.blockchair.com/zcash'\n\nexport interface ChainDescriptor {\n caip2: string\n key: 'solana' | 'ton' | 'tron' | 'btc' | 'near' | 'zcash'\n name: string\n symbol: string\n decimals: number\n explorerTx: string\n explorerAddress: string\n}\n\nexport const NON_EVM_CHAINS: readonly ChainDescriptor[] = Object.freeze([\n { caip2: SOLANA_CHAIN, key: 'solana', name: 'Solana', symbol: 'SOL', decimals: 9, explorerTx: 'https://solscan.io/tx/', explorerAddress: 'https://solscan.io/account/' },\n { caip2: TON_CHAIN, key: 'ton', name: 'TON', symbol: 'GRAM', decimals: 9, explorerTx: 'https://tonviewer.com/transaction/', explorerAddress: 'https://tonviewer.com/' },\n { caip2: TRON_CHAIN, key: 'tron', name: 'Tron', symbol: 'TRX', decimals: 6, explorerTx: 'https://tronscan.org/#/transaction/', explorerAddress: 'https://tronscan.org/#/address/' },\n { caip2: BTC_CHAIN, key: 'btc', name: 'Bitcoin', symbol: 'BTC', decimals: 8, explorerTx: 'https://mempool.space/tx/', explorerAddress: 'https://mempool.space/address/' },\n { caip2: NEAR_CHAIN, key: 'near', name: 'NEAR', symbol: 'NEAR', decimals: 24, explorerTx: 'https://nearblocks.io/txns/', explorerAddress: 'https://nearblocks.io/address/' },\n { caip2: ZCASH_CHAIN, key: 'zcash', name: 'Zcash', symbol: 'ZEC', decimals: 8, explorerTx: 'https://blockchair.com/zcash/transaction/', explorerAddress: 'https://blockchair.com/zcash/address/' },\n])\n\nexport const nonEvmChain = (caip2: string): ChainDescriptor | undefined => NON_EVM_CHAINS.find((c) => c.caip2 === caip2)\n","import type { StorageAreaLike } from './chrome.js'\n\n/** One JSON value under one key — the shape every small store here needs. */\nexport interface JsonStorage<T> {\n get(): Promise<T | null>\n set(value: T): Promise<void>\n}\n\nexport function chromeJsonStorage<T>(area: StorageAreaLike, key: string): JsonStorage<T> {\n return {\n async get() { return ((await area.get(key))[key] as T | undefined) ?? null },\n async set(value) { await area.set({ [key]: value }) },\n }\n}\n\nexport function memoryJsonStorage<T>(initial: T | null = null): JsonStorage<T> & { value: T | null } {\n const s = {\n value: initial,\n async get() { return s.value === null ? null : structuredClone(s.value) },\n async set(value: T) { s.value = structuredClone(value) },\n }\n return s\n}\n","/**\n * Per-origin permissions: which accounts a site may see and which chain it is\n * on. Nothing here is secret (`chrome.storage.local`, plain JSON); the origin\n * key is the one the browser recorded for the port, never the page's claim.\n */\nimport type { JsonStorage } from './storage.js'\n\nexport interface OriginPermission {\n origin: string\n /** EVM addresses exposed to this origin (checksummed as the keyring stores them). Empty when only another chain is connected. */\n accounts: string[]\n /** CAIP-2 chain the origin currently sees (`eth_chainId`). */\n chain: string\n /** Solana addresses exposed to this origin (Wallet Standard `standard:connect`). */\n solanaAccounts?: string[]\n /** TON addresses exposed to this origin (TON Connect). */\n tonAccounts?: string[]\n /** Tron (TIP-1193), Bitcoin (sats-connect) and NEAR (wallet-selector) addresses. */\n tronAccounts?: string[]\n btcAccounts?: string[]\n nearAccounts?: string[]\n connectedAt: number\n}\n\nexport type PermissionsState = Record<string, OriginPermission>\n\nexport type ChainAccountsKey = 'solanaAccounts' | 'tonAccounts' | 'tronAccounts' | 'btcAccounts' | 'nearAccounts'\nexport const CHAIN_ACCOUNT_KEYS: readonly ChainAccountsKey[] = ['solanaAccounts', 'tonAccounts', 'tronAccounts', 'btcAccounts', 'nearAccounts']\n\nexport class PermissionStore {\n private _state: PermissionsState | null = null\n private _loading: Promise<PermissionsState> | null = null\n /** Every mutation runs here, one after another (scan F22): a read-modify-write never starts from a snapshot another one is about to replace. */\n private _queue: Promise<unknown> = Promise.resolve()\n private readonly _listeners = new Set<(origin: string, permission: OriginPermission | null) => void>()\n\n constructor(private readonly storage: JsonStorage<PermissionsState>) {}\n\n private async state(): Promise<PermissionsState> {\n if (this._state) return this._state\n // One load; a load that resolves after a write must not replace the newer cache.\n this._loading ??= this.storage.get().then(\n (s) => (this._state ??= s ?? {}),\n (e: unknown) => { this._loading = null; throw e },\n )\n return this._loading\n }\n\n /**\n * Run `fn` after every earlier mutation settled. Public mutators wrap their WHOLE read-modify-write\n * in this; `write` itself is unlocked (setAccountsEverywhere calls it in a loop — a lock there too\n * would deadlock). Nothing awaited inside may wait on the user: routers await the approval sheet\n * first and only then call the store.\n */\n private serialize<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n async get(origin: string): Promise<OriginPermission | null> {\n return (await this.state())[origin] ?? null\n }\n\n async list(): Promise<OriginPermission[]> {\n return Object.values(await this.state())\n }\n\n connect(origin: string, accounts: string[], chain: string): Promise<OriginPermission> {\n return this.serialize(async () => {\n if (accounts.length === 0) throw new Error('Connect at least one account.')\n const current = await this.get(origin)\n const permission: OriginPermission = { ...(current ?? {}), origin, accounts: [...accounts], chain, connectedAt: current?.connectedAt ?? Date.now() }\n await this.write(origin, permission)\n return permission\n })\n }\n\n /** Connect another chain's accounts to the same origin (one \"connected sites\" list). */\n connectChain(origin: string, key: ChainAccountsKey, accounts: string[], defaultChain: string): Promise<OriginPermission> {\n return this.serialize(async () => {\n if (accounts.length === 0) throw new Error('Connect at least one account.')\n const current = await this.get(origin)\n const permission: OriginPermission = { origin, accounts: current?.accounts ?? [], chain: current?.chain ?? defaultChain, ...(current ?? {}), [key]: [...accounts], connectedAt: current?.connectedAt ?? Date.now() }\n await this.write(origin, permission)\n return permission\n })\n }\n\n /** Drop one chain's accounts; the origin stays connected while any chain remains. A no-op (no write) when there is nothing to drop. */\n disconnectChain(origin: string, key: 'accounts' | ChainAccountsKey): Promise<void> {\n return this.serialize(async () => {\n const current = await this.get(origin)\n if (!current) return\n if (key === 'accounts' ? current.accounts.length === 0 : current[key] === undefined) return\n const next: OriginPermission = { ...current, [key]: key === 'accounts' ? [] : undefined }\n if (key !== 'accounts') delete next[key]\n const anything = next.accounts.length > 0 || CHAIN_ACCOUNT_KEYS.some((k) => (next[k]?.length ?? 0) > 0)\n await this.write(origin, anything ? next : null)\n })\n }\n\n setChain(origin: string, chain: string): Promise<OriginPermission | null> {\n return this.serialize(async () => {\n const current = await this.get(origin)\n if (!current) return null\n const next = { ...current, chain }\n await this.write(origin, next)\n return next\n })\n }\n\n /**\n * The active EVM account changed: every origin holding an EVM grant now sees `accounts` (MetaMask behaviour).\n * An origin connected only on another chain (`accounts: []` — Solana/TON/Tron/BTC/NEAR providers, a WalletConnect\n * session without eip155) is skipped: it never passed an EVM connect and must not learn the EVM address (scan F6/F8).\n * Lock never writes `[]` here, so the skip cannot strip a real EVM grant.\n */\n setAccountsEverywhere(accounts: string[]): Promise<OriginPermission[]> {\n return this.serialize(async () => {\n const changed: OriginPermission[] = []\n for (const p of await this.list()) {\n if (p.accounts.length === 0 || sameList(p.accounts, accounts)) continue\n const next = { ...p, accounts: [...accounts] }\n await this.write(p.origin, next)\n changed.push(next)\n }\n return changed\n })\n }\n\n disconnect(origin: string): Promise<void> {\n return this.serialize(async () => {\n if (!(await this.get(origin))) return\n await this.write(origin, null)\n })\n }\n\n onChange(listener: (origin: string, permission: OriginPermission | null) => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n /** Unlocked: callers hold the queue. The cache changes before the await (readers see it at once) and is rolled back when storage refuses. */\n private async write(origin: string, permission: OriginPermission | null): Promise<void> {\n const prev = await this.state()\n const state = { ...prev }\n if (permission) state[origin] = permission\n else delete state[origin]\n this._state = state\n try {\n await this.storage.set(state)\n } catch (e) {\n if (this._state === state) this._state = prev\n throw e\n }\n for (const l of this._listeners) l(origin, permission)\n }\n}\n\nconst sameList = (a: string[], b: string[]) => a.length === b.length && a.every((x, i) => x === b[i])\n","/**\n * The approval queue — Vaulty's `txGate` (mobile/lib/txGate.ts) for an\n * extension. A dApp request that needs the user waits here; ONE approval window\n * is open at a time (`chrome.windows.create({ type: 'popup' })`), the next\n * request opens when the current one is answered. The window losing focus\n * changes nothing: the request stays pending. Closing the window, or declining,\n * rejects with {@link ReviewDeclined} — EIP-1193 4001, \"nothing was signed\".\n *\n * The queue lives in the service worker's memory: an open approval window keeps\n * the worker alive, and if the worker is nevertheless restarted the pending\n * promises die with it — the page gets no answer and retries, which is the\n * failure mode MetaMask has too.\n *\n * Two limits keep a page from burying one real request under decoys (SDK-142 M3):\n * at most `maxPendingPerOrigin` requests wait per origin (-32005), and a second\n * `connect` while one is pending is refused outright (-32002).\n *\n * An origin can carry a transport note (`via`, set by the WalletConnect bridge):\n * the sheet then says the request came over WalletConnect, what the dApp claims\n * to be and what WalletConnect Verify says about that claim — the claim itself is\n * never used as the permission key.\n */\nimport { RELAY_ERRORS } from './relay.js'\n\nexport class ReviewDeclined extends Error {\n readonly code = RELAY_ERRORS.userRejected\n constructor(message = 'You declined — nothing was signed.') {\n super(message)\n this.name = 'ReviewDeclined'\n }\n}\n\nexport type ApprovalKind = 'connect' | 'switch-chain' | 'add-chain' | 'sign-message' | 'sign-typed-data' | 'send-transaction' | 'solana-send' | 'swap' | 'earn' | 'chain-send' | 'tron-sign' | 'btc-sign' | 'near-sign' | 'near-signin' | 'wc-session'\n\n/** How a request reached the wallet when it did not come through a content script. */\nexport interface OriginVia {\n transport: 'walletconnect'\n /** What the dApp declared about itself (self-reported, unverified unless `verify` says so). */\n url: string\n name: string\n /** WalletConnect Verify: VALID = the relay saw the request come from `url`'s origin; INVALID = it came from somewhere else; UNKNOWN = not attested. */\n verify: 'VALID' | 'INVALID' | 'UNKNOWN'\n scam?: boolean\n}\n\n/** The queue refused to enqueue (per-origin limits); carries an EIP-1474 code the page understands. */\nexport class QueueLimitError extends Error {\n constructor(readonly code: number, message: string) {\n super(message)\n this.name = 'QueueLimitError'\n }\n}\n\n/** The origin is refused before any window opens (the shipped phishing list); EIP-1193 4100. */\nexport class OriginRefused extends Error {\n readonly code = RELAY_ERRORS.unauthorized\n constructor(message: string) {\n super(message)\n this.name = 'OriginRefused'\n }\n}\n\nexport const APPROVALS_MAX_PENDING_PER_ORIGIN = 3\n\nexport interface ApprovalRequest<P = unknown> {\n id: string\n origin: string\n chain: string\n kind: ApprovalKind\n /** What the window shows; shape per kind, public data only. */\n payload: P\n createdAt: number\n /** Phishing / lookalike / punycode notes about the origin, from the queue's `annotate` hook. */\n originWarnings?: string[]\n /** Set when the origin is a transport pseudo-origin (`wc:<topic>`): what the sheet should say about where this came from. */\n via?: OriginVia\n}\n\nexport interface ApprovalQueueOptions {\n /** Called for every request's origin; the lines are shown on the sheet (e.g. the shipped phishing list's verdict). */\n annotate?: (origin: string) => string[]\n /**\n * Called for every request's origin before anything is queued: a reason refuses the request with\n * {@link OriginRefused} (4100) and no window opens. Wire `PhishingDetector.refusal` here — a\n * warning on the sheet is one click away from a signature.\n */\n refuse?: (origin: string) => string | null | undefined\n /** Requests one origin may have waiting (current + queued). Default {@link APPROVALS_MAX_PENDING_PER_ORIGIN}. */\n maxPendingPerOrigin?: number\n}\n\n/** The window side: open for one request, close when it is answered. `memoryApprovalWindow()` for tests. */\nexport interface ApprovalWindow {\n open(request: ApprovalRequest): Promise<void>\n close(requestId: string): Promise<void>\n /** The user closed the window themself (chrome.windows.onRemoved): the queue declines the request. */\n onClosed(handler: (requestId: string) => void): void\n}\n\ninterface Pending<T = unknown> {\n request: ApprovalRequest\n resolve: (value: T) => void\n reject: (error: Error) => void\n}\n\nexport class ApprovalQueue {\n private _current: Pending | null = null\n private readonly _waiting: Pending[] = []\n private readonly _listeners = new Set<() => void>()\n private readonly _via = new Map<string, OriginVia>()\n\n constructor(private readonly window: ApprovalWindow, private readonly newId: () => string = () => crypto.randomUUID(), private readonly options: ApprovalQueueOptions = {}) {\n window.onClosed((id) => { if (this._current?.request.id === id) this.decline(id) })\n }\n\n /** Enqueue and wait for the user's answer. Refuses (never queues) past the per-origin limits. */\n request<T = unknown>(input: Omit<ApprovalRequest, 'id' | 'createdAt' | 'originWarnings' | 'via'>): Promise<T> {\n let refused: string | null | undefined\n try { refused = this.options.refuse?.(input.origin) } catch (e) { refused = `The wallet could not check this site (${e instanceof Error ? e.message : String(e)}).` }\n if (refused) return Promise.reject(new OriginRefused(refused))\n const sameOrigin = [...(this._current ? [this._current] : []), ...this._waiting].filter((p) => p.request.origin === input.origin)\n if (input.kind === 'connect' && sameOrigin.some((p) => p.request.kind === 'connect')) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.resourceUnavailable, 'A connect request from this site is already waiting for your answer.'))\n }\n const max = this.options.maxPendingPerOrigin ?? APPROVALS_MAX_PENDING_PER_ORIGIN\n if (sameOrigin.length >= max) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.limitExceeded, `This site already has ${max} requests waiting for you; answer or close them first.`))\n }\n return new Promise<T>((resolve, reject) => {\n const warnings = this.options.annotate?.(input.origin) ?? []\n const via = this._via.get(input.origin)\n const pending: Pending = { request: { ...input, id: this.newId(), createdAt: Date.now(), ...(warnings.length ? { originWarnings: warnings } : {}), ...(via ? { via } : {}) }, resolve: resolve as (v: unknown) => void, reject }\n this._waiting.push(pending)\n void this.next()\n })\n }\n\n /** Attach (or clear) the transport note every later request from `origin` carries. */\n setVia(origin: string, via: OriginVia | null): void {\n if (via) this._via.set(origin, via)\n else this._via.delete(origin)\n }\n\n /** The transport note later requests from `origin` carry (WalletConnect Verify's verdict for `wc:<topic>`), if any. */\n viaFor(origin: string): OriginVia | undefined {\n return this._via.get(origin)\n }\n\n /** Requests waiting for `origin` (current + queued). */\n pendingFor(origin: string): number {\n return [...(this._current ? [this._current] : []), ...this._waiting].filter((p) => p.request.origin === origin).length\n }\n\n /** The request currently shown (the window asks for it by id on load). */\n get current(): ApprovalRequest | null {\n return this._current?.request ?? null\n }\n\n get queued(): number {\n return this._waiting.length\n }\n\n resolve(requestId: string, value: unknown): boolean {\n return this.settle(requestId, (p) => p.resolve(value))\n }\n\n decline(requestId: string, error: Error = new ReviewDeclined()): boolean {\n return this.settle(requestId, (p) => p.reject(error))\n }\n\n /** Lock, disconnect, shutdown: everything pending is declined. */\n declineAll(error: Error = new ReviewDeclined('The wallet was locked.')): void {\n const all = [...(this._current ? [this._current] : []), ...this._waiting.splice(0)]\n for (const p of all) p.reject(error)\n if (this._current) void this.window.close(this._current.request.id)\n this._current = null\n this.emit()\n }\n\n onChange(listener: () => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n private settle(requestId: string, fn: (p: Pending) => void): boolean {\n if (this._current?.request.id === requestId) {\n const p = this._current\n this._current = null\n fn(p)\n void this.window.close(requestId).catch(() => undefined)\n this.emit()\n void this.next()\n return true\n }\n const i = this._waiting.findIndex((p) => p.request.id === requestId)\n if (i < 0) return false\n fn(this._waiting.splice(i, 1)[0]!)\n this.emit()\n return true\n }\n\n private async next(): Promise<void> {\n if (this._current || this._waiting.length === 0) return\n const p = this._waiting.shift()!\n this._current = p\n this.emit()\n try {\n await this.window.open(p.request)\n } catch (e) {\n if (this._current === p) {\n this._current = null\n p.reject(e instanceof Error ? e : new Error(String(e)))\n this.emit()\n void this.next()\n }\n }\n }\n\n private emit(): void {\n for (const l of this._listeners) l()\n }\n}\n\n/** In-memory window: tests answer through the queue; `opened` records every request shown. */\nexport function memoryApprovalWindow(): ApprovalWindow & { opened: ApprovalRequest[]; openIds: Set<string>; userClose(id: string): void } {\n let handler: (id: string) => void = () => undefined\n const w = {\n opened: [] as ApprovalRequest[],\n openIds: new Set<string>(),\n async open(request: ApprovalRequest) { w.opened.push(request); w.openIds.add(request.id) },\n async close(id: string) { w.openIds.delete(id) },\n onClosed(h: (id: string) => void) { handler = h },\n userClose(id: string) { w.openIds.delete(id); handler(id) },\n }\n return w\n}\n","/**\n * The request router: what a dApp may ask and what happens to each request.\n * Policy:\n *\n * - the origin is the browser's (checked by the service worker before this runs);\n * - accounts are exposed only to origins the user connected (`eth_requestAccounts`\n * → approval window); `eth_accounts` is `[]` otherwise;\n * - chain switching and adding go through the approval window; a chain can be\n * added only if the asset catalog knows it, with https RPCs;\n * - read-only JSON-RPC is answered from the wallet's own clients (the networks\n * table's failover list), never from a URL the page names;\n * - `eth_sign` (blind hash signing) is never offered; the other signing methods\n * go to the `sign` hook (the review flow) when the wallet provides one;\n * - everything else is refused with 4200.\n *\n * Errors leave as {@link RouterError} (EIP-1193 codes) or {@link ReviewDeclined}\n * (4001); the service worker turns both into a `RelayResponse.error`.\n */\nimport { UserRejectedError } from '@anywalletkit/core'\nimport { ApprovalQueue, ReviewDeclined } from './approvals.js'\nimport { DEFAULT_CHAIN, NetworksTable, caip2FromChainId, chainHex, parseAddChainParams, type EvmNetwork } from './networks.js'\nimport { PermissionStore, type OriginPermission } from './permissions.js'\nimport { RELAY_ERRORS, isRelayMethod, type RelayChain, type RelayError } from './relay.js'\n\nexport class RouterError extends Error {\n readonly code: number\n readonly data: unknown\n constructor(code: number, message: string, data?: unknown) {\n super(message)\n this.name = 'RouterError'\n this.code = code\n this.data = data\n }\n static from(e: RelayError): RouterError {\n return new RouterError(e.code, e.message, e.data)\n }\n}\n\n/** Options for {@link toRelayError}. */\nexport interface RelayErrorOptions {\n /** Gets every error that is NOT passed to the page, in full — the extension's own log. */\n log?: (error: unknown) => void\n}\n\n/** EIP-1193 provider codes a wallet error may carry to the page. */\nconst PROVIDER_CODES: ReadonlySet<number> = new Set([4001, 4100, 4200, 4900, 4901, 4902])\n/** A node's JSON-RPC error: execution reverted (3) or the reserved -32768…-32000 range. */\nconst isNodeCode = (code: unknown): code is number => typeof code === 'number' && Number.isInteger(code) && (code === 3 || (code >= -32768 && code <= -32000))\n/**\n * A URL in an error message. The scheme is bounded, so a long run of scheme characters (a node's\n * or a page's own text) costs a constant per position instead of a scan to the end of the string;\n * there is no `\\b`, so a URL glued to a word is still caught (scan 2026-10-27 modules, F5).\n */\nconst URL_RE = /[a-z][a-z0-9+.-]{0,31}:\\/\\/[^\\s\"'<>()]+/gi\n/** How much of a message is read at all: the page sees 300 characters of its first line. */\nconst PAGE_TEXT_WINDOW = 1024\n/** A message as a page may see it: no URLs (RPC keys live in their paths and queries), one line, bounded — bounded before the regex runs. */\nconst pageText = (text: string): string => text.slice(0, PAGE_TEXT_WINDOW).split('\\n', 1)[0]!.replace(URL_RE, '[url]').slice(0, 300)\nconst isHexData = (v: unknown): v is string => typeof v === 'string' && /^0x[0-9a-fA-F]*$/.test(v) && v.length <= 2 + 2 * 8192\n\n/**\n * The node's own JSON-RPC error inside `e`, if there is one: viem's `RpcRequestError` (alone or\n * under a typed RPC error) carries the node's code, message (`details`) and data, while its\n * `message` adds the URL and the request body; a fetch-based transport may throw the bare\n * `{code, message, data}` object.\n */\nfunction nodeError(e: unknown): RelayError | undefined {\n for (let cur: unknown = e, depth = 0; cur && typeof cur === 'object' && depth < 8; cur = (cur as { cause?: unknown }).cause, depth++) {\n const o = cur as { name?: unknown; code?: unknown; details?: unknown; shortMessage?: unknown; message?: unknown; data?: unknown }\n if (o.name === 'RpcRequestError' && isNodeCode(o.code)) {\n const text = typeof o.details === 'string' && o.details ? o.details : typeof o.shortMessage === 'string' ? o.shortMessage : 'RPC error'\n return { code: o.code, message: pageText(text), ...(isHexData(o.data) ? { data: o.data } : {}) }\n }\n }\n if (!(e instanceof Error) && typeof e === 'object' && e !== null) {\n const o = e as { code?: unknown; message?: unknown; data?: unknown }\n if (isNodeCode(o.code) && typeof o.message === 'string') return { code: o.code, message: pageText(o.message), ...(isHexData(o.data) ? { data: o.data } : {}) }\n }\n return undefined\n}\n\n/**\n * Any error → the `RelayError` for the page. Wallet refusals keep their EIP-1193 code\n * ({@link RouterError}, {@link ReviewDeclined}, a core `UserRejectedError` → 4001), a node's own\n * JSON-RPC error keeps its code and revert data; their messages lose URLs. Everything else is\n * `-32603 Internal error` on the page and goes to `options.log` in full — transport errors name\n * the RPC URL (often with the provider key in it) and the request.\n */\nexport function toRelayError(e: unknown, options: RelayErrorOptions = {}): RelayError {\n if (e instanceof RouterError) return e.data === undefined ? { code: e.code, message: pageText(e.message) } : { code: e.code, message: pageText(e.message), data: e.data }\n if (e instanceof ReviewDeclined) return { code: e.code, message: pageText(e.message) }\n if (e instanceof UserRejectedError) return { code: RELAY_ERRORS.userRejected, message: pageText(e.message) }\n const node = nodeError(e)\n if (node) return node\n const code = (e as { code?: unknown } | null)?.code\n if (e instanceof Error && typeof code === 'number' && PROVIDER_CODES.has(code)) return { code, message: pageText(e.message) }\n options.log?.(e)\n return { code: RELAY_ERRORS.internal, message: 'Internal error' }\n}\n\n/** Read-only methods answered from our RPC without asking the user. */\nexport const READ_METHODS: ReadonlySet<string> = new Set([\n 'eth_blockNumber', 'eth_call', 'eth_estimateGas', 'eth_feeHistory', 'eth_gasPrice', 'eth_getBalance',\n 'eth_getBlockByHash', 'eth_getBlockByNumber', 'eth_getCode', 'eth_getLogs', 'eth_getStorageAt',\n 'eth_getTransactionByHash', 'eth_getTransactionCount', 'eth_getTransactionReceipt', 'eth_maxPriorityFeePerGas',\n])\n\n/** Methods that produce a signature — the review flow's business (step 4), never answered here. */\nexport const SIGNING_METHODS: ReadonlySet<string> = new Set(['personal_sign', 'eth_signTypedData_v4', 'eth_signTypedData_v3', 'eth_signTypedData', 'eth_sendTransaction'])\n\nexport interface ConnectApproval {\n /** Addresses the wallet can expose, active account first (empty while locked — the window unlocks first and reloads). */\n accounts: string[]\n}\nexport interface SwitchChainApproval {\n from: EvmNetwork | null\n to: EvmNetwork\n}\nexport interface AddChainApproval {\n network: EvmNetwork\n}\n\nexport interface RouterDeps {\n permissions: PermissionStore\n networks: NetworksTable\n approvals: ApprovalQueue\n /** EVM addresses the wallet exposes, active account first. Empty when locked or without a wallet. */\n accounts(): Promise<string[]>\n /** Read-only JSON-RPC over the network's own RPC list. */\n rpc(network: EvmNetwork, method: string, params: unknown[]): Promise<unknown>\n /** Push an EIP-1193 event to every page of `origin`. */\n emit(origin: string, event: string, data: unknown): void\n /** The review flow for signing methods. Absent → 4200. */\n sign?(input: { origin: string; network: EvmNetwork; method: string; params: unknown[]; accounts: string[] }): Promise<unknown>\n defaultChain?: string\n /**\n * A reason to refuse every request from `origin` (reads, `eth_accounts`, an earlier permission\n * included) with 4100, or nothing. Wire `PhishingDetector.refusal`.\n */\n refuse?(origin: string): string | null | undefined\n}\n\nexport class RequestRouter {\n constructor(private readonly deps: RouterDeps) {}\n\n /** The chain an origin currently sees (its permission's, else the default). */\n async chainFor(origin: string): Promise<EvmNetwork> {\n const permission = await this.deps.permissions.get(origin)\n const wanted = permission?.chain ?? this.deps.defaultChain ?? DEFAULT_CHAIN\n return (await this.deps.networks.get(wanted)) ?? (await this.deps.networks.get(DEFAULT_CHAIN))!\n }\n\n async handle(origin: string, chain: RelayChain, method: string, rawParams: unknown): Promise<unknown> {\n const refused = this.deps.refuse?.(origin)\n if (refused) throw new RouterError(RELAY_ERRORS.unauthorized, refused)\n // Only a method name is echoed back in the refusals below, never whatever text the page sent.\n if (!isRelayMethod(method)) throw new RouterError(RELAY_ERRORS.invalidRequest, 'The request has no valid method name.')\n if (chain !== 'eip155') throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${chain} providers are not available yet.`)\n const params = Array.isArray(rawParams) ? rawParams : rawParams === undefined ? [] : [rawParams]\n const network = await this.chainFor(origin)\n const permission = await this.deps.permissions.get(origin)\n\n switch (method) {\n case 'eth_chainId':\n return chainHex(network.caip2)\n case 'net_version':\n return String(network.chainId)\n case 'eth_accounts':\n return this.visibleAccounts(permission)\n case 'eth_requestAccounts':\n return this.connect(origin, network)\n case 'wallet_getPermissions':\n // An origin connected only on another chain holds no EVM permission (scan F6/F8).\n return permission && permission.accounts.length > 0 ? [permissionDescriptor(origin, permission.accounts)] : []\n case 'wallet_requestPermissions': {\n const accounts = await this.connect(origin, network)\n return [permissionDescriptor(origin, accounts)]\n }\n case 'wallet_revokePermissions':\n await this.disconnect(origin)\n return null\n case 'wallet_switchEthereumChain': {\n const target = caip2FromChainId((params[0] as { chainId?: unknown } | undefined)?.chainId)\n if (!target) throw new RouterError(RELAY_ERRORS.invalidParams, 'wallet_switchEthereumChain expects [{ chainId }].')\n const to = await this.deps.networks.get(target)\n if (!to) throw new RouterError(RELAY_ERRORS.chainNotAdded, `Chain ${chainHex(target)} is not in this wallet; add it with wallet_addEthereumChain.`)\n await this.switchChain(origin, network, to)\n return null\n }\n case 'wallet_addEthereumChain': {\n const parsed = parseAddChainParams(params)\n if ('code' in parsed) throw RouterError.from(parsed)\n const existing = await this.deps.networks.get(parsed.caip2)\n if (existing) { await this.switchChain(origin, network, existing); return null }\n await this.deps.approvals.request({ origin, chain: network.caip2, kind: 'add-chain', payload: { network: parsed } satisfies AddChainApproval })\n // EIP-3085: the endpoint must answer for the chain it is being added as (a look-alike RPC for a real chain id is the phishing shape).\n let answered: unknown\n try { answered = await this.deps.rpc(parsed, 'eth_chainId', []) } catch (e) { throw new RouterError(RELAY_ERRORS.invalidParams, `The RPC for ${parsed.name} did not answer eth_chainId (${e instanceof Error ? e.message : String(e)}); the network was not added.`) }\n const got = caip2FromChainId(answered)\n if (got !== parsed.caip2) throw new RouterError(RELAY_ERRORS.invalidParams, `The RPC for ${parsed.name} answers chain ${String(answered)}, not ${chainHex(parsed.caip2)}; the network was not added.`)\n await this.deps.networks.add({ ...parsed, custom: { origin, addedAt: Date.now() } })\n if (permission) await this.switchChain(origin, network, parsed, true)\n return null\n }\n case 'eth_sign':\n case 'eth_signTransaction':\n throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${method} (blind signing) is never offered by this wallet.`)\n }\n\n if (READ_METHODS.has(method)) return this.deps.rpc(network, method, params)\n\n if (SIGNING_METHODS.has(method)) {\n if (!this.deps.sign) throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${method} is not available yet.`)\n if (!permission) throw new RouterError(RELAY_ERRORS.unauthorized, 'Connect the wallet first (eth_requestAccounts).')\n return this.deps.sign({ origin, network, method, params, accounts: permission.accounts })\n }\n\n throw new RouterError(RELAY_ERRORS.unsupportedMethod, `This wallet does not support ${method}.`)\n }\n\n /** What a connected origin sees right now: its permitted accounts that the wallet can expose (none while locked). */\n private async visibleAccounts(permission: OriginPermission | null): Promise<string[]> {\n if (!permission) return []\n const available = await this.deps.accounts()\n return permission.accounts.filter((a) => available.includes(a))\n }\n\n /**\n * Connected and unlocked → the accounts; otherwise the approval window (which\n * unlocks first when needed) picks them. Emits `connect` + `accountsChanged`.\n */\n private async connect(origin: string, network: EvmNetwork): Promise<string[]> {\n const existing = await this.visibleAccounts(await this.deps.permissions.get(origin))\n if (existing.length) return existing\n const chosen = await this.deps.approvals.request<unknown>({ origin, chain: network.caip2, kind: 'connect', payload: { accounts: await this.deps.accounts() } satisfies ConnectApproval })\n const available = await this.deps.accounts()\n const accounts = Array.isArray(chosen) ? chosen.filter((a): a is string => typeof a === 'string' && available.includes(a)) : []\n if (accounts.length === 0) throw new ReviewDeclined('No account was selected.')\n await this.deps.permissions.connect(origin, accounts, network.caip2)\n this.deps.emit(origin, 'connect', { chainId: chainHex(network.caip2) })\n this.deps.emit(origin, 'accountsChanged', accounts)\n return accounts\n }\n\n async disconnect(origin: string): Promise<void> {\n if (!(await this.deps.permissions.get(origin))) return\n await this.deps.permissions.disconnect(origin)\n this.deps.emit(origin, 'accountsChanged', [])\n this.deps.emit(origin, 'disconnect', { code: RELAY_ERRORS.disconnected, message: 'The wallet disconnected this site.' })\n }\n\n private async switchChain(origin: string, from: EvmNetwork, to: EvmNetwork, approved = false): Promise<void> {\n if (from.caip2 === to.caip2) return\n const permission = await this.deps.permissions.get(origin)\n if (!permission) throw new RouterError(RELAY_ERRORS.unauthorized, 'Connect the wallet first (eth_requestAccounts).')\n if (!approved) await this.deps.approvals.request({ origin, chain: from.caip2, kind: 'switch-chain', payload: { from, to } satisfies SwitchChainApproval })\n await this.deps.permissions.setChain(origin, to.caip2)\n this.deps.emit(origin, 'chainChanged', chainHex(to.caip2))\n }\n}\n\nconst permissionDescriptor = (origin: string, accounts: string[]) => ({\n id: crypto.randomUUID(),\n parentCapability: 'eth_accounts',\n invoker: origin,\n caveats: [{ type: 'restrictReturnedAccounts', value: [...accounts] }],\n date: Date.now(),\n})\n","/**\n * Sign-In with Ethereum (EIP-4361) messages, parsed so the sheet can say what a\n * `personal_sign` really is and check the fields a phishing site would lie\n * about: the domain (scheme + host) must be the site asking, the address must\n * be the signing account, the chain must be the site's, the message must not be\n * expired or not-yet-valid, and the nonce must look like one (replay).\n *\n * Everything here is a WARNING: the sheet turns problems into warn checks and\n * the user can still sign. Whenever the first line is an EIP-4361 header the\n * text is treated as a sign-in (scan F9) — a message whose remaining fields do\n * not parse is reported as malformed instead of silently becoming a plain\n * message without the cross-site check.\n */\nimport type { OriginVia } from './approvals.js'\n\nexport interface SiweMessage {\n /** As written in the header: `host[:port]`, optionally prefixed by `scheme://`. */\n domain: string\n address: string\n statement?: string\n uri: string\n version: string\n chainId: number\n nonce: string\n issuedAt: string\n expirationTime?: string\n notBefore?: string\n requestId?: string\n resources: string[]\n}\n\nexport interface SiweInfo {\n message: SiweMessage\n /** Human lines, each a reason the sheet should warn; empty = the sign-in is consistent with the request. */\n problems: string[]\n /** The header said \"sign-in\" but the rest did not parse as EIP-4361 (`message` then holds what could be read). */\n malformed?: boolean\n}\n\nexport interface SiweContext {\n /** The page that asked, as the browser recorded it (`https://…`), or a transport pseudo-origin (`wc:<topic>`). */\n origin: string\n /** The signing address. */\n account: string\n /** The site's chain. */\n chainId: number\n now?: number\n /** Transport note for pseudo-origins (WalletConnect): the dApp's claimed URL and what Verify said about it. */\n via?: OriginVia\n}\n\n/** First line of an EIP-4361 message; the \"Ethereum account\" literal is what makes it one. */\nconst HEADER_LINE = /^(?<domain>[^\\n]+?) wants you to sign in with your Ethereum account:(?:\\n|$)/\nconst ADDRESS_LINE = /^0x[0-9a-fA-F]{40}$/\nconst FIELD = /^([A-Za-z ]+): (.*)$/\n\ninterface Parsed { message: SiweMessage; missing: string[] }\n\n/** Tolerant parse: `null` only when the first line is not an EIP-4361 header. */\nfunction parseLoose(text: string): Parsed | null {\n const head = HEADER_LINE.exec(text)\n if (!head?.groups) return null\n const lines = text.slice(head[0].length).split('\\n')\n const missing: string[] = []\n const addressLine = lines.shift() ?? ''\n const address = ADDRESS_LINE.test(addressLine) ? addressLine : ''\n if (!address) missing.push('address')\n // Between the address and the `URI:` line: blank lines and at most one statement line.\n // Covers `addr\\n\\nstatement\\n\\nURI`, `addr\\n\\n\\nURI` (no statement, the ABNF form) and `addr\\n\\nURI` (older libraries).\n const uriAt = lines.findIndex((l) => l.startsWith('URI: '))\n const between = (uriAt < 0 ? lines : lines.slice(0, uriAt)).filter((l) => l !== '')\n let statement: string | undefined\n if (uriAt >= 0) {\n if (between.length === 1 && !FIELD.test(between[0]!)) statement = between[0]\n else if (between.length > 0) missing.push('statement layout')\n }\n const fields: Record<string, string> = {}\n const resources: string[] = []\n for (const line of uriAt < 0 ? [] : lines.slice(uriAt)) {\n if (line.startsWith('- ')) { resources.push(line.slice(2)); continue }\n const m = FIELD.exec(line)\n if (m && !(m[1]! in fields)) fields[m[1]!] = m[2]!\n }\n const chainId = Number(fields['Chain ID'])\n if (!fields.URI) missing.push('URI')\n if (!fields.Version) missing.push('Version')\n if (fields['Chain ID'] === undefined || !Number.isInteger(chainId)) missing.push('Chain ID')\n if (!fields.Nonce) missing.push('Nonce')\n if (!fields['Issued At']) missing.push('Issued At')\n const message: SiweMessage = { domain: head.groups.domain!, address, uri: fields.URI ?? '', version: fields.Version ?? '', chainId: Number.isInteger(chainId) ? chainId : NaN, nonce: fields.Nonce ?? '', issuedAt: fields['Issued At'] ?? '', resources }\n if (statement) message.statement = statement\n if (fields['Expiration Time']) message.expirationTime = fields['Expiration Time']\n if (fields['Not Before']) message.notBefore = fields['Not Before']\n if (fields['Request ID']) message.requestId = fields['Request ID']\n return { message, missing }\n}\n\n/** `null` when the text is not a well-formed EIP-4361 message (see {@link describeSiwe} for the tolerant form the sheet uses). */\nexport function parseSiwe(text: string): SiweMessage | null {\n const p = parseLoose(text)\n return p && p.missing.length === 0 ? p.message : null\n}\n\ninterface Where { scheme: string; host: string }\n\n/** `scheme://host[:port]` or bare `host[:port]` (scheme defaults to https, as EIP-4361 says). */\nfunction whereOf(s: string): Where | null {\n try {\n if (!s.includes('://')) {\n // A URL parser, never fetched — and written as the one dynamic `https://` prefix the extension's host gate knows.\n const host = new URL(`https://${s}`).host.toLowerCase()\n return host ? { scheme: 'https', host } : null\n }\n const u = new URL(s)\n return u.host ? { scheme: u.protocol.replace(/:$/, '').toLowerCase(), host: u.host.toLowerCase() } : null\n } catch { return null }\n}\n\n/** A browser origin with a host the wallet can vouch for: http(s) only — `wc:<topic>` and other pseudo-origins have none. */\nfunction originWhere(origin: string): Where | null {\n try {\n const u = new URL(origin)\n return (u.protocol === 'https:' || u.protocol === 'http:') && u.host ? { scheme: u.protocol.slice(0, -1), host: u.host.toLowerCase() } : null\n } catch { return null }\n}\n\n/** Loopback / `*.localhost` (dev servers): plain http is normal there, so no scheme warnings. Takes `host[:port]`. */\nexport function isLocalHost(host: string): boolean {\n const h = host.toLowerCase().replace(/:\\d+$/, '')\n return h === 'localhost' || h === '127.0.0.1' || h === '[::1]' || h.endsWith('.localhost')\n}\n\n/** The checks; `origin` is the page that asked (as the browser recorded it), `account` the signing address, `chainId` the site's chain. */\nexport function siweProblems(m: SiweMessage, ctx: SiweContext): string[] {\n const out: string[] = []\n const domain = whereOf(m.domain)\n let site = originWhere(ctx.origin)\n if (!site) {\n // No browser-recorded host (WalletConnect `wc:<topic>`): only a Verify-attested claim naming the same host counts (scan F10).\n const claimed = ctx.via?.verify === 'VALID' && !ctx.via.scam ? whereOf(ctx.via.url) : null\n if (claimed && domain && claimed.host === domain.host) site = claimed\n else out.push(`The wallet cannot verify which site is asking; this sign-in for ${m.domain} may be replayed there.`)\n }\n if (site) {\n // Scheme as well as host (scan F20/F21): an http:// twin of the site must not collect sign-ins valid for the https one.\n const local = isLocalHost(site.host)\n if (site.scheme === 'http' && !local) out.push(`This sign-in is requested by an insecure page (${site.scheme}://${site.host}); anyone on the network can read or change it and replay the signature on the https site.`)\n if (!domain || domain.host !== site.host) out.push(`The sign-in names ${m.domain} but the request comes from ${site.host} — a sign-in meant for another site would be replayable there.`)\n else if (!local && domain.scheme !== site.scheme) out.push(`The sign-in is for ${domain.scheme}://${domain.host} but the request comes from ${site.scheme}://${site.host}.`)\n const uri = m.uri ? whereOf(m.uri) : null\n if (uri && uri.host !== site.host) out.push(`The URI ${m.uri} is not on ${site.host}.`)\n else if (uri && !local && (uri.scheme === 'http' || uri.scheme === 'https') && uri.scheme !== site.scheme) out.push(`The URI ${m.uri} uses ${uri.scheme}:// but the request comes from ${site.scheme}://${site.host}.`)\n }\n if (m.address && m.address.toLowerCase() !== ctx.account.toLowerCase()) out.push(`The sign-in is for ${m.address}, not the account that would sign (${ctx.account}).`)\n if (Number.isInteger(m.chainId) && m.chainId !== ctx.chainId) out.push(`The sign-in is for chain ${m.chainId}; this site is on chain ${ctx.chainId}.`)\n if (m.version && m.version !== '1') out.push(`Unknown SIWE version ${m.version}.`)\n if (m.nonce && (m.nonce.length < 8 || !/^[A-Za-z0-9]+$/.test(m.nonce))) out.push('The nonce is too short to protect against replay.')\n const now = ctx.now ?? Date.now()\n const exp = m.expirationTime ? Date.parse(m.expirationTime) : NaN\n if (m.expirationTime && (Number.isNaN(exp) || exp <= now)) out.push('The sign-in has already expired.')\n const nbf = m.notBefore ? Date.parse(m.notBefore) : NaN\n if (m.notBefore && (Number.isNaN(nbf) || nbf > now)) out.push('The sign-in is not valid yet (Not Before is in the future).')\n if (m.issuedAt) {\n const iat = Date.parse(m.issuedAt)\n if (Number.isNaN(iat)) out.push('Issued At is not a date.')\n else if (iat > now + 5 * 60_000) out.push('Issued At is in the future.')\n }\n return out\n}\n\n/** `null` only when the text does not start with an EIP-4361 header; a header with unreadable fields comes back with a \"malformed sign-in message\" problem. */\nexport function describeSiwe(text: string, ctx: SiweContext): SiweInfo | null {\n const p = parseLoose(text)\n if (!p) return null\n const problems = siweProblems(p.message, ctx)\n if (p.missing.length === 0) return { message: p.message, problems }\n return { message: p.message, problems: [`This is a malformed sign-in message (EIP-4361): ${p.missing.join(', ')} missing or unreadable — check the site before signing.`, ...problems], malformed: true }\n}\n","/**\n * Signing requests from dApps (and from the wallet's own Send): classification,\n * transaction preparation, the review stop, the signature.\n *\n * Classification is Vaulty's `signingRequest` (mobile/lib/browser.ts): the\n * address a page names must be one the user connected; typed data bound to\n * another chain than the one the site is on is refused (4901); a transaction\n * must have a `to` (no deployments) and a `chainId`, when given, equal to the\n * site's chain; `eth_sign` never reaches here (the router refuses it).\n *\n * Preparation fills nonce, gas and fees from the wallet's own RPC (never the\n * page's): EIP-1559 cap = 2 × base fee + tip with the tip floored at 0.1 gwei\n * (Vaulty's `evmFees`), legacy `gasPrice` where a chain has no base fee, gas =\n * the page's limit or `eth_estimateGas` × 1.2.\n *\n * The nonce the sheet shows is a guess: the one signed is read AFTER the\n * approval, under a per-account lock that also covers the broadcast, and is\n * never below the wallet's own next nonce (a node may not see the previous\n * send yet). Two requests reviewed at once therefore get consecutive nonces.\n * The fee caps signed are the ones shown, unless the network outgrew them\n * while the sheet was open (EIP-1559: base fee + tip above the shown cap;\n * legacy: a higher gas price) — then the user is asked again with the new\n * numbers (`repriced: true`).\n *\n * The review payload ({@link SignApproval}) carries what the window shows: the\n * classified request, the prepared fields, the fee, and the preview the wallet\n * attached (tx-preview-evm: decode, simulation, balance changes, checks). Only\n * after the user approves does {@link SignDeps.signerFor} open the key; the\n * handle is disposed (zeroized) in `finally`, the raw transaction goes out via\n * `eth_sendRawTransaction` on the wallet's RPC.\n */\nimport { ApprovalQueue, type OriginVia } from './approvals.js'\nimport type { EvmNetwork } from './networks.js'\nimport { RELAY_ERRORS, type RelayError } from './relay.js'\nimport { RouterError, type RouterDeps } from './router.js'\nimport { describeSiwe, type SiweInfo } from './siwe.js'\n\n/** The account nonce an RPC reported, refused when it is not a safe integer (a broken or hostile RPC). */\nconst safeNonce = (n: bigint): number => {\n if (n < 0n || n > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error(`The RPC returned an impossible nonce (${n}).`)\n return Number(n.toString())\n}\n\nexport type SignRequestInfo =\n | { kind: 'sign-message'; method: 'personal_sign'; account: string; /** Decoded text when printable, else the hex. */ text: string; /** What is actually signed (hex or utf-8 string). */ raw: string; /** Parsed Sign-In with Ethereum (EIP-4361) with the checks against the asking origin, when the text is one. */ siwe?: SiweInfo }\n | { kind: 'sign-typed-data'; method: string; account: string; /** Pretty-printed JSON. */ text: string; typedData: TypedData }\n | { kind: 'send-transaction'; method: 'eth_sendTransaction'; account: string; tx: { to: string; value: string; data: string | null; gas: string | null } }\n\nexport interface TypedData {\n domain: Record<string, unknown>\n types: Record<string, Array<{ name: string; type: string }>>\n message: Record<string, unknown>\n primaryType?: string\n}\n\nexport interface PreparedTx {\n chainId: number\n nonce: number\n gasLimit: string\n /** EIP-1559 fields, or `gasPrice` on legacy-fee chains. All 0x hex. */\n maxFeePerGas?: string\n maxPriorityFeePerGas?: string\n gasPrice?: string\n /** gasLimit × max fee, base units. */\n maxFee: string\n}\n\n/** The approval window's payload for the three signing kinds. */\nexport interface SignApproval {\n request: SignRequestInfo\n network: EvmNetwork\n prepared?: PreparedTx\n /** A second sheet for the same transaction: the network's fee outgrew the cap the first one showed. */\n repriced?: true\n /** What the wallet attached (tx-preview-evm `TxPreview`, typed-data description…). */\n preview: unknown\n}\n\nexport interface EvmSigner {\n signMessage(message: string | Uint8Array): Promise<string>\n signTypedData(typed: TypedData): Promise<string>\n /** Fully specified tx (chainId, nonce, gas, fees) → signed raw transaction. */\n signTransaction(tx: { chainId: number; nonce: number; to: string; value: bigint; data: string; gasLimit: bigint; maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint; gasPrice?: bigint }): Promise<string>\n}\n\nexport interface SignDeps {\n approvals: ApprovalQueue\n rpc(network: EvmNetwork, method: string, params: unknown[]): Promise<unknown>\n /** Opens the key for `address`; `dispose()` zeroizes it. */\n signerFor(address: string, network: EvmNetwork): Promise<{ signer: EvmSigner; dispose(): void }>\n /** Review data for the window (errors inside are the wallet's to swallow → `null`). */\n preview?(input: { network: EvmNetwork; request: SignRequestInfo; accounts: string[] }): Promise<unknown>\n /** Tip floor per chain id in wei (default 0.1 gwei everywhere). */\n tipFloor?: (chainId: number) => bigint\n}\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/\nconst HEX = /^0x([0-9a-fA-F]{2})*$/\nconst lc = (s: string) => s.toLowerCase()\n\n/** Vaulty's `messageText`: hex that decodes to printable text is shown decoded; binary payloads stay hex. */\nexport function messageText(value: unknown): string {\n if (typeof value !== 'string') return ''\n if (!HEX.test(value)) return value\n try {\n const bytes = Uint8Array.from(value.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16))\n const s = new TextDecoder('utf-8', { fatal: true }).decode(bytes)\n return /^[\\x09\\x0a\\x0d\\x20-\\x7e -￿]*$/.test(s) ? s : value\n } catch {\n return value\n }\n}\n\n/**\n * The message as the signer will sign it: hex decoded when it is valid UTF-8, whatever\n * its printability (scan 2026-10-23 F7 — the SIWE checks must read the bytes that get\n * signed, not the hex fallback `messageText` shows for unprintable text).\n */\nexport function decodedMessage(value: unknown): string | null {\n if (typeof value !== 'string') return null\n if (!HEX.test(value)) return value\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(Uint8Array.from(value.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16)))\n } catch {\n return null\n }\n}\n\n/** Control characters other than tab / newline / carriage return — never part of an honest EIP-4361 message. */\nconst HIDDEN_CONTROL = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]/\n\nconst err = (code: number, message: string): RelayError => ({ code, message })\n\n/** Signing method + params → what the window reviews, or the error to answer with. */\nexport function classifySignRequest(input: { network: EvmNetwork; method: string; params: unknown[]; accounts: string[]; /** The asking page (browser-recorded) — needed for the SIWE domain check. */ origin?: string; /** Transport note for pseudo-origins (WalletConnect Verify), for the SIWE check. */ via?: OriginVia; now?: number }): SignRequestInfo | RelayError {\n const { method, params } = input\n const owned = new Set(input.accounts.map(lc))\n const ours = (a: unknown): a is string => typeof a === 'string' && ADDRESS.test(a) && owned.has(lc(a))\n const checksum = (a: string) => input.accounts.find((x) => lc(x) === lc(a)) ?? a\n\n if (method === 'personal_sign') {\n // [message, address] per spec; some dApps send [address, message].\n let [msg, addr] = params\n if (ours(msg) && !ours(addr)) [msg, addr] = [addr, msg]\n if (!ours(addr)) return err(RELAY_ERRORS.unauthorized, 'personal_sign for an address this wallet does not hold.')\n if (typeof msg !== 'string') return err(RELAY_ERRORS.invalidParams, 'personal_sign expects a message string.')\n const text = messageText(msg)\n const signed = decodedMessage(msg) ?? text\n const siwe = input.origin ? describeSiwe(signed, { origin: input.origin, account: checksum(addr), chainId: input.network.chainId, ...(input.via ? { via: input.via } : {}), ...(input.now !== undefined ? { now: input.now } : {}) }) : null\n // A sign-in message with hidden control characters would show as an opaque hex blob while\n // a lenient verifier still accepts it: refuse it outright.\n if (siwe && HIDDEN_CONTROL.test(signed)) return err(RELAY_ERRORS.invalidParams, 'This sign-in message contains hidden control characters — refused.')\n return { kind: 'sign-message', method, account: checksum(addr), text, raw: msg, ...(siwe ? { siwe } : {}) }\n }\n\n if (method === 'eth_signTypedData_v4' || method === 'eth_signTypedData_v3' || method === 'eth_signTypedData') {\n const [addr, data] = params\n if (!ours(addr)) return err(RELAY_ERRORS.unauthorized, 'signTypedData for an address this wallet does not hold.')\n let parsed: TypedData\n try {\n parsed = (typeof data === 'string' ? JSON.parse(data) : data) as TypedData\n } catch {\n return err(RELAY_ERRORS.invalidParams, 'Typed data is not valid JSON.')\n }\n if (!parsed || typeof parsed !== 'object' || typeof parsed.domain !== 'object' || typeof parsed.types !== 'object' || typeof parsed.message !== 'object') {\n return err(RELAY_ERRORS.invalidParams, 'Typed data needs domain, types and message.')\n }\n const cid = parsed.domain.chainId\n if (cid !== undefined && cid !== null && Number(cid) !== input.network.chainId) {\n // A domain bound to another chain than the one the site is on is the classic cross-chain replay / phishing shape.\n return err(RELAY_ERRORS.chainDisconnected, `Typed data is for chain ${String(cid)}; this site is on ${input.network.name} (${input.network.chainId}).`)\n }\n return { kind: 'sign-typed-data', method, account: checksum(addr), text: JSON.stringify(parsed, bigintSafe, 2), typedData: parsed }\n }\n\n if (method === 'eth_sendTransaction') {\n const tx = (params[0] ?? {}) as { from?: unknown; to?: unknown; value?: unknown; data?: unknown; gas?: unknown; gasLimit?: unknown; chainId?: unknown; type?: unknown; authorizationList?: unknown }\n if (!ours(tx.from)) return err(RELAY_ERRORS.unauthorized, 'Transaction from an address this wallet does not hold.')\n // EIP-7702: a delegation hands the whole account to a contract; >80 % of early delegations went to sweepers. Sites never get one from this wallet.\n if ((Array.isArray(tx.authorizationList) && tx.authorizationList.length > 0) || tx.type === '0x4' || tx.type === 4) return err(RELAY_ERRORS.unsupportedMethod, 'EIP-7702 delegations (authorizationList / type 4) are never signed for a site by this wallet.')\n if (typeof tx.to !== 'string' || !ADDRESS.test(tx.to)) return err(RELAY_ERRORS.invalidParams, 'Contract deployment is not supported (a transaction needs a valid `to`).')\n if (tx.chainId !== undefined && tx.chainId !== null && Number(tx.chainId) !== input.network.chainId) return err(RELAY_ERRORS.chainDisconnected, 'Transaction chainId differs from the selected chain.')\n let value: string\n try {\n value = BigInt((tx.value as string | number | bigint | undefined) ?? 0).toString()\n } catch {\n return err(RELAY_ERRORS.invalidParams, 'Bad transaction value.')\n }\n const data = typeof tx.data === 'string' && tx.data !== '0x' ? tx.data : null\n if (data !== null && !HEX.test(data)) return err(RELAY_ERRORS.invalidParams, 'Transaction data is not hex.')\n const gasRaw = tx.gas ?? tx.gasLimit\n const gas = typeof gasRaw === 'string' && /^0x[0-9a-fA-F]+$/.test(gasRaw) ? gasRaw : null\n return { kind: 'send-transaction', method, account: checksum(tx.from), tx: { to: tx.to, value, data, gas } }\n }\n\n return err(RELAY_ERRORS.unsupportedMethod, `This wallet does not support ${method}.`)\n}\n\nconst bigintSafe = (_k: string, v: unknown) => (typeof v === 'bigint' ? v.toString() : v)\nconst hex = (n: bigint) => `0x${n.toString(16)}`\nconst big = (v: unknown): bigint => BigInt(v as string)\nconst MIN_TIP_WEI = 100_000_000n // 0.1 gwei\n\ntype Fees = { base: bigint; tip: bigint } | { gasPrice: bigint }\n\n/** The network's fee right now: base fee + floored tip, or the legacy gas price. */\nasync function readFees(deps: Pick<SignDeps, 'rpc' | 'tipFloor'>, network: EvmNetwork, block?: { baseFeePerGas?: string | null } | null): Promise<Fees> {\n const b = block === undefined ? ((await deps.rpc(network, 'eth_getBlockByNumber', ['latest', false])) as { baseFeePerGas?: string | null } | null) : block\n const base = b?.baseFeePerGas != null ? big(b.baseFeePerGas) : null\n if (base === null) return { gasPrice: big(await deps.rpc(network, 'eth_gasPrice', [])) }\n const floor = deps.tipFloor?.(network.chainId) ?? MIN_TIP_WEI\n const nodeTip = await (deps.rpc(network, 'eth_maxPriorityFeePerGas', []) as Promise<string>).then(big).catch(() => 0n)\n return { base, tip: nodeTip > floor ? nodeTip : floor }\n}\n\nfunction withFees(chainId: number, nonce: number, gasLimit: bigint, fees: Fees): PreparedTx {\n if ('gasPrice' in fees) return { chainId, nonce, gasLimit: hex(gasLimit), gasPrice: hex(fees.gasPrice), maxFee: (gasLimit * fees.gasPrice).toString() }\n const maxFeePerGas = fees.base * 2n + fees.tip\n return { chainId, nonce, gasLimit: hex(gasLimit), maxFeePerGas: hex(maxFeePerGas), maxPriorityFeePerGas: hex(fees.tip), maxFee: (gasLimit * maxFeePerGas).toString() }\n}\n\n/** True when `shown` can no longer pay for inclusion at `now` (the user must see the new numbers). */\nfunction outgrown(shown: PreparedTx, now: Fees): boolean {\n if ('gasPrice' in now) return shown.gasPrice === undefined || now.gasPrice > big(shown.gasPrice)\n return shown.maxFeePerGas === undefined || now.base + now.tip > big(shown.maxFeePerGas)\n}\n\n/**\n * A cap more than this many times what the network asks now is lowered to the current fees at\n * signing. Signers hold a caller-set fee rate against the network's quote and refuse one far above\n * it, so a cap shown during a spike that has since passed would be refused after the user said yes.\n */\nconst STALE_FEE_FACTOR = 4n\n\n/** True when `shown` sits far above `fresh` (a fee spike passed while the sheet was open). */\nfunction overpriced(shown: PreparedTx, fresh: PreparedTx): boolean {\n if (shown.gasPrice !== undefined && fresh.gasPrice !== undefined) return big(shown.gasPrice) > STALE_FEE_FACTOR * big(fresh.gasPrice)\n if (shown.maxFeePerGas !== undefined && fresh.maxFeePerGas !== undefined) return big(shown.maxFeePerGas) > STALE_FEE_FACTOR * big(fresh.maxFeePerGas)\n return false\n}\n\n/** Nonce, gas, fees from the wallet's RPC. */\nexport async function prepareTransaction(deps: Pick<SignDeps, 'rpc' | 'tipFloor'>, network: EvmNetwork, from: string, tx: { to: string; value: string; data: string | null; gas: string | null }): Promise<PreparedTx> {\n const call = { from, to: tx.to, value: hex(BigInt(tx.value)), ...(tx.data ? { data: tx.data } : {}) }\n const [nonceHex, block, gasHex] = await Promise.all([\n deps.rpc(network, 'eth_getTransactionCount', [from, 'pending']),\n deps.rpc(network, 'eth_getBlockByNumber', ['latest', false]) as Promise<{ baseFeePerGas?: string | null } | null>,\n tx.gas ? Promise.resolve(tx.gas) : deps.rpc(network, 'eth_estimateGas', [call]),\n ])\n const estimated = big(gasHex)\n const gasLimit = tx.gas ? estimated : (estimated * 120n + 99n) / 100n\n return withFees(network.chainId, safeNonce(big(nonceHex)), gasLimit, await readFees(deps, network, block))\n}\n\n/** The router's `sign` hook: classify → prepare → review → sign (→ broadcast). */\nexport function createSignHandler(deps: SignDeps): NonNullable<RouterDeps['sign']> {\n // Per chain + account: the tail of the sign-and-broadcast queue and the next nonce this worker\n // handed out. Memory only — a restarted service worker starts again from the node's count.\n const tails = new Map<string, Promise<unknown>>()\n const nextNonce = new Map<string, number>()\n const serial = <T>(key: string, fn: () => Promise<T>): Promise<T> => {\n const run = (tails.get(key) ?? Promise.resolve()).then(fn, fn)\n const tail = run.then(() => undefined, () => undefined)\n tails.set(key, tail)\n void tail.then(() => { if (tails.get(key) === tail) tails.delete(key) })\n return run\n }\n\n return async ({ origin, network, method, params, accounts }) => {\n const via = deps.approvals.viaFor(origin)\n const info = classifySignRequest({ network, method, params, accounts, origin, ...(via ? { via } : {}) })\n if ('code' in info) throw RouterError.from(info)\n\n const prepared = info.kind === 'send-transaction' ? await prepareTransaction(deps, network, info.account, info.tx) : undefined\n const preview = deps.preview ? await deps.preview({ network, request: info, accounts }).catch(() => null) : null\n const payload: SignApproval = { request: info, network, ...(prepared ? { prepared } : {}), preview }\n await deps.approvals.request({ origin, chain: network.caip2, kind: info.kind, payload })\n\n if (info.kind === 'send-transaction') {\n const key = `${network.caip2}|${lc(info.account)}`\n return serial(key, async () => {\n let shown = prepared!\n for (;;) {\n const [nonceHex, fees] = await Promise.all([deps.rpc(network, 'eth_getTransactionCount', [info.account, 'pending']), readFees(deps, network)])\n const local = nextNonce.get(key) ?? 0\n const nodeNonce = safeNonce(big(nonceHex))\n const nonce = nodeNonce > local ? nodeNonce : local\n if (outgrown(shown, fees)) {\n shown = withFees(network.chainId, nonce, big(shown.gasLimit), fees)\n await deps.approvals.request({ origin, chain: network.caip2, kind: info.kind, payload: { ...payload, prepared: shown, repriced: true } })\n continue // the network may have moved again while the second sheet was open\n }\n // A lower cap than the one approved needs no second sheet: the user pays at most what they saw.\n const fresh = withFees(network.chainId, nonce, big(shown.gasLimit), fees)\n if (overpriced(shown, fresh)) shown = fresh\n const handle = await deps.signerFor(info.account, network)\n let raw: string\n try {\n raw = await handle.signer.signTransaction({\n chainId: shown.chainId, nonce, to: info.tx.to, value: BigInt(info.tx.value), data: info.tx.data ?? '0x', gasLimit: BigInt(shown.gasLimit),\n ...(shown.gasPrice !== undefined ? { gasPrice: BigInt(shown.gasPrice) } : { maxFeePerGas: BigInt(shown.maxFeePerGas!), maxPriorityFeePerGas: BigInt(shown.maxPriorityFeePerGas!) }),\n })\n } finally {\n handle.dispose()\n }\n const hash = await deps.rpc(network, 'eth_sendRawTransaction', [raw])\n nextNonce.set(key, nonce + 1)\n return hash\n }\n })\n }\n\n const handle = await deps.signerFor(info.account, network)\n try {\n switch (info.kind) {\n case 'sign-message':\n return await handle.signer.signMessage(HEX.test(info.raw) ? Uint8Array.from(info.raw.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16)) : info.raw)\n case 'sign-typed-data':\n return await handle.signer.signTypedData(info.typedData)\n }\n } finally {\n handle.dispose()\n }\n }\n}\n","/**\n * Pre-approvals — the second half of Vaulty's `txGate` (mobile/lib/txGate.ts).\n * A flow that reviewed a WHOLE plan in one sheet (a swap: approvals + source\n * leg) registers one matcher per operation it is about to perform; the\n * reviewed account then lets exactly those operations through without a second\n * window, each once, within `ttlMs`, and only for the account that reviewed the\n * plan. Anything else still stops at the review.\n */\nexport type GatedOp = (\n | { kind: 'evm-tx'; caip2: string; to: string; data?: string; value: bigint }\n /** EIP-712 data about to be signed: `typedDataHash` is `typedDataHash(typed)` from `@anywalletkit/wallet-evm` — the digest the account signs. */\n | { kind: 'evm-typed-data'; caip2: string; typedDataHash: string }\n | { kind: 'solana-transfer'; to: string; amount: bigint; token?: string }\n | { kind: 'solana-tx'; to: string; value: bigint }\n | { kind: 'solana-serialized'; serializedTx: string }\n /** A module-built Solana transaction message (instructions), reviewed as a plan. */\n | { kind: 'solana-message' }\n /** TON / Tron / Bitcoin / NEAR send or token transfer (amount in base units; token = jetton master / TRC-20 / NEP-141 id). */\n | { kind: 'chain-tx'; chain: string; to: string; amount: bigint; token?: string | undefined; memo?: string | undefined }\n) & {\n /** The account about to sign or send. A pre-approval bound to an account passes only ops that name it. */\n account?: string | undefined\n}\n\nexport type GateMatcher = (op: GatedOp) => boolean\n\nconst HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/\n/** Same account: EVM addresses in any case, anything else exactly. */\nconst sameAccount = (a: string, b: string): boolean => a === b || (HEX_ADDRESS.test(a) && a.toLowerCase() === b.toLowerCase())\n\nexport class ReviewGate {\n private approved: { match: GateMatcher; until: number; account?: string }[] = []\n\n constructor(private readonly now: () => number = Date.now) {}\n\n /**\n * Each matcher passes ONE operation, within `ttlMs` (default 10 min). With `account`, only an op\n * whose `account` is that account (an op without one does not pass). `reviewSwapPlan` and\n * `reviewEarnPlan` always bind.\n */\n preApprove(matchers: GateMatcher[], ttlMs = 10 * 60_000, account?: string): void {\n const until = this.now() + ttlMs\n this.approved.push(...matchers.map((match) => ({ match, until, ...(account ? { account } : {}) })))\n }\n\n /** True (and the matcher is spent) when a pre-approval covers `op`. */\n consume(op: GatedOp): boolean {\n const now = this.now()\n this.approved = this.approved.filter((a) => a.until > now)\n const i = this.approved.findIndex((a) => (a.account === undefined || (op.account !== undefined && sameAccount(a.account, op.account))) && a.match(op))\n if (i < 0) return false\n this.approved.splice(i, 1)\n return true\n }\n\n get pending(): number {\n return this.approved.length\n }\n\n clear(): void {\n this.approved = []\n }\n}\n\nconst lc = (s: string) => s.toLowerCase()\n\n/** Matcher for an exact EVM call: same chain, `to`, calldata and value. */\nexport function evmCallMatcher(expected: { caip2: string; to: string; data?: string | undefined; value: bigint }): GateMatcher {\n const data = expected.data && expected.data !== '0x' ? lc(expected.data) : undefined\n return (op) =>\n op.kind === 'evm-tx' &&\n op.caip2 === expected.caip2 &&\n lc(op.to) === lc(expected.to) &&\n (op.data && op.data !== '0x' ? lc(op.data) : undefined) === data &&\n op.value === expected.value\n}\n\n/** Matcher for one EIP-712 payload on one chain, by the digest the account signs (`typedDataHash` from `@anywalletkit/wallet-evm`). */\nexport function typedDataMatcher(expected: { caip2: string; typedDataHash: string }): GateMatcher {\n const hash = lc(expected.typedDataHash)\n return (op) => op.kind === 'evm-typed-data' && op.caip2 === expected.caip2 && lc(op.typedDataHash) === hash\n}\n\n/** Matcher for a non-EVM send: same chain, recipient, amount, token and memo. */\nexport function chainTxMatcher(expected: { chain: string; to: string; amount: bigint; token?: string | undefined; memo?: string | undefined }): GateMatcher {\n return (op) => op.kind === 'chain-tx' && op.chain === expected.chain && op.to === expected.to && op.amount === expected.amount && (op.token ?? '') === (expected.token ?? '') && (op.memo ?? '') === (expected.memo ?? '')\n}\n","/**\n * Swaps for the extension, the DIRECT path of Vaulty mobile's `lib/swap2.ts`:\n * the providers run in the service worker and talk to their APIs themselves.\n *\n * - {@link quoteRoutes}: dry quotes from every provider that can serve the\n * pair, delivered progressively (`onUpdate` fires as each venue answers), with\n * BEST / FASTEST tags and every refusal named.\n * TODO: replace with `CrossChainRouter.getQuotes` (net-USD ranking,\n * RouteSet). Until then this fan-out over the public `CrossChainProvider`\n * interface ranks by output amount.\n * - {@link reviewSwapPlan}: the engine's `reviewExecution` hook — one sheet for\n * the whole plan (approvals + source leg) BEFORE anything is signed; on\n * approval exactly those operations are pre-approved in the {@link ReviewGate}\n * so the reviewed account lets them through once; a decline aborts with\n * nothing sent (`ReviewDeclined`, 4001).\n */\nimport type { CrossChainProvider, Quote, QuoteParams, Swap2ExecutionPlan } from '@anywalletkit/protocol-swap2-core'\nimport { validQuote } from '@anywalletkit/protocol-swap2-core'\nimport { typedDataHash } from '@anywalletkit/wallet-evm'\nimport { ApprovalQueue } from './approvals.js'\nimport { ReviewGate, chainTxMatcher, evmCallMatcher, typedDataMatcher, type GateMatcher } from './gate.js'\nimport type { TypedData } from './signing.js'\n\nexport interface RouteView {\n provider: string\n destAmount: string\n minDestAmount: string\n feeUsd: number\n /** On-chain pool venues take the fee inside the output; \"$0.00\" would mislead. */\n feeNote?: string\n etaSeconds: number\n validUntilMs: number\n tags: ('best' | 'fastest')[]\n}\n\nexport interface RouteListView {\n routes: RouteView[]\n /** Providers still quoting. */\n pending: string[]\n /** Provider → why it sat out (refusal, error, timeout). */\n refusals: Record<string, string>\n /** The quotes themselves, by provider, for execution with the same numbers the user saw. */\n quotes: Record<string, Quote>\n}\n\nexport interface QuoteRoutesOptions {\n onUpdate?: (view: RouteListView) => void\n /** Per-provider wall clock (default 20 s). */\n timeoutMs?: number\n signal?: AbortSignal\n now?: () => number\n}\n\n/** Dry quotes from every enabled provider that claims the route, progressively. */\nexport async function quoteRoutes(providers: readonly CrossChainProvider[], params: QuoteParams, options: QuoteRoutesOptions = {}): Promise<RouteListView> {\n const timeoutMs = options.timeoutMs ?? 20_000\n const from = { chain: params.sourceChain, token: params.sourceToken }\n const to = { chain: params.destChain, token: params.destToken }\n const refusals: Record<string, string> = {}\n const quotes: Record<string, Quote> = {}\n const candidates: CrossChainProvider[] = []\n for (const p of providers) {\n let enabled = false\n try { enabled = p.enabled() } catch { /* fail closed */ }\n if (!enabled) continue\n if (params.sourceChain === params.destChain && !p.supportsSameChain) { refusals[p.name] = 'does not do same-chain swaps'; continue }\n let serves = false\n try { serves = p.supportsRoute(from, to) } catch (e) { refusals[p.name] = e instanceof Error ? e.message : String(e); continue }\n if (!serves) { refusals[p.name] = 'does not serve this pair'; continue }\n candidates.push(p)\n }\n const pending = new Set(candidates.map((p) => p.name))\n const view = (): RouteListView => ({ routes: rank(Object.values(quotes)), pending: [...pending], refusals: { ...refusals }, quotes: { ...quotes } })\n const emit = () => options.onUpdate?.(view())\n emit()\n await Promise.all(\n candidates.map(async (p) => {\n const ctrl = new AbortController()\n const timer = setTimeout(() => ctrl.abort(new Error(`no answer within ${Math.round(timeoutMs / 1000)} s`)), timeoutMs)\n const onAbort = () => ctrl.abort(options.signal?.reason)\n options.signal?.addEventListener('abort', onAbort, { once: true })\n let refusal: string | undefined\n try {\n // Race the signal too: a provider that ignores it must not hold the list open forever.\n const aborted = new Promise<never>((_, reject) => ctrl.signal.addEventListener('abort', () => reject(ctrl.signal.reason instanceof Error ? ctrl.signal.reason : new Error(String(ctrl.signal.reason ?? 'cancelled'))), { once: true }))\n const q = await Promise.race([p.getQuote({ ...params, dry: true, onRefusal: (r) => { refusal = r } }, ctrl.signal), aborted])\n if (q && validQuote(q, { ...params, dry: true }, p.name)) quotes[p.name] = q\n else refusals[p.name] = refusal ?? (q ? 'returned an invalid quote' : 'no route for this pair right now')\n } catch (e) {\n refusals[p.name] = ctrl.signal.aborted ? String(ctrl.signal.reason instanceof Error ? ctrl.signal.reason.message : ctrl.signal.reason ?? 'cancelled') : e instanceof Error ? e.message : String(e)\n } finally {\n clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n pending.delete(p.name)\n emit()\n }\n }),\n )\n return view()\n}\n\n/** Highest output first (same destination token for every quote); FASTEST = lowest ETA among them. */\nexport function rank(quotes: Quote[]): RouteView[] {\n const sorted = [...quotes].sort((a, b) => (BigInt(b.destAmount) > BigInt(a.destAmount) ? 1 : BigInt(b.destAmount) < BigInt(a.destAmount) ? -1 : a.feeUsd - b.feeUsd || a.etaSeconds - b.etaSeconds))\n const fastest = sorted.length ? sorted.reduce((f, q) => (q.etaSeconds < f.etaSeconds ? q : f)) : null\n return sorted.map((q, i) => {\n const poolFee = q.providerData?.poolFee\n const feeNote = typeof poolFee === 'string' && poolFee && q.feeUsd === 0 ? (poolFee === 'pools' ? 'pool fees in price' : `pool ${poolFee} in price`) : undefined\n const tags: RouteView['tags'] = []\n if (i === 0) tags.push('best')\n if (fastest && q.provider === fastest.provider) tags.push('fastest')\n return { provider: q.provider, destAmount: q.destAmount, minDestAmount: q.minDestAmount, feeUsd: q.feeUsd, etaSeconds: q.etaSeconds, validUntilMs: q.validUntilMs, tags, ...(feeNote ? { feeNote } : {}) }\n })\n}\n\n/** Vaulty's execution floor: 50 bps under the quoted minimum rides normal drift while the user reviews, still refuses a real reprice. */\nexport const FLOOR_TOLERANCE_BPS = 50n\nexport function executionFloor(minDestAmount: bigint): bigint {\n const floor = (minDestAmount * (10_000n - FLOOR_TOLERANCE_BPS)) / 10_000n\n return floor > 0n ? floor : minDestAmount\n}\n\n// ---- the review stop ----\n\nexport interface SwapReviewMeta {\n /** Who runs the flow (the wallet's origin). */\n origin: string\n /** The account that signs the plan: the gate passes the plan's operations for this account only. */\n account: string\n providerLabel: string\n fromSymbol: string\n fromDecimals: number\n toSymbol: string\n toDecimals: number\n fromChainName: string\n toChainName: string\n /** All of the user's addresses — recipient own/foreign. */\n own: string[]\n}\n\n/** What the swap sheet renders. Amounts are base-unit strings. */\nexport interface SwapApproval {\n provider: string\n providerLabel: string\n fromChain: string\n toChain: string\n fromChainName: string\n toChainName: string\n send: { symbol: string; decimals: number; amount: string }\n receive: { symbol: string; decimals: number; amount: string; min: string }\n recipient: { address: string; isOwn: boolean }\n refundAddress: string\n feeUsd: number\n etaSeconds: number\n validUntilMs: number\n approvals: { token: string; spender: string; amount: string }[]\n source:\n | { kind: 'call'; to: string; data?: string; value: string; deposit?: string }\n | { kind: 'token-transfer'; token: string; recipient: string; amount: string; memo?: string }\n | { kind: 'serialized' }\n /** The EIP-712 order the account signs (gasless routes): `typedData` to render, `text` pretty JSON. */\n | { kind: 'typed-order'; typedData: TypedData; text: string }\n checks: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n}\n\nconst APPROVE_SELECTOR = '0x095ea7b3'\nconst TRANSFER_SELECTOR = '0xa9059cbb'\nconst pad = (hexNoPrefix: string) => hexNoPrefix.toLowerCase().padStart(64, '0')\nexport const encodeApproveCalldata = (spender: string, amount: bigint): string => `${APPROVE_SELECTOR}${pad(spender.slice(2))}${pad(amount.toString(16))}`\nconst lc = (s: string) => s.toLowerCase()\n\n/** A plain native send or ERC-20 transfer pays a provider deposit address (1Click-style). */\nfunction depositOf(s: { to: string; data?: string }, approvals: number): string | undefined {\n if (approvals > 0) return undefined\n if (!s.data || s.data === '0x') return s.to\n if (!s.data.startsWith(TRANSFER_SELECTOR) || s.data.length < 10 + 64) return undefined\n return `0x${s.data.slice(10 + 24, 10 + 64)}`\n}\n\nexport function swapApprovalPayload(plan: Swap2ExecutionPlan, meta: SwapReviewMeta): SwapApproval {\n const isOwn = meta.own.some((a) => lc(a) === lc(plan.recipient))\n const checks: SwapApproval['checks'] = [{ status: 'ok', label: `Built by the ${meta.providerLabel} module` }]\n const s = plan.source\n let source: SwapApproval['source']\n if (s.kind === 'call') {\n const deposit = depositOf(s, plan.approvals.length)\n source = { kind: 'call', to: s.to, ...(s.data ? { data: s.data } : {}), value: s.value.toString(), ...(deposit ? { deposit } : {}) }\n checks.push(deposit ? { status: 'ok', label: `Deposit address from the ${meta.providerLabel} quote` } : { status: 'ok', label: `Calls the ${meta.providerLabel} contract` })\n } else if (s.kind === 'token-transfer') {\n source = { kind: 'token-transfer', token: s.token, recipient: s.recipient, amount: s.amount.toString(), ...(s.memo ? { memo: s.memo } : {}) }\n checks.push({ status: 'ok', label: `Deposit address from the ${meta.providerLabel} quote` })\n } else if (s.kind === 'serialized') {\n source = { kind: 'serialized' }\n checks.push({ status: 'ok', label: 'Balance changes are proven before signing (SDK guard)' })\n } else {\n const typedData = parseTypedOrder(s.typedData)\n source = { kind: 'typed-order', typedData, text: JSON.stringify(typedData, null, 2) }\n checks.push({ status: 'ok', label: 'Signed order — no transaction is sent from your wallet' })\n }\n for (const a of plan.approvals) checks.push(a.amount > plan.sourceAmount ? { status: 'warn', label: 'Approval is larger than this swap needs' } : { status: 'ok', label: 'Approval is exactly the amount needed' })\n if (plan.approvals.length > 1) checks.push({ status: 'ok', label: `${plan.approvals.length} approvals (reset to 0 first)` })\n checks.push(isOwn ? { status: 'ok', label: 'Funds arrive at your address' } : { status: 'warn', label: `Funds arrive at ${plan.recipient.slice(0, 6)}…${plan.recipient.slice(-4)}, not your address` })\n return {\n provider: plan.provider, providerLabel: meta.providerLabel, fromChain: plan.fromChain, toChain: plan.destChain, fromChainName: meta.fromChainName, toChainName: meta.toChainName,\n send: { symbol: meta.fromSymbol, decimals: meta.fromDecimals, amount: plan.sourceAmount.toString() },\n receive: { symbol: meta.toSymbol, decimals: meta.toDecimals, amount: plan.destAmount.toString(), min: plan.minDestAmount.toString() },\n recipient: { address: plan.recipient, isOwn }, refundAddress: plan.refundAddress, feeUsd: plan.feeUsd, etaSeconds: plan.etaSeconds, validUntilMs: plan.validUntilMs,\n approvals: plan.approvals.map((a) => ({ token: a.token, spender: a.spender, amount: a.amount.toString() })),\n source, checks,\n }\n}\n\nfunction parseTypedOrder(json: string): TypedData {\n const t = JSON.parse(json) as TypedData\n if (!t || typeof t !== 'object' || !t.domain || typeof t.domain !== 'object' || !t.types || typeof t.types !== 'object' || !t.message || typeof t.message !== 'object') throw new Error('The swap order is not EIP-712 typed data.')\n return t\n}\n\n/** Matchers for exactly the operations the plan will perform, in the engine's order. */\nexport function planMatchers(plan: Swap2ExecutionPlan): GateMatcher[] {\n const m: GateMatcher[] = plan.approvals.map((a) => evmCallMatcher({ caip2: plan.fromChain, to: a.token, data: encodeApproveCalldata(a.spender, a.amount), value: 0n }))\n const s = plan.source\n if (s.kind === 'call') {\n if (plan.fromChain.startsWith('eip155:')) m.push(evmCallMatcher({ caip2: plan.fromChain, to: s.to, data: s.data, value: s.value }))\n else if (plan.fromChain.startsWith('solana:')) m.push((op) => op.kind === 'solana-tx' && op.to === s.to && op.value === s.value)\n else m.push(chainTxMatcher({ chain: plan.fromChain, to: s.to, amount: s.value, memo: s.memo }))\n } else if (s.kind === 'token-transfer') {\n if (plan.fromChain.startsWith('eip155:')) m.push(evmCallMatcher({ caip2: plan.fromChain, to: s.token, data: `${TRANSFER_SELECTOR}${pad(s.recipient.slice(2))}${pad(s.amount.toString(16))}`, value: 0n }))\n else if (plan.fromChain.startsWith('solana:')) m.push((op) => op.kind === 'solana-transfer' && op.to === s.recipient && op.amount === s.amount && (op.token ?? '') === s.token)\n else m.push(chainTxMatcher({ chain: plan.fromChain, to: s.recipient, amount: s.amount, token: s.token, memo: s.memo }))\n } else if (s.kind === 'serialized') {\n m.push((op) => op.kind === 'solana-serialized' && op.serializedTx === s.serializedTx)\n } else {\n // The order itself, by the EIP-712 digest the account will sign (the engine's domain / type clean-up does not change it).\n m.push(typedDataMatcher({ caip2: plan.fromChain, typedDataHash: typedDataHash(parseTypedOrder(s.typedData) as Parameters<typeof typedDataHash>[0]) }))\n }\n return m\n}\n\n/** The engine's `reviewExecution`: one sheet for the plan; approve → pre-approve exactly its operations; decline → nothing sent. */\nexport function reviewSwapPlan(approvals: ApprovalQueue, gate: ReviewGate, meta: SwapReviewMeta): (plan: Swap2ExecutionPlan) => Promise<void> {\n if (typeof meta.account !== 'string' || !meta.account) throw new TypeError('reviewSwapPlan needs meta.account: the gate passes the plan for that account only.')\n return async (plan) => {\n const matchers = planMatchers(plan) // a plan that cannot be matched is refused before the sheet\n const payload = swapApprovalPayload(plan, meta)\n await approvals.request({ origin: meta.origin, chain: plan.fromChain, kind: 'swap', payload })\n gate.clear()\n gate.preApprove(matchers, Math.max(60_000, plan.validUntilMs - Date.now() + 5 * 60_000), meta.account)\n }\n}\n","/**\n * Pending swaps across service-worker restarts: records in `chrome.storage.local`,\n * a `chrome.alarms` tick every minute while anything is active, resumable by\n * the swap2 id (`awk1.<provider>.<intent>[.<sourceTxHash>]`), the provider's\n * `trackIntent` as the only source of truth.\n *\n * States (the provider's `IntentState` plus the wallet's own `claiming`):\n * pending ──deposit seen──▶ pending (depositReceived)\n * pending ──attested (CCTP)──▶ action-required ──user claims──▶ claiming ──mint seen──▶ completed\n * pending ──▶ completed | failed | refunded | refund-pending | partial | cancelled | expired\n * A tracker error leaves the record as it was (with `lastError`); a record older\n * than `giveUpAfterMs` with no progress becomes `expired` so the alarm stops.\n */\nimport { SWAP2_ID_PREFIX, type IntentStatus } from '@anywalletkit/protocol-swap2-core'\nimport type { JsonStorage } from './storage.js'\n\nexport type SwapRecordStatus = IntentStatus['state'] | 'claiming'\n\nexport interface SwapRecord {\n /** swap2 id — `awk1.<provider>.<intentId>[.<sourceTxHash>[.<claimTxHash>]]`. */\n id: string\n provider: string\n fromChain: string\n toChain: string\n fromToken: string\n toToken: string\n /** Base units. */\n amountIn: string\n destAmount: string\n recipient: string\n sourceTxHash: string | null\n destTxHash: string | null\n status: SwapRecordStatus\n depositReceived?: boolean\n /** Two-phase routes: where and whether the claim can be built now. */\n claim?: { chain: string; ready: boolean }\n createdAt: number\n updatedAt: number\n /** Last tracker problem (RPC/API), kept until the next successful check. */\n lastError?: string\n checks: number\n}\n\nexport const ACTIVE_STATUSES: ReadonlySet<SwapRecordStatus> = new Set<SwapRecordStatus>(['pending', 'action-required', 'refund-pending', 'partial', 'claiming'])\n\n/**\n * `awk1.<provider>.<intentId>[.<sourceTxHash>[.<claimTxHash>[.ok]]]` — the 4th segment is on the id `claimSwap2`\n * returns, and `.ok` after it when the destination account saw the claim succeed (`destTxConfirmed`).\n */\nexport function parseSwapId(id: string): { provider: string; intentId: string; sourceTxHash?: string; destTxHash?: string; destTxConfirmed?: true } | null {\n if (!id.startsWith(`${SWAP2_ID_PREFIX}.`)) return null\n const parts = id.slice(SWAP2_ID_PREFIX.length + 1).split('.')\n if (parts.length < 2 || parts.length > 5 || !parts[0] || !parts[1]) return null\n if (parts[4] !== undefined && (parts[4] !== 'ok' || !parts[3])) return null\n const provider = decodeURIComponent(parts[0])\n const intentId = decodeURIComponent(parts[1])\n const sourceTxHash = parts[2] ? decodeURIComponent(parts[2]) : undefined\n const destTxHash = parts[3] ? decodeURIComponent(parts[3]) : undefined\n if (destTxHash && !sourceTxHash) return null\n return { provider, intentId, ...(sourceTxHash ? { sourceTxHash } : {}), ...(destTxHash ? { destTxHash } : {}), ...(parts[4] !== undefined ? { destTxConfirmed: true as const } : {}) }\n}\n\nexport class SwapsStore {\n private _records: SwapRecord[] | null = null\n private readonly _listeners = new Set<() => void>()\n /**\n * add / update / remove run here one after another, each reading the list inside its turn: an\n * alarm tick's update that read the list before a new swap was added would otherwise write the\n * old list back and drop the swap.\n */\n private _queue: Promise<unknown> = Promise.resolve()\n\n constructor(private readonly storage: JsonStorage<SwapRecord[]>) {}\n\n async list(): Promise<SwapRecord[]> {\n return [...(await this._all())].sort((a, b) => b.createdAt - a.createdAt)\n }\n\n async get(id: string): Promise<SwapRecord | null> {\n return (await this.list()).find((r) => r.id === id) ?? null\n }\n\n async active(): Promise<SwapRecord[]> {\n return (await this.list()).filter((r) => ACTIVE_STATUSES.has(r.status))\n }\n\n add(record: SwapRecord): Promise<void> {\n return this._serial(async () => {\n const all = (await this._all()).filter((r) => r.id !== record.id)\n await this.write([...all, record])\n })\n }\n\n update(id: string, patch: Partial<SwapRecord>): Promise<SwapRecord | null> {\n return this._serial(async () => {\n const all = [...(await this._all())]\n const i = all.findIndex((r) => r.id === id)\n if (i < 0) return null\n const next = { ...all[i]!, ...patch, updatedAt: patch.updatedAt ?? Date.now() }\n all[i] = next\n await this.write(all)\n return next\n })\n }\n\n remove(id: string): Promise<void> {\n return this._serial(async () => {\n await this.write((await this._all()).filter((r) => r.id !== id))\n })\n }\n\n onChange(listener: () => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n private async _all(): Promise<SwapRecord[]> {\n this._records ??= (await this.storage.get()) ?? []\n return this._records\n }\n\n private _serial<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n private async write(records: SwapRecord[]): Promise<void> {\n await this.storage.set(records)\n this._records = records\n for (const l of this._listeners) l()\n }\n}\n\nexport interface SwapTrackerDeps {\n store: SwapsStore\n /** The provider's view of the swap (`CrossChainRouter.trackIntent`). */\n status(record: SwapRecord): Promise<IntentStatus>\n /** Start / stop the periodic alarm (`chrome.alarms.create(name, { periodInMinutes: 1 })`). */\n alarm: { start(): Promise<void> | void; stop(): Promise<void> | void }\n now?: () => number\n /** No progress for this long → `expired` (default 48 h). */\n giveUpAfterMs?: number\n}\n\nexport class SwapTracker {\n private readonly now: () => number\n private ticking: Promise<void> | null = null\n\n constructor(private readonly deps: SwapTrackerDeps) {\n this.now = deps.now ?? Date.now\n }\n\n /** Record a just-executed swap and make sure the alarm runs. */\n async track(input: Omit<SwapRecord, 'createdAt' | 'updatedAt' | 'checks' | 'status' | 'destTxHash'> & { status?: SwapRecordStatus }): Promise<SwapRecord> {\n const t = this.now()\n const record: SwapRecord = { ...input, status: input.status ?? 'pending', destTxHash: null, createdAt: t, updatedAt: t, checks: 0 }\n await this.deps.store.add(record)\n await this.deps.alarm.start()\n return record\n }\n\n /** After the user's claim transaction went out: keep polling until the provider sees the mint. */\n async claimed(id: string, destTxHash: string): Promise<void> {\n await this.deps.store.update(id, { status: 'claiming', destTxHash, claim: undefined as never })\n await this.deps.alarm.start()\n }\n\n /** One alarm tick: check every active record once; stop the alarm when nothing is active. Concurrent ticks coalesce. */\n tick(): Promise<void> {\n this.ticking ??= this.run().finally(() => { this.ticking = null })\n return this.ticking\n }\n\n private async run(): Promise<void> {\n const active = await this.deps.store.active()\n if (active.length === 0) { await this.deps.alarm.stop(); return }\n const giveUp = this.deps.giveUpAfterMs ?? 48 * 60 * 60_000\n for (const record of active) {\n const patch: Partial<SwapRecord> = { checks: record.checks + 1, updatedAt: this.now() }\n try {\n const s = await this.deps.status(record)\n patch.lastError = undefined as never\n if (s.depositReceived !== undefined) patch.depositReceived = s.depositReceived\n if (s.destTxHash) patch.destTxHash = s.destTxHash\n if (s.claim) patch.claim = s.claim\n // Our own claim is out: the provider still says action-required until it sees the mint; keep \"claiming\".\n patch.status = record.status === 'claiming' && (s.state === 'action-required' || s.state === 'pending') ? 'claiming' : s.state\n } catch (e) {\n patch.lastError = e instanceof Error ? e.message : String(e)\n if (this.now() - record.createdAt > giveUp) patch.status = 'expired'\n }\n await this.deps.store.update(record.id, patch)\n }\n if ((await this.deps.store.active()).length === 0) await this.deps.alarm.stop()\n }\n}\n","/**\n * Earn plan review — the Earn modules' counterpart of the swap sheet. A module\n * that exposes its plan (Aave / Morpho `planSupply` & co: ERC-20 approvals\n * first, then the call) gets ONE sheet for the whole plan; on approval exactly\n * those calls are pre-approved in the {@link ReviewGate} so the module's own\n * `supply()` / `withdraw()` / … passes through the reviewed account without a\n * second window. Modules without a plan API (Mellow, Lido, SSV, Jito) are\n * reviewed per transaction by the reviewed account itself — still every send.\n */\nimport { ApprovalQueue } from './approvals.js'\nimport { ReviewGate, evmCallMatcher, type GateMatcher } from './gate.js'\nimport type { EvmNetwork } from './networks.js'\n\nexport interface EarnTx {\n to: string\n data?: string | undefined\n /** Base units, decimal string. */\n value: string\n}\n\nexport interface EarnPlan {\n approvals: EarnTx[]\n tx: EarnTx\n}\n\nexport interface EarnReviewMeta {\n origin: string\n /** The account that sends the plan: the gate passes its calls for this account only. */\n account: string\n /** 'Aave v3', 'Morpho', … */\n module: string\n /** 'Supply', 'Withdraw', 'Borrow', 'Repay', 'Stake', … */\n action: string\n network: EvmNetwork\n /** Human lines the sheet shows (asset, amount, APY, market/vault, health factor…). */\n facts: { k: string; v: string }[]\n /** What the module says about the plan (its own refusals never reach here — they throw before). */\n checks?: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n /** tx-preview-evm result for approvals + call, attached by the wallet (JSON-safe) or null. */\n preview?: unknown\n}\n\nexport interface EarnApproval {\n module: string\n action: string\n network: EvmNetwork\n facts: { k: string; v: string }[]\n approvals: EarnTx[]\n tx: EarnTx\n checks: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n preview: unknown\n}\n\nconst APPROVE_SELECTOR = '0x095ea7b3'\n\nexport function earnPlanMatchers(network: EvmNetwork, plan: EarnPlan): GateMatcher[] {\n return [...plan.approvals, plan.tx].map((t) => evmCallMatcher({ caip2: network.caip2, to: t.to, data: t.data, value: BigInt(t.value) }))\n}\n\nexport function earnApprovalPayload(plan: EarnPlan, meta: EarnReviewMeta): EarnApproval {\n const checks = [{ status: 'ok' as const, label: `Built by the ${meta.module} module` }, ...(meta.checks ?? [])]\n for (const a of plan.approvals) {\n if (!a.data?.startsWith(APPROVE_SELECTOR)) checks.push({ status: 'warn', label: `Unexpected pre-call to ${a.to.slice(0, 8)}…` })\n }\n if (plan.approvals.length > 1) checks.push({ status: 'ok', label: `${plan.approvals.length} approvals (reset to 0 first)` })\n return { module: meta.module, action: meta.action, network: meta.network, facts: meta.facts, approvals: plan.approvals, tx: plan.tx, checks, preview: meta.preview ?? null }\n}\n\n/** One sheet for the plan; approve → pre-approve exactly its calls; decline → ReviewDeclined, nothing sent. */\nexport async function reviewEarnPlan(approvals: ApprovalQueue, gate: ReviewGate, meta: EarnReviewMeta, plan: EarnPlan): Promise<void> {\n if (typeof meta.account !== 'string' || !meta.account) throw new TypeError('reviewEarnPlan needs meta.account: the gate passes the plan for that account only.')\n await approvals.request({ origin: meta.origin, chain: meta.network.caip2, kind: 'earn', payload: earnApprovalPayload(plan, meta) })\n gate.preApprove(earnPlanMatchers(meta.network, plan), 10 * 60_000, meta.account)\n}\n","/**\n * TON Connect protocol v2 for the extension's JS bridge. Request parsing, error codes and the\n * signature digests live in one place, `@anywalletkit/wallet-ton/tonconnect`, shared with the\n * WalletConnect transport (`@anywalletkit/walletconnect-ton`); this module re-exports them and\n * keeps the bridge-side helpers (the page origin as the proof domain, relay errors as TON Connect\n * codes). The wallet side (keys, sheet, broadcast) lives in the extension; nothing here touches a key.\n *\n * To SIGN, use `WalletAccountTon.signTonProof` / `signTonConnectData` (wallet-ton): they build the\n * same digests from the request and the account's own address. `account.sign()` refuses these\n * 32-byte digests — 32 raw bytes may as well be the hash of a transfer — so the digest functions\n * here are for checking a proof, not for feeding `sign()`.\n */\nimport { TONCONNECT_ERRORS, TonConnectError, tonAddressParts, tonProofDigest, tonSignDataDigest, type TonSignDataPayload } from '@anywalletkit/wallet-ton/tonconnect'\n\nexport {\n TONCONNECT_ERRORS, TONCONNECT_MAX_MESSAGES, TONCONNECT_NETWORKS, TONCONNECT_SIGN_DATA_MAX, TonConnectError,\n parseConnectRequest, parseSendTransaction, parseSignData, tonConnectRawAddress, tonConnectFriendlyAddress, sameTonConnectAddress,\n type TonConnectRequest, type TonConnectMessage, type TonConnectSendTransaction, type TonConnectParseOptions, type TonConnectSendOptions, type TonSignDataPayload,\n} from '@anywalletkit/wallet-ton/tonconnect'\n\n/** Workchain and 32-byte account hash of a TON address. */\nexport interface TonAddressParts { workchain: number; hash: Uint8Array }\n\nconst parts = (a: TonAddressParts) => {\n if (a.hash.length !== 32) throw new TonConnectError(TONCONNECT_ERRORS.unknown, 'address hash must be 32 bytes')\n return { workChain: a.workchain, hash: a.hash }\n}\n\n/** The 32-byte digest a wallet signs for `ton_proof` — to verify a proof; sign with `WalletAccountTon.signTonProof`. */\nexport function tonProofMessage(input: { address: TonAddressParts; domain: string; timestamp: number; payload: string }): Uint8Array {\n return tonProofDigest(parts(input.address), { domain: input.domain, timestamp: input.timestamp, payload: input.payload })\n}\n\n/** The 32-byte digest a wallet signs for `signData` (text / binary) — to verify; sign with `WalletAccountTon.signTonConnectData`. */\nexport function tonSignDataMessage(input: { address: TonAddressParts; domain: string; timestamp: number; payload: TonSignDataPayload }): Uint8Array {\n return tonSignDataDigest(parts(input.address), { domain: input.domain, timestamp: input.timestamp, payload: input.payload })\n}\n\n/** `0:abcd…` → parts. Friendly addresses are the wallet package's job (it hands us the raw form). */\nexport function parseRawAddress(raw: string): TonAddressParts {\n if (!/^-?\\d+:[0-9a-fA-F]{64}$/.test(raw)) throw new TonConnectError(TONCONNECT_ERRORS.unknown, `not a raw TON address: ${raw}`)\n try {\n const p = tonAddressParts(raw)\n return { workchain: p.workChain, hash: p.hash }\n } catch {\n throw new TonConnectError(TONCONNECT_ERRORS.unknown, `not a raw TON address: ${raw}`)\n }\n}\n\n/** The dApp's domain for proofs, from the page origin (host only, as the spec's `domain.value`). */\nexport function proofDomain(origin: string): string {\n try { return new URL(origin).host } catch { throw new TonConnectError(TONCONNECT_ERRORS.badRequest, `bad origin ${origin}`) }\n}\n\n/** Our relay errors → TON Connect error codes. */\nexport function tonConnectErrorCode(e: unknown): number {\n if (e instanceof TonConnectError || (e as { name?: unknown } | null)?.name === 'TonConnectError') return (e as TonConnectError).code\n const code = (e as { code?: unknown })?.code\n if (code === 4001) return TONCONNECT_ERRORS.userDeclined\n if (code === 4100) return TONCONNECT_ERRORS.unknownApp\n if (code === 4200) return TONCONNECT_ERRORS.methodNotSupported\n if (code === -32602) return TONCONNECT_ERRORS.badRequest\n return TONCONNECT_ERRORS.unknown\n}\n","/**\n * Phishing / impersonation checks on a page's host, against a SHIPPED list\n * (never fetched at runtime — decision 10). The list format is MetaMask's\n * eth-phishing-detect `config.json`: `blacklist` / `whitelist` (hosts; a listed\n * domain covers its subdomains), `fuzzylist` + `tolerance` (well-known hosts a\n * lookalike is measured against by Levenshtein distance). On top: punycode\n * (`xn--`) labels are flagged, because mixed-script lookalikes are the common\n * impersonation shape.\n */\nexport interface PhishingList {\n version?: number\n tolerance?: number\n blacklist: readonly string[]\n whitelist?: readonly string[]\n fuzzylist?: readonly string[]\n /** The wallet's own additions to the fuzzylist (the big dApps our users visit): same semantics. */\n extraFuzzylist?: readonly string[]\n}\n\nexport interface HostCheck {\n host: string\n /** On the blocklist (or a subdomain of a listed domain): refuse to inject / connect. */\n blocked: boolean\n /** Human lines for the approval window; empty when nothing is odd. */\n warnings: string[]\n}\n\nexport class PhishingDetector {\n private readonly black: Set<string>\n private readonly white: Set<string>\n private readonly fuzzy: string[]\n private readonly tolerance: number\n\n constructor(list: PhishingList) {\n this.black = new Set(list.blacklist.map(normalizeHost))\n this.white = new Set((list.whitelist ?? []).map(normalizeHost))\n this.fuzzy = [...new Set([...(list.fuzzylist ?? []), ...(list.extraFuzzylist ?? [])].map(normalizeHost))]\n this.tolerance = list.tolerance ?? 1\n }\n\n get size(): number {\n return this.black.size\n }\n\n check(hostOrOrigin: string): HostCheck {\n const host = hostOf(hostOrOrigin)\n const warnings: string[] = []\n if (!host) return { host, blocked: false, warnings }\n if (matchesList(host, this.white)) return { host, blocked: false, warnings }\n if (matchesList(host, this.black)) return { host, blocked: true, warnings: ['This site is on the shipped phishing list.'] }\n if (host.split('.').some((l) => l.startsWith('xn--'))) warnings.push('The address uses punycode (xn--): it may imitate another site with look-alike characters.')\n const look = this.lookalike(host)\n if (look) warnings.push(`The address looks like ${look} but is not that site.`)\n else {\n const brand = this.brandInLabel(host)\n if (brand) warnings.push(`The address contains the name of ${brand.known} (“${brand.label}”) but is not that site.`)\n }\n return { host, blocked: false, warnings }\n }\n\n /**\n * Why `hostOrOrigin` must be refused outright, or `null`: a host on the blocklist (or under a\n * listed domain) and not on the allowlist. Lookalikes and punycode only warn ({@link check}).\n * Wire it as `ApprovalQueueOptions.refuse` and `RouterDeps.refuse`.\n */\n refusal(hostOrOrigin: string): string | null {\n return this.check(hostOrOrigin).blocked ? 'This site is on the wallet\\'s phishing list; the wallet refuses its requests.' : null\n }\n\n /**\n * `metamask.io-login.com`, `app-uniswap.com`, `uniswap.org.evil.net`: a known site's name used as (part of) a label\n * of a host that is not that site. Names shorter than 5 characters are skipped (too many honest matches).\n */\n brandInLabel(host: string): { known: string; label: string } | null {\n const labels = host.split('.')\n for (const known of this.fuzzy) {\n if (host === known || host.endsWith(`.${known}`)) return null\n const name = stripForFuzzy(known).split('.').pop() ?? ''\n if (name.length < 5) continue\n const hit = labels.find((l) => l.includes(name))\n if (hit) return { known, label: hit }\n }\n return null\n }\n\n /** eth-phishing-detect's fuzzy check: the host (minus the TLD and a www.) within `tolerance` edits of a known one. */\n lookalike(host: string): string | null {\n const probe = stripForFuzzy(host)\n const probeName = probe.split('.').pop() ?? probe\n for (const known of this.fuzzy) {\n if (host === known || host.endsWith(`.${known}`)) return null // the real site or one of its subdomains\n const stripped = stripForFuzzy(known)\n if (levenshtein(probe, stripped) <= this.tolerance) return known // same name on another TLD counts as a lookalike\n // `uniswep.org` vs the listed `app.uniswap.org`: compare the registrable labels too (names ≥ 5 chars)\n const name = stripped.split('.').pop() ?? stripped\n if (name.length >= 5 && name !== probeName && levenshtein(probeName, name) <= this.tolerance) return known\n }\n return null\n }\n}\n\nexport const normalizeHost = (h: string): string => h.trim().toLowerCase().replace(/\\.$/, '')\n\nexport function hostOf(hostOrOrigin: string): string {\n try { return normalizeHost(new URL(hostOrOrigin.includes('://') ? hostOrOrigin : `https://${hostOrOrigin}`).hostname) } catch { return normalizeHost(hostOrOrigin) }\n}\n\n/** `a.b.c` matches a list containing `a.b.c`, `b.c` (parent) — never `c` alone unless listed. */\nfunction matchesList(host: string, list: Set<string>): boolean {\n const parts = host.split('.')\n for (let i = 0; i < parts.length - 1; i++) if (list.has(parts.slice(i).join('.'))) return true\n return list.has(host)\n}\n\nfunction stripForFuzzy(host: string): string {\n const parts = host.replace(/^www\\./, '').split('.')\n if (parts.length > 1) parts.pop() // TLD\n return parts.join('.')\n}\n\nexport function levenshtein(a: string, b: string): number {\n if (a === b) return 0\n const m = a.length, n = b.length\n if (m === 0) return n\n if (n === 0) return m\n let prev = Array.from({ length: n + 1 }, (_, j) => j)\n for (let i = 1; i <= m; i++) {\n const cur = [i]\n for (let j = 1; j <= n; j++) cur[j] = Math.min(prev[j]! + 1, cur[j - 1]! + 1, prev[j - 1]! + (a[i - 1] === b[j - 1] ? 0 : 1))\n prev = cur\n }\n return prev[n]!\n}\n","/**\n * WebAuthn assertion verification for \"passkey on every signature\": the approval\n * page asks the authenticator to sign a challenge the service worker derived from\n * the request, and the worker checks the assertion against the public key the\n * vault stored at registration. The ceremony itself (`navigator.credentials`) runs\n * in an extension page; this module is pure WebCrypto so it is testable and the\n * worker never trusts the page's word that the user touched the authenticator.\n *\n * ES256 (COSE -7, P-256 + SHA-256) only — the only algorithm registration asks\n * for. The signature is DER (WebAuthn) and converted to the raw r‖s WebCrypto\n * wants.\n */\nimport { fromBase64, toArrayBuffer } from './codec.js'\nimport { fromBase64Url } from './vault.js'\n\nexport interface AssertionInput {\n /** `PublicKeyCredential.rawId`, base64url. */\n credentialId: string\n /** `AuthenticatorAssertionResponse.authenticatorData`, base64url. */\n authenticatorData: string\n /** `AuthenticatorAssertionResponse.clientDataJSON`, base64url. */\n clientDataJSON: string\n /** `AuthenticatorAssertionResponse.signature` (DER), base64url. */\n signature: string\n}\n\nexport interface AssertionExpectations {\n /** SPKI public key of the credential, base64 (what `getPublicKey()` returned at registration). */\n publicKey: string\n /** COSE alg of the key; only -7 is accepted. */\n alg: number\n /** The challenge the worker handed the page (raw bytes; the page sent it base64url in clientDataJSON). */\n challenge: Uint8Array\n /** `chrome-extension://<id>` */\n origin: string\n /** The RP id the credential was created for (the extension id); its SHA-256 must be the first 32 bytes of authenticatorData. */\n rpId: string\n /** Require the UV flag (user verification: biometric / PIN) — on for signing. */\n requireUserVerification?: boolean\n crypto?: Crypto\n}\n\nexport type AssertionVerdict = { ok: true; counter: number } | { ok: false; reason: string }\n\nconst FLAG_UP = 0x01\nconst FLAG_UV = 0x04\n\n/** Verify one assertion. Never throws on bad input — a verdict with the reason, so the worker can refuse in-band. */\nexport async function verifyAssertion(input: AssertionInput, expect: AssertionExpectations): Promise<AssertionVerdict> {\n const c = expect.crypto ?? globalThis.crypto\n try {\n if (expect.alg !== -7) return { ok: false, reason: `unsupported algorithm ${expect.alg} (ES256 only)` }\n const authData = fromBase64Url(input.authenticatorData)\n const clientData = fromBase64Url(input.clientDataJSON)\n const signature = fromBase64Url(input.signature)\n if (authData.length < 37) return { ok: false, reason: 'authenticatorData too short' }\n // 1. client data: type, challenge, origin\n let client: { type?: unknown; challenge?: unknown; origin?: unknown; crossOrigin?: unknown }\n try { client = JSON.parse(new TextDecoder().decode(clientData)) as typeof client } catch { return { ok: false, reason: 'clientDataJSON is not JSON' } }\n if (client.type !== 'webauthn.get') return { ok: false, reason: `clientData.type is ${String(client.type)}` }\n if (client.origin !== expect.origin) return { ok: false, reason: `assertion origin ${String(client.origin)} is not ${expect.origin}` }\n if (client.crossOrigin === true) return { ok: false, reason: 'cross-origin assertion' }\n if (typeof client.challenge !== 'string' || !equal(fromBase64Url(client.challenge), expect.challenge)) return { ok: false, reason: 'challenge does not match this request' }\n // 2. authenticator data: rpIdHash, flags, counter\n const rpIdHash = new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(new TextEncoder().encode(expect.rpId))))\n if (!equal(authData.subarray(0, 32), rpIdHash)) return { ok: false, reason: 'rpIdHash does not match this extension' }\n const flags = authData[32]!\n if (!(flags & FLAG_UP)) return { ok: false, reason: 'user presence flag not set' }\n if (expect.requireUserVerification !== false && !(flags & FLAG_UV)) return { ok: false, reason: 'user verification flag not set' }\n const counter = ((authData[33]! << 24) | (authData[34]! << 16) | (authData[35]! << 8) | authData[36]!) >>> 0\n // 3. signature over authenticatorData ‖ SHA-256(clientDataJSON)\n const clientHash = new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(clientData)))\n const signed = new Uint8Array(authData.length + clientHash.length)\n signed.set(authData, 0)\n signed.set(clientHash, authData.length)\n const raw = derToRaw(signature)\n if (!raw) return { ok: false, reason: 'signature is not a DER ECDSA signature' }\n const key = await c.subtle.importKey('spki', toArrayBuffer(fromBase64(expect.publicKey)), { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify'])\n const ok = await c.subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, key, toArrayBuffer(raw), toArrayBuffer(signed))\n return ok ? { ok: true, counter } : { ok: false, reason: 'signature does not verify against the registered passkey' }\n } catch (e) {\n return { ok: false, reason: e instanceof Error ? e.message : String(e) }\n }\n}\n\n/** DER `SEQUENCE { INTEGER r, INTEGER s }` → 64-byte r‖s; `null` when malformed. */\nexport function derToRaw(der: Uint8Array): Uint8Array | null {\n if (der[0] !== 0x30) return null\n let i = 2\n if (der[1]! & 0x80) i = 2 + (der[1]! & 0x7f)\n const int = (): Uint8Array | null => {\n if (der[i] !== 0x02) return null\n const len = der[i + 1]!\n const start = i + 2\n i = start + len\n let v = der.subarray(start, start + len)\n while (v.length > 32 && v[0] === 0) v = v.subarray(1)\n if (v.length > 32) return null\n const out = new Uint8Array(32)\n out.set(v, 32 - v.length)\n return out\n }\n const r = int()\n if (!r) return null\n const s = int()\n if (!s) return null\n const raw = new Uint8Array(64)\n raw.set(r, 0)\n raw.set(s, 32)\n return raw\n}\n\n/** Raw r‖s → DER (tests build assertions with WebCrypto, which signs raw). */\nexport function rawToDer(raw: Uint8Array): Uint8Array {\n const enc = (v: Uint8Array): number[] => {\n let i = 0\n while (i < v.length - 1 && v[i] === 0) i++\n let body = Array.from(v.subarray(i))\n if (body[0]! & 0x80) body = [0, ...body]\n return [0x02, body.length, ...body]\n }\n const r = enc(raw.subarray(0, 32))\n const s = enc(raw.subarray(32, 64))\n return Uint8Array.from([0x30, r.length + s.length, ...r, ...s])\n}\n\n/**\n * The challenge for one approval request: SHA-256 over the request id, kind,\n * origin and payload, so an assertion made for one sheet cannot answer another.\n */\nexport async function approvalChallenge(request: { id: string; kind: string; origin: string; payload: unknown }, c: Crypto = globalThis.crypto): Promise<Uint8Array> {\n const text = JSON.stringify([request.id, request.kind, request.origin, request.payload])\n return new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(new TextEncoder().encode(text))))\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n let d = 0\n for (let i = 0; i < a.length; i++) d |= a[i]! ^ b[i]!\n return d === 0\n}\n","/**\n * Address poisoning: an attacker sends dust from an address whose first and\n * last characters match one the user actually paid, hoping the next copy-paste\n * picks the wrong one. The wallet has no transaction history, so it keeps its\n * own book of recipients the user confirmed (per chain) and warns when a new\n * recipient looks like one of them without being it. \"Fresh address\" (no\n * activity on chain) is the other half of the signal; the EVM preview computes it.\n */\nimport type { JsonStorage } from './storage.js'\n\nexport type RecipientsState = Record<string, string[]>\n\n/** How many characters at each end must match (after any `0x`). */\nexport const LOOKALIKE_PREFIX = 4\nexport const LOOKALIKE_SUFFIX = 4\n\nconst norm = (a: string) => a.trim().toLowerCase().replace(/^0x/, '')\n\n/** A known recipient that `address` imitates (same start and end, different address), or `null`. */\nexport function lookalikeOf(address: string, known: readonly string[]): string | null {\n const a = norm(address)\n if (a.length < LOOKALIKE_PREFIX + LOOKALIKE_SUFFIX + 1) return null\n for (const k of known) {\n const b = norm(k)\n if (b === a || b.length !== a.length) continue\n if (a.startsWith(b.slice(0, LOOKALIKE_PREFIX)) && a.endsWith(b.slice(-LOOKALIKE_SUFFIX))) return k\n }\n return null\n}\n\n/** Recipients the user confirmed on each chain (`eip155`, `solana`, …), newest last, capped. */\nexport class RecipientBook {\n private _state: RecipientsState | null = null\n\n constructor(private readonly storage: JsonStorage<RecipientsState>, private readonly cap = 500) {}\n\n private async state(): Promise<RecipientsState> {\n this._state ??= (await this.storage.get()) ?? {}\n return this._state\n }\n\n async list(namespace: string): Promise<string[]> {\n return [...((await this.state())[namespace] ?? [])]\n }\n\n async remember(namespace: string, address: string): Promise<void> {\n const s = { ...(await this.state()) }\n const list = (s[namespace] ?? []).filter((a) => norm(a) !== norm(address))\n list.push(address)\n s[namespace] = list.slice(-this.cap)\n await this.storage.set(s)\n this._state = s\n }\n\n /** `known` → the address is one the user paid before; `lookalike` → it imitates one. */\n async check(namespace: string, address: string): Promise<{ known: boolean; lookalike: string | null }> {\n const list = await this.list(namespace)\n const known = list.some((a) => norm(a) === norm(address))\n return { known, lookalike: known ? null : lookalikeOf(address, list) }\n }\n}\n"],"mappings":"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","names":["kek","kdf","import_core","import_core","import_core","handle","lc","lc","import_protocol_swap2_core","parts","APPROVE_SELECTOR","import_tonconnect","parts"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/vault.ts","../src/codec.ts","../src/session.ts","../src/relay.ts","../src/chrome.ts","../src/keyring.ts","../src/networks.ts","../src/storage.ts","../src/permissions.ts","../src/site.ts","../src/approvals.ts","../src/router.ts","../src/siwe.ts","../src/signing.ts","../src/gate.ts","../src/swap.ts","../src/swaps.ts","../src/earn.ts","../src/tonconnect.ts","../src/phishing.ts","../src/webauthn.ts","../src/poison.ts","../src/mac-storage.ts"],"sourcesContent":["export * from './errors.js'\nexport * from './vault.js'\nexport * from './session.js'\nexport * from './relay.js'\nexport * from './chrome.js'\nexport * from './keyring.js'\nexport * from './networks.js'\nexport * from './storage.js'\nexport * from './permissions.js'\nexport * from './approvals.js'\nexport * from './router.js'\nexport * from './signing.js'\nexport * from './gate.js'\nexport * from './swap.js'\nexport * from './swaps.js'\nexport * from './earn.js'\nexport * from './tonconnect.js'\nexport * from './phishing.js'\nexport * from './webauthn.js'\nexport * from './siwe.js'\nexport * from './poison.js'\nexport * from './mac-storage.js'\nexport * from './site.js'\n","/** A vault or session rule was broken. Messages are safe to show the user and never contain secrets. */\nexport class VaultError extends Error {\n readonly code: VaultErrorCode\n constructor(message: string, code: VaultErrorCode) {\n super(message)\n this.name = 'VaultError'\n this.code = code\n }\n}\n\nexport type VaultErrorCode =\n /** The password did not open the vault (or the envelope was tampered with — AES-GCM cannot tell the two apart). */\n | 'wrong-password'\n /** `create` was called while a vault already exists — an existing wallet is never overwritten. */\n | 'exists'\n /** `unlock` / `getSecret` on a storage area that holds no vault. */\n | 'missing'\n /** The stored envelope has a version or shape this build does not read. */\n | 'unsupported-envelope'\n /** The session is locked: the unlocked key is gone (auto-lock, browser exit, explicit lock). */\n | 'locked'\n /** Bad input (empty or too-short password, bad key length, bad id). */\n | 'invalid-input'\n /** The stored envelope's KDF parameters are below the floor this build accepts (edited on disk). */\n | 'weak-kdf'\n","/**\n * The vault: every secret (seed phrase, imported private key, TON words) at rest\n * in `chrome.storage.local`, encrypted with WebCrypto plus one audited pure-JS\n * primitive (`@noble/hashes` scrypt) — no WASM, no third-party crypto in the\n * key path beyond that.\n *\n * Two layers of keys, so that unlocking does not keep the password around and\n * other unlock paths (passkeys) do not re-encrypt the secrets:\n *\n * ```text\n * password ──scrypt (N=2^17, r=8, p=1)──▶ KEK ──AES-256-GCM──▶ wraps the DEK (envelope v2)\n * passkey PRF ──HKDF-SHA256 (salt = credential id)──▶ KEK ──AES-256-GCM──▶ wraps the DEK, one box per passkey\n * DEK (32 random bytes) ──AES-256-GCM, AAD = secret id──▶ each secret\n * ```\n *\n * What the session holds while unlocked is the DEK (see {@link Session}); the\n * password and the PRF output never leave {@link Vault.create} / {@link Vault.unlock} /\n * {@link Vault.unlockWithPasskey}. Every ciphertext carries its own 96-bit IV; the\n * AAD binds a secret to its id (so two entries cannot be swapped inside the\n * envelope) and binds the DEK box to the exact KDF parameters (so an envelope whose\n * salt or cost was edited on disk fails to open instead of deriving a weaker key).\n * Wrong password and tampering are indistinguishable (GCM tag failure) and both\n * surface as `wrong-password`.\n *\n * Envelope versions: v1 = PBKDF2-SHA256 (≥ 600 000 iterations), still opened and\n * re-sealed as v2 on the next successful unlock (MetaMask's `updateVault` pattern);\n * v2 = scrypt (OWASP parameters, memory-hard: an attacker who copied the Chrome\n * profile cannot run the search on GPUs the way PBKDF2 allows) + optional passkey\n * boxes. Anything else is refused (`unsupported-envelope`) instead of guessed.\n * Passwords: at least {@link VAULT_MIN_PASSWORD_LENGTH} characters, enforced here\n * and not only in a UI.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport { scryptAsync } from '@noble/hashes/scrypt.js'\nimport { fromBase64, toArrayBuffer, toBase64, withSecretBuffer } from './codec.js'\nimport { VaultError } from './errors.js'\n\n/** PBKDF2-SHA256 iterations (v1 envelopes): OWASP 2023 floor for SHA-256; anything lower is refused. */\nexport const VAULT_MIN_ITERATIONS = 600_000\nexport const VAULT_DEFAULT_ITERATIONS = 600_000\n/** scrypt for v2 envelopes: OWASP's recommended cost (128 MiB, ~1 s in a service worker). */\nexport const VAULT_SCRYPT = { N: 1 << 17, r: 8, p: 1 } as const\n/** The weakest scrypt an envelope may carry and still open (16 MiB). Tests use this; `create` uses {@link VAULT_SCRYPT}. */\nexport const VAULT_MIN_SCRYPT = { N: 1 << 14, r: 8, p: 1 } as const\n/** Shortest password `create` / `changePassword` accept. `unlock` takes whatever opens the vault. */\nexport const VAULT_MIN_PASSWORD_LENGTH = 8\n/**\n * Upper bounds on what an envelope (and the options) may carry, checked before any KDF runs: an\n * envelope edited on disk must not make unlock hang (PBKDF2 iterations) or exhaust the worker's\n * memory (scrypt N × r), and its size stays within what `chrome.storage.local` holds.\n */\nexport const VAULT_LIMITS = Object.freeze({\n /** scrypt cost: 2^20 × 16 = 2 GiB is the most any envelope may ask for. */\n scrypt: Object.freeze({ N: 1 << 20, r: 16, p: 4 }),\n /** PBKDF2-SHA256 iterations (v1 envelopes). */\n iterations: 5_000_000,\n /** Sealed secrets in one vault. */\n secrets: 1_000,\n /** Registered passkeys. */\n passkeys: 32,\n /** Plaintext bytes of one secret (`setSecret`). */\n secretBytes: 16 * 1024,\n /** base64 characters of one sealed box (iv or data). */\n boxChars: 32 * 1024,\n /** JSON characters of the whole envelope. */\n envelopeChars: 4 * 1024 * 1024,\n})\nconst SALT_BYTES = 32\nconst IV_BYTES = 12\nconst DEK_BYTES = 32\n/** PRF outputs are 32 bytes (WebAuthn `prf` extension, `first`). */\nconst PRF_BYTES = 32\n\nexport interface SealedBox {\n /** 96-bit AES-GCM nonce, base64. */\n iv: string\n /** ciphertext ‖ 128-bit tag, base64. */\n data: string\n}\n\nexport interface VaultEnvelopeV1 {\n v: 1\n kdf: { name: 'PBKDF2-SHA256'; iterations: number; salt: string }\n /** The DEK, sealed under the password-derived key. AAD = version + kdf. */\n dek: SealedBox\n /** One box per key source (keyring source id), sealed under the DEK. AAD `forgewallet-vault/secret/<id>`. */\n secrets: Record<string, SealedBox>\n /** A fixed value sealed under the DEK (AAD `forgewallet-vault/dek-check`): proves a key is this vault's while it holds no secret. Absent in envelopes written before it existed. */\n dekCheck?: SealedBox\n createdAt: number\n}\n\nexport interface VaultPasskey {\n /** WebAuthn credential id, base64url. */\n id: string\n label: string\n createdAt: number\n /** The DEK sealed under HKDF(PRF output, salt = credential id). AAD = `forgewallet-vault/2/passkey/<id>`. */\n dek: SealedBox\n /** The credential's public key (SPKI, base64) when the authenticator gave one — lets the worker verify assertions (passkey-per-signature). */\n publicKey?: string\n /** COSE algorithm of `publicKey` (-7 = ES256). */\n alg?: number\n}\n\nexport interface VaultEnvelopeV2 {\n v: 2\n kdf: { name: 'scrypt'; N: number; r: number; p: number; salt: string }\n dek: SealedBox\n secrets: Record<string, SealedBox>\n /** See {@link VaultEnvelopeV1.dekCheck}. */\n dekCheck?: SealedBox\n passkeys: VaultPasskey[]\n createdAt: number\n /** When a v1 envelope was re-sealed as v2. */\n upgradedAt?: number\n /** When {@link Vault.rotateVaultKey} last replaced the DEK. */\n rotatedAt?: number\n}\n\nexport type VaultEnvelope = VaultEnvelopeV1 | VaultEnvelopeV2\n\n/** Where the envelope lives. `chromeLocalVaultStorage()` for the extension, `memoryVaultStorage()` for tests. */\nexport interface VaultStorage {\n get(): Promise<VaultEnvelope | null>\n set(envelope: VaultEnvelope): Promise<void>\n clear(): Promise<void>\n}\n\nexport interface VaultOptions {\n storage: VaultStorage\n /** KDF for NEW envelopes and re-seals. Default scrypt (v2); `'pbkdf2'` writes v1 (tests, or a build that must stay FIPS-only). */\n kdf?: 'scrypt' | 'pbkdf2'\n /** PBKDF2 iterations for v1 envelopes (default and minimum {@link VAULT_DEFAULT_ITERATIONS}). */\n iterations?: number\n /** scrypt cost for v2 envelopes (default {@link VAULT_SCRYPT}; not below {@link VAULT_MIN_SCRYPT}). */\n scrypt?: { N: number; r: number; p: number }\n /** Progress of the scrypt derivation, 0..1 — the unlock screen's bar. */\n onProgress?: (fraction: number) => void\n /** Defaults to `globalThis.crypto`; injectable for tests. */\n crypto?: Crypto\n}\n\nexport interface VaultKdfInfo {\n version: 1 | 2\n name: 'PBKDF2-SHA256' | 'scrypt'\n /** Human line for the UI, e.g. \"scrypt N=2^17 r=8 p=1\". */\n summary: string\n}\n\n// AAD / HKDF labels are part of the sealed format: existing vaults open only with these exact strings.\nconst aadDekV1 = (kdf: VaultEnvelopeV1['kdf']) => `forgewallet-vault/1/dek/${kdf.name}/${kdf.iterations}/${kdf.salt}`\nconst aadDekV2 = (kdf: VaultEnvelopeV2['kdf']) => `forgewallet-vault/2/dek/scrypt/${kdf.N}/${kdf.r}/${kdf.p}/${kdf.salt}`\nconst aadPasskey = (id: string) => `forgewallet-vault/2/passkey/${id}`\nconst aadSecret = (id: string) => `forgewallet-vault/secret/${id}`\nconst AAD_DEK_CHECK = 'forgewallet-vault/dek-check'\n/** What the DEK check box holds: a fixed value, so opening it proves the key and nothing else. */\nconst DEK_CHECK = 'forgewallet-vault/dek-check/1'\nconst HKDF_INFO = 'forgewallet-vault/2/passkey'\n\n/**\n * One `Vault` per storage area: writes to the envelope are serialized inside the instance, so two\n * instances over the same area could still overwrite each other.\n */\nexport class Vault {\n private readonly _storage: VaultStorage\n /** Every read-modify-write of the envelope runs here, one after another (a parallel write would drop the other's change). */\n private _queue: Promise<unknown> = Promise.resolve()\n private readonly _kdf: 'scrypt' | 'pbkdf2'\n private readonly _iterations: number\n private readonly _scrypt: { N: number; r: number; p: number }\n private readonly _onProgress: ((fraction: number) => void) | undefined\n private readonly _crypto: Crypto\n\n constructor(options: VaultOptions) {\n this._storage = options.storage\n this._kdf = options.kdf ?? 'scrypt'\n this._iterations = options.iterations ?? VAULT_DEFAULT_ITERATIONS\n this._scrypt = options.scrypt ?? VAULT_SCRYPT\n this._onProgress = options.onProgress\n this._crypto = options.crypto ?? globalThis.crypto\n if (!Number.isInteger(this._iterations) || this._iterations < VAULT_MIN_ITERATIONS || this._iterations > VAULT_LIMITS.iterations) {\n throw new VaultError(`PBKDF2 iterations must be an integer from ${VAULT_MIN_ITERATIONS} to ${VAULT_LIMITS.iterations}`, 'invalid-input')\n }\n if (!isStrongScrypt(this._scrypt)) throw new VaultError(`scrypt cost must be at least N=${VAULT_MIN_SCRYPT.N} r=${VAULT_MIN_SCRYPT.r} p=${VAULT_MIN_SCRYPT.p} (N a power of two)`, 'invalid-input')\n if (!isBoundedScrypt(this._scrypt)) throw new VaultError(`scrypt cost must be at most N=${VAULT_LIMITS.scrypt.N} r=${VAULT_LIMITS.scrypt.r} p=${VAULT_LIMITS.scrypt.p}`, 'invalid-input')\n }\n\n async exists(): Promise<boolean> {\n return (await this._storage.get()) !== null\n }\n\n /** What protects the DEK right now (UI). `null` without a vault. */\n async kdfInfo(): Promise<VaultKdfInfo | null> {\n const e = await this._storage.get()\n if (!e) return null\n if (isEnvelopeV1(e)) return { version: 1, name: 'PBKDF2-SHA256', summary: `PBKDF2-SHA256 ${e.kdf.iterations.toLocaleString('en-US')} iterations` }\n if (isEnvelopeV2(e)) return { version: 2, name: 'scrypt', summary: `scrypt N=2^${Math.log2(e.kdf.N)} r=${e.kdf.r} p=${e.kdf.p}` }\n return null\n }\n\n /**\n * Create an empty vault protected by `password`. Returns the DEK — hand it to the\n * session, then `setSecret` the first seed. Refuses when a vault exists.\n */\n async create(password: string): Promise<Uint8Array> {\n requirePassword(password, VAULT_MIN_PASSWORD_LENGTH)\n return this._exclusive(async () => {\n if (await this.exists()) throw new VaultError('A vault already exists; unlock it or reset explicitly.', 'exists')\n const dek = this._random(DEK_BYTES)\n await this._write(await this._sealEnvelope(password, dek, {}, [], Date.now()))\n return dek\n })\n }\n\n /**\n * Derive the KEK from `password`, unseal and return the DEK. `wrong-password` on\n * failure. A v1 (PBKDF2) envelope that opens is re-sealed as v2 (scrypt) on the\n * way out, secrets untouched.\n */\n async unlock(password: string): Promise<Uint8Array> {\n requirePassword(password)\n return this._exclusive(() => this._unlock(password))\n }\n\n private async _unlock(password: string): Promise<Uint8Array> {\n const envelope = await this._load()\n if (isEnvelopeV1(envelope)) {\n if (envelope.kdf.iterations < VAULT_MIN_ITERATIONS) throw new VaultError(`The vault's KDF (${envelope.kdf.iterations} iterations) is below the floor this build accepts.`, 'weak-kdf')\n const kek = await this._derivePbkdf2(password, fromBase64(envelope.kdf.salt), envelope.kdf.iterations)\n const dek = await this._proveOwn(await this._open(kek, envelope.dek, aadDekV1(envelope.kdf), 'wrong-password'), envelope)\n if (this._kdf === 'scrypt') {\n // Upgrade in place: same secrets, same createdAt, scrypt-wrapped DEK.\n const next = await this._sealEnvelope(password, dek, envelope.secrets, [], envelope.createdAt)\n await this._write(isEnvelopeV2(next) ? { ...next, upgradedAt: Date.now() } : next)\n }\n return dek\n }\n if (!isStrongScrypt(envelope.kdf)) throw new VaultError(`The vault's scrypt cost (N=${envelope.kdf.N} r=${envelope.kdf.r} p=${envelope.kdf.p}) is below the floor this build accepts.`, 'weak-kdf')\n const kek = await this._deriveScrypt(password, fromBase64(envelope.kdf.salt), envelope.kdf)\n return this._proveOwn(await this._open(kek, envelope.dek, aadDekV2(envelope.kdf), 'wrong-password'), envelope)\n }\n\n /**\n * A DEK unwrapped from a dek / passkey box must be the key this vault's secrets are sealed under\n * (audit 2026-11-09 E21): a box spliced in from another vault, under another password or passkey,\n * opens with that password but holds a foreign key. Proven with the DEK check, or — in an envelope\n * written before it — the first secret; an old empty envelope has nothing to prove it with. Returns\n * `dek`; on a mismatch zeroizes it and fails as `wrong-password` (the same failure as tampering).\n */\n private async _proveOwn(dek: Uint8Array, envelope: VaultEnvelope): Promise<Uint8Array> {\n if (envelope.dekCheck === undefined && Object.keys(envelope.secrets).length === 0) return dek\n try {\n await this._requireDek(dek, envelope)\n return dek\n } catch {\n zeroize(dek)\n throw new VaultError('Wrong password.', 'wrong-password')\n }\n }\n\n /**\n * Re-wrap the DEK under a new password (fresh salt, current KDF). Secrets and passkeys are untouched —\n * and so is the DEK: after a suspected compromise (a copied profile, a leaked session, a lost passkey)\n * this is not enough, because whoever holds the DEK still opens every secret, old and new. Use\n * {@link Vault.rotateVaultKey} then.\n */\n async changePassword(oldPassword: string, newPassword: string): Promise<void> {\n requirePassword(newPassword, VAULT_MIN_PASSWORD_LENGTH)\n requirePassword(oldPassword)\n return this._exclusive(async () => {\n const dek = await this._unlock(oldPassword)\n try {\n const envelope = await this._load()\n const passkeys = isEnvelopeV2(envelope) ? envelope.passkeys : []\n const next = await this._sealEnvelope(newPassword, dek, envelope.secrets, passkeys, envelope.createdAt)\n await this._write(isEnvelopeV2(envelope) && envelope.upgradedAt !== undefined && isEnvelopeV2(next) ? { ...next, upgradedAt: envelope.upgradedAt } : next)\n } finally {\n zeroize(dek)\n }\n })\n }\n\n /**\n * Replace the DEK (scan 2026-10-27 modules, F30): a fresh random DEK, every secret re-sealed under it,\n * the DEK wrapped under `password` with a fresh salt — written as one envelope, so a failure leaves the\n * old vault as it was. Returns the new DEK: hand it to `session.unlock(dek)`, which overwrites the old\n * one in `chrome.storage.session`. A DEK copied before the rotation opens nothing in the new envelope,\n * and {@link Vault.setSecret} refuses it, so a stale session cannot seal new secrets under it.\n *\n * Passkeys are dropped — their boxes hold the old DEK and cannot be re-wrapped without their PRF\n * output — and must be registered again ({@link Vault.addPasskey} with the new DEK).\n *\n * With `newPassword` this is also the password change: the new DEK is wrapped under `newPassword`\n * (at least {@link VAULT_MIN_PASSWORD_LENGTH} characters), and `password` must be the current one.\n */\n async rotateVaultKey(password: string, newPassword?: string): Promise<Uint8Array> {\n requirePassword(password)\n if (newPassword !== undefined) requirePassword(newPassword, VAULT_MIN_PASSWORD_LENGTH)\n return this._exclusive(async () => {\n const oldDek = await this._unlock(password)\n const dek = this._random(DEK_BYTES)\n try {\n const envelope = await this._load()\n const [oldKey, newKey] = await Promise.all([this._importDek(oldDek), this._importDek(dek)])\n const secrets: Record<string, SealedBox> = {}\n for (const [id, box] of Object.entries(envelope.secrets)) {\n const plaintext = await this._open(oldKey, box, aadSecret(id), 'locked')\n try {\n secrets[id] = await this._seal(newKey, plaintext, aadSecret(id))\n } finally {\n zeroize(plaintext)\n }\n }\n const next = await this._sealEnvelope(newPassword ?? password, dek, secrets, [], envelope.createdAt)\n const upgradedAt = isEnvelopeV2(envelope) ? envelope.upgradedAt : undefined\n await this._write(isEnvelopeV2(next) ? { ...next, ...(upgradedAt !== undefined ? { upgradedAt } : {}), rotatedAt: Date.now() } : next)\n return dek\n } catch (e) {\n zeroize(dek)\n throw e\n } finally {\n zeroize(oldDek)\n }\n })\n }\n\n // ---- passkeys (v2) ----\n\n /** Public view of the registered passkeys (ids, labels; whether each can verify assertions). */\n async listPasskeys(): Promise<Array<{ id: string; label: string; createdAt: number; canVerify: boolean }>> {\n const e = await this._storage.get()\n if (!e || !isEnvelopeV2(e)) return []\n return e.passkeys.map((p) => ({ id: p.id, label: p.label, createdAt: p.createdAt, canVerify: typeof p.publicKey === 'string' && p.alg === -7 }))\n }\n\n /** The SPKI public key (base64) of one passkey, for assertion verification; `null` when unknown. */\n async passkeyPublicKey(id: string): Promise<{ publicKey: string; alg: number } | null> {\n const e = await this._storage.get()\n if (!e || !isEnvelopeV2(e)) return null\n const p = e.passkeys.find((k) => k.id === id)\n return p?.publicKey && p.alg !== undefined ? { publicKey: p.publicKey, alg: p.alg } : null\n }\n\n /**\n * Register a passkey as a second unlock path: the DEK (from the unlocked session)\n * is sealed under HKDF-SHA256(`prf`, salt = credential id). The password stays\n * the recovery path; `prf` is zeroized here. A v1 envelope must be unlocked (and\n * thereby upgraded) first, and the vault must hold a secret (it proves the DEK).\n */\n async addPasskey(dek: Uint8Array, passkey: { id: string; prf: Uint8Array; label: string; publicKey?: string | undefined; alg?: number | undefined }): Promise<void> {\n try {\n requireId(passkey.id)\n if (passkey.prf.length !== PRF_BYTES) throw new VaultError(`A PRF output is ${PRF_BYTES} bytes.`, 'invalid-input')\n await this._exclusive(() => this._addPasskey(dek, passkey))\n } finally {\n zeroize(passkey.prf)\n }\n }\n\n private async _addPasskey(dek: Uint8Array, passkey: { id: string; prf: Uint8Array; label: string; publicKey?: string | undefined; alg?: number | undefined }): Promise<void> {\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) throw new VaultError('Unlock with the password once so the vault is upgraded before adding a passkey.', 'unsupported-envelope')\n if (envelope.passkeys.some((p) => p.id === passkey.id)) throw new VaultError('This passkey is already registered.', 'exists')\n // Prove the DEK is the vault's before sealing it under a new key.\n await this._requireDek(dek, envelope)\n const key = await this._derivePasskeyKek(passkey.prf, passkey.id)\n const entry: VaultPasskey = { id: passkey.id, label: passkey.label.slice(0, 64), createdAt: Date.now(), dek: await this._seal(key, dek, aadPasskey(passkey.id)) }\n if (passkey.publicKey && passkey.alg !== undefined) { entry.publicKey = passkey.publicKey; entry.alg = passkey.alg }\n await this._write({ ...envelope, passkeys: [...envelope.passkeys, entry] })\n }\n\n /** Unseal the DEK with a passkey's PRF output. `wrong-password` when the box does not open, `missing` when the id is unknown. */\n async unlockWithPasskey(id: string, prf: Uint8Array): Promise<Uint8Array> {\n try {\n requireId(id)\n if (prf.length !== PRF_BYTES) throw new VaultError(`A PRF output is ${PRF_BYTES} bytes.`, 'invalid-input')\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) throw new VaultError('This vault has no passkeys; unlock with the password.', 'missing')\n const entry = envelope.passkeys.find((p) => p.id === id)\n if (!entry) throw new VaultError('No such passkey on this vault.', 'missing')\n const key = await this._derivePasskeyKek(prf, id)\n return await this._proveOwn(await this._open(key, entry.dek, aadPasskey(id), 'wrong-password'), envelope)\n } finally {\n zeroize(prf)\n }\n }\n\n /** Forget one passkey's box. A DEK that passkey already unwrapped stays valid: after a lost or compromised passkey, {@link Vault.rotateVaultKey}. */\n async removePasskey(id: string): Promise<void> {\n requireId(id)\n return this._exclusive(async () => {\n const envelope = await this._load()\n if (!isEnvelopeV2(envelope)) return\n await this._write({ ...envelope, passkeys: envelope.passkeys.filter((p) => p.id !== id) })\n })\n }\n\n // ---- secrets ----\n\n async listSecretIds(): Promise<string[]> {\n const envelope = await this._storage.get()\n return envelope ? Object.keys(envelope.secrets) : []\n }\n\n /**\n * Seal `secret` under the DEK as `sourceId` (overwrites an entry with the same id). The DEK must open the\n * vault's secrets (`locked` otherwise): a key retired by {@link Vault.rotateVaultKey} never seals a new one.\n */\n async setSecret(dek: Uint8Array, sourceId: string, secret: Uint8Array): Promise<void> {\n requireId(sourceId)\n if (secret.length > VAULT_LIMITS.secretBytes) throw new VaultError(`A secret is at most ${VAULT_LIMITS.secretBytes} bytes.`, 'invalid-input')\n const key = await this._importDek(dek)\n return this._exclusive(async () => {\n const envelope = await this._load()\n // Only an envelope from before the DEK check, still empty, has nothing to prove the key with.\n if (envelope.dekCheck !== undefined || Object.keys(envelope.secrets).length > 0) await this._requireDek(dek, envelope)\n if (!(sourceId in envelope.secrets) && Object.keys(envelope.secrets).length >= VAULT_LIMITS.secrets) {\n throw new VaultError(`A vault holds at most ${VAULT_LIMITS.secrets} secrets.`, 'invalid-input')\n }\n const box = await this._seal(key, secret, aadSecret(sourceId))\n await this._write({ ...envelope, secrets: { ...envelope.secrets, [sourceId]: box } })\n })\n }\n\n /** Unseal one secret. `null` when the id is unknown; the caller zeroizes the result after use. */\n async getSecret(dek: Uint8Array, sourceId: string): Promise<Uint8Array | null> {\n requireId(sourceId)\n const envelope = await this._load()\n const box = envelope.secrets[sourceId]\n if (!box) return null\n const key = await this._importDek(dek)\n return this._open(key, box, aadSecret(sourceId), 'locked')\n }\n\n async deleteSecret(sourceId: string): Promise<void> {\n requireId(sourceId)\n return this._exclusive(async () => {\n const envelope = await this._load()\n if (!(sourceId in envelope.secrets)) return\n const secrets = { ...envelope.secrets }\n delete secrets[sourceId]\n await this._write({ ...envelope, secrets })\n })\n }\n\n /** Remove the whole vault. The explicit destructive flow only (back up → wipe → create). */\n async destroy(): Promise<void> {\n return this._exclusive(() => this._storage.clear())\n }\n\n // ---- serialized writes ----\n\n private _exclusive<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn)\n this._queue = run.catch(() => undefined)\n return run\n }\n\n /** Store an envelope this build will open again (bounds checked before it is written). */\n private async _write(envelope: VaultEnvelope): Promise<void> {\n const problem = envelopeProblem(envelope)\n if (problem) throw new VaultError(`The vault would exceed its limits (${problem}); nothing was written.`, 'invalid-input')\n await this._storage.set(envelope)\n }\n\n // ---- crypto ----\n\n private _random(n: number): Uint8Array {\n return this._crypto.getRandomValues(new Uint8Array(n))\n }\n\n /** A fresh envelope (v2 by default, v1 with `kdf: 'pbkdf2'`) wrapping `dek` under `password`. */\n private async _sealEnvelope(password: string, dek: Uint8Array, secrets: Record<string, SealedBox>, passkeys: VaultPasskey[], createdAt: number): Promise<VaultEnvelope> {\n const salt = this._random(SALT_BYTES)\n if (this._kdf === 'pbkdf2') {\n const kdf: VaultEnvelopeV1['kdf'] = { name: 'PBKDF2-SHA256', iterations: this._iterations, salt: toBase64(salt) }\n const kek = await this._derivePbkdf2(password, salt, this._iterations)\n return { v: 1, kdf, dek: await this._seal(kek, dek, aadDekV1(kdf)), secrets, dekCheck: await this._sealDekCheck(dek), createdAt }\n }\n const kdf: VaultEnvelopeV2['kdf'] = { name: 'scrypt', ...this._scrypt, salt: toBase64(salt) }\n const kek = await this._deriveScrypt(password, salt, kdf)\n return { v: 2, kdf, dek: await this._seal(kek, dek, aadDekV2(kdf)), secrets, dekCheck: await this._sealDekCheck(dek), passkeys, createdAt }\n }\n\n /** The DEK check box: {@link DEK_CHECK} sealed under `dek`. */\n private async _sealDekCheck(dek: Uint8Array): Promise<SealedBox> {\n return this._seal(await this._importDek(dek), new TextEncoder().encode(DEK_CHECK), AAD_DEK_CHECK)\n }\n\n /**\n * The caller's DEK must open this envelope's DEK check (or, in an envelope written before it, its\n * first secret) — it is the key the password protects, not any 32 bytes. An old empty envelope has\n * nothing to prove it with, so it is refused rather than trusted.\n */\n private async _requireDek(dek: Uint8Array, envelope: VaultEnvelope): Promise<void> {\n const ids = Object.keys(envelope.secrets)\n const key = await this._importDek(dek)\n if (envelope.dekCheck !== undefined) {\n const check = await this._open(key, envelope.dekCheck, AAD_DEK_CHECK, 'locked')\n const ok = new TextDecoder().decode(check) === DEK_CHECK\n zeroize(check)\n if (!ok) throw new VaultError('The vault key does not open this entry; lock and unlock again.', 'locked')\n return\n }\n if (ids.length === 0) throw new VaultError('Add a secret to the vault before a passkey: an empty vault cannot prove the key is its own.', 'invalid-input')\n const probe = await this._open(key, envelope.secrets[ids[0]!]!, aadSecret(ids[0]!), 'locked')\n zeroize(probe)\n }\n\n private async _derivePbkdf2(password: string, salt: Uint8Array, iterations: number): Promise<CryptoKey> {\n const subtle = this._crypto.subtle\n const pw = new TextEncoder().encode(password.normalize('NFKC'))\n let material: CryptoKey\n try {\n material = await withSecretBuffer(pw, (b) => subtle.importKey('raw', b, 'PBKDF2', false, ['deriveKey']))\n } finally {\n zeroize(pw)\n }\n return subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-256', salt: toArrayBuffer(salt), iterations }, material, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\n }\n\n private async _deriveScrypt(password: string, salt: Uint8Array, cost: { N: number; r: number; p: number }): Promise<CryptoKey> {\n const pw = new TextEncoder().encode(password.normalize('NFKC'))\n let raw: Uint8Array\n try {\n raw = await scryptAsync(pw, salt, { N: cost.N, r: cost.r, p: cost.p, dkLen: 32, maxmem: 2 * 128 * cost.N * cost.r + 1024 * 1024, ...(this._onProgress ? { onProgress: this._onProgress } : {}) })\n } finally {\n zeroize(pw)\n }\n try {\n return await withSecretBuffer(raw, (b) => this._crypto.subtle.importKey('raw', b, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']))\n } finally {\n zeroize(raw)\n }\n }\n\n /** HKDF-SHA256(ikm = PRF output, salt = credential id bytes, info) → AES-256-GCM key. */\n private async _derivePasskeyKek(prf: Uint8Array, credentialId: string): Promise<CryptoKey> {\n const subtle = this._crypto.subtle\n const ikm = await withSecretBuffer(prf, (b) => subtle.importKey('raw', b, 'HKDF', false, ['deriveKey']))\n return subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt: toArrayBuffer(fromBase64Url(credentialId)), info: toArrayBuffer(new TextEncoder().encode(HKDF_INFO)) }, ikm, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\n }\n\n private async _importDek(dek: Uint8Array): Promise<CryptoKey> {\n if (dek.length !== DEK_BYTES) throw new VaultError('Vault key must be 32 bytes.', 'invalid-input')\n return withSecretBuffer(dek, (b) => this._crypto.subtle.importKey('raw', b, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']))\n }\n\n private async _seal(key: CryptoKey, plaintext: Uint8Array, aad: string): Promise<SealedBox> {\n const iv = this._random(IV_BYTES)\n const ct = await withSecretBuffer(plaintext, (b) => this._crypto.subtle.encrypt({ name: 'AES-GCM', iv: toArrayBuffer(iv), additionalData: toArrayBuffer(new TextEncoder().encode(aad)) }, key, b))\n return { iv: toBase64(iv), data: toBase64(new Uint8Array(ct)) }\n }\n\n private async _open(key: CryptoKey, box: SealedBox, aad: string, onFail: 'wrong-password' | 'locked'): Promise<Uint8Array> {\n try {\n const pt = await this._crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: toArrayBuffer(fromBase64(box.iv)), additionalData: toArrayBuffer(new TextEncoder().encode(aad)) },\n key,\n toArrayBuffer(fromBase64(box.data)),\n )\n return new Uint8Array(pt)\n } catch {\n throw new VaultError(onFail === 'wrong-password' ? 'Wrong password.' : 'The vault key does not open this entry; lock and unlock again.', onFail)\n }\n }\n\n private async _load(): Promise<VaultEnvelope> {\n const envelope = await this._storage.get()\n if (!envelope) throw new VaultError('No vault in this storage area.', 'missing')\n if (!isEnvelopeV1(envelope) && !isEnvelopeV2(envelope)) throw new VaultError('Unsupported vault envelope.', 'unsupported-envelope')\n const problem = envelopeProblem(envelope)\n if (problem) throw new VaultError(`The vault envelope is outside the limits this build opens (${problem}).`, 'unsupported-envelope')\n return envelope\n }\n}\n\nexport function isEnvelopeV1(x: unknown): x is VaultEnvelopeV1 {\n if (typeof x !== 'object' || x === null) return false\n const e = x as Record<string, unknown>\n const kdf = e.kdf as Record<string, unknown> | undefined\n return (\n e.v === 1 &&\n typeof kdf === 'object' && kdf !== null && kdf.name === 'PBKDF2-SHA256' && Number.isInteger(kdf.iterations) && typeof kdf.salt === 'string' &&\n isBox(e.dek) &&\n typeof e.secrets === 'object' && e.secrets !== null && Object.values(e.secrets as object).every(isBox) &&\n (e.dekCheck === undefined || isBox(e.dekCheck))\n )\n}\n\nexport function isEnvelopeV2(x: unknown): x is VaultEnvelopeV2 {\n if (typeof x !== 'object' || x === null) return false\n const e = x as Record<string, unknown>\n const kdf = e.kdf as Record<string, unknown> | undefined\n return (\n e.v === 2 &&\n typeof kdf === 'object' && kdf !== null && kdf.name === 'scrypt' && Number.isInteger(kdf.N) && Number.isInteger(kdf.r) && Number.isInteger(kdf.p) && typeof kdf.salt === 'string' &&\n isBox(e.dek) &&\n typeof e.secrets === 'object' && e.secrets !== null && Object.values(e.secrets as object).every(isBox) &&\n (e.dekCheck === undefined || isBox(e.dekCheck)) &&\n Array.isArray(e.passkeys) && e.passkeys.every((p) => typeof p === 'object' && p !== null && typeof (p as VaultPasskey).id === 'string' && typeof (p as VaultPasskey).label === 'string' && isBox((p as VaultPasskey).dek))\n )\n}\n\nfunction isBox(x: unknown): x is SealedBox {\n return typeof x === 'object' && x !== null && typeof (x as SealedBox).iv === 'string' && typeof (x as SealedBox).data === 'string'\n}\n\nfunction isBoundedScrypt(c: { N: number; r: number; p: number }): boolean {\n return c.N <= VAULT_LIMITS.scrypt.N && c.r <= VAULT_LIMITS.scrypt.r && c.p <= VAULT_LIMITS.scrypt.p\n}\n\n/** Why an envelope is outside {@link VAULT_LIMITS}, or null when it is within them. */\nfunction envelopeProblem(e: VaultEnvelope): string | null {\n if (e.v === 1 && e.kdf.iterations > VAULT_LIMITS.iterations) return `PBKDF2 iterations ${e.kdf.iterations} > ${VAULT_LIMITS.iterations}`\n if (e.v === 2 && !isBoundedScrypt(e.kdf)) return `scrypt N=${e.kdf.N} r=${e.kdf.r} p=${e.kdf.p} above N=${VAULT_LIMITS.scrypt.N} r=${VAULT_LIMITS.scrypt.r} p=${VAULT_LIMITS.scrypt.p}`\n const secrets = Object.values(e.secrets)\n if (secrets.length > VAULT_LIMITS.secrets) return `${secrets.length} secrets > ${VAULT_LIMITS.secrets}`\n const passkeys = e.v === 2 ? e.passkeys : []\n if (passkeys.length > VAULT_LIMITS.passkeys) return `${passkeys.length} passkeys > ${VAULT_LIMITS.passkeys}`\n for (const box of [e.dek, ...(e.dekCheck ? [e.dekCheck] : []), ...secrets, ...passkeys.map((p) => p.dek)]) {\n if (box.iv.length > VAULT_LIMITS.boxChars || box.data.length > VAULT_LIMITS.boxChars) return `a sealed box above ${VAULT_LIMITS.boxChars} characters`\n }\n if (JSON.stringify(e).length > VAULT_LIMITS.envelopeChars) return `envelope above ${VAULT_LIMITS.envelopeChars} characters`\n return null\n}\n\nfunction isStrongScrypt(c: { N: number; r: number; p: number }): boolean {\n return Number.isInteger(c.N) && c.N >= VAULT_MIN_SCRYPT.N && (c.N & (c.N - 1)) === 0 && Number.isInteger(c.r) && c.r >= VAULT_MIN_SCRYPT.r && Number.isInteger(c.p) && c.p >= VAULT_MIN_SCRYPT.p\n}\n\nfunction requirePassword(password: string, minLength = 1): void {\n if (typeof password !== 'string' || password.length === 0) throw new VaultError('Password must not be empty.', 'invalid-input')\n if ([...password].length < minLength) throw new VaultError(`Password must be at least ${minLength} characters.`, 'invalid-input')\n}\n\nfunction requireId(id: string): void {\n if (typeof id !== 'string' || id.length === 0 || id.length > 128) throw new VaultError('Bad source id.', 'invalid-input')\n}\n\n/** base64url (WebAuthn ids) → bytes; plain base64 is accepted too. */\nexport function fromBase64Url(text: string): Uint8Array {\n const b64 = text.replace(/-/g, '+').replace(/_/g, '/')\n return fromBase64(b64 + '='.repeat((4 - (b64.length % 4)) % 4))\n}\n\nexport function toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Envelope in memory — tests and the smoke. */\nexport function memoryVaultStorage(initial: VaultEnvelope | null = null): VaultStorage & { envelope: VaultEnvelope | null } {\n const s = {\n envelope: initial,\n async get() { return s.envelope ? structuredClone(s.envelope) : null },\n async set(envelope: VaultEnvelope) { s.envelope = structuredClone(envelope) },\n async clear() { s.envelope = null },\n }\n return s\n}\n","// base64 for the JSON envelopes — `btoa`/`atob` exist in every extension context (service worker included).\n\nexport function toBase64(bytes: Uint8Array): string {\n let s = ''\n for (let i = 0; i < bytes.length; i += 0x8000) s += String.fromCharCode(...bytes.subarray(i, i + 0x8000))\n return btoa(s)\n}\n\nexport function fromBase64(text: string): Uint8Array {\n const s = atob(text)\n const out = new Uint8Array(s.length)\n for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i)\n return out\n}\n\nexport const utf8 = {\n encode: (text: string): Uint8Array => new TextEncoder().encode(text),\n decode: (bytes: Uint8Array): string => new TextDecoder().decode(bytes),\n}\n\n/** Copy into a fresh ArrayBuffer — WebCrypto rejects views over shared / offset buffers in some engines. */\nexport function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength)\n copy.set(bytes)\n return copy.buffer\n}\n\n/**\n * {@link toArrayBuffer} for a secret (a key, a password, a plaintext): `fn` gets the copy, which is\n * zero-filled afterwards whatever happens. WebCrypto copies its input when called, so wiping after\n * the returned promise settles is safe.\n */\nexport async function withSecretBuffer<T>(bytes: Uint8Array, fn: (buffer: ArrayBuffer) => Promise<T>): Promise<T> {\n const buffer = toArrayBuffer(bytes)\n try {\n return await fn(buffer)\n } finally {\n new Uint8Array(buffer).fill(0)\n }\n}\n","/**\n * The unlocked state. An MV3 service worker dies after ~30 s idle, so the\n * unlocked vault key cannot live in a JS variable: it lives in\n * `chrome.storage.session` (memory-only, cleared when the browser exits, readable\n * by extension contexts only) together with its expiry, and a `chrome.alarms`\n * alarm locks it when the auto-lock timer (default 15 min since the last\n * activity) runs out.\n *\n * The session never sees a password or a seed — only the DEK the vault returned.\n * The popup never receives the DEK either: it asks the service worker to\n * perform operations by id.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport { fromBase64, toBase64 } from './codec.js'\nimport { VaultError } from './errors.js'\n\n/** Structural `chrome.storage.session` (or any `StorageArea`); `memorySessionStorage()` for tests. */\nexport interface SessionStorage {\n get(key: string): Promise<unknown>\n set(key: string, value: unknown): Promise<void>\n remove(key: string): Promise<void>\n}\n\n/** Structural `chrome.alarms`: one named alarm, fired once at `when` (ms since epoch). */\nexport interface SessionAlarms {\n schedule(name: string, when: number): Promise<void> | void\n clear(name: string): Promise<void> | void\n /** Register the lock callback; the chrome adapter wires `chrome.alarms.onAlarm`. */\n onFire(handler: (name: string) => void): void\n}\n\nexport interface SessionOptions {\n storage: SessionStorage\n alarms: SessionAlarms\n /** Lock this long after the last `touch` / `unlock`. Default 15 min; 0 disables the timer (lock only on browser exit or explicit lock; stored as `expiresAt: null`). */\n autoLockMs?: number\n /** Storage key and alarm name prefix. */\n name?: string\n /** Clock, injectable for tests. */\n now?: () => number\n}\n\ninterface SessionRecord {\n key: string\n /** When the auto-lock fires (ms since epoch); `null` = no auto-lock. Never `Infinity`: chrome.storage stores JSON. */\n expiresAt: number | null\n}\n\nexport const SESSION_DEFAULT_AUTOLOCK_MS = 15 * 60_000\n\nexport class Session {\n private readonly _storage: SessionStorage\n private readonly _alarms: SessionAlarms\n private _autoLockMs: number\n private readonly _key: string\n private readonly _alarm: string\n private readonly _now: () => number\n private readonly _onLock = new Set<() => void>()\n /**\n * Every operation on the stored record runs here, one after another: a `touch` that read the\n * record before a `lock` removed it would otherwise write it back and undo the lock.\n */\n private _queue: Promise<unknown> = Promise.resolve()\n /** Bumped by every lock; a `touch` writes only when no lock happened since it read the record. */\n private _epoch = 0\n\n constructor(options: SessionOptions) {\n this._storage = options.storage\n this._alarms = options.alarms\n this._autoLockMs = options.autoLockMs ?? SESSION_DEFAULT_AUTOLOCK_MS\n const name = options.name ?? 'anywalletkit-session'\n this._key = name\n this._alarm = `${name}/autolock`\n this._now = options.now ?? Date.now\n this._alarms.onFire((fired) => { if (fired === this._alarm) void this.lock() })\n }\n\n /** Store the DEK and arm the auto-lock. The caller's copy is zeroized. */\n async unlock(dek: Uint8Array): Promise<void> {\n if (dek.length !== 32) throw new VaultError('Vault key must be 32 bytes.', 'invalid-input')\n return this._serial(async () => {\n const expiresAt = this._expiry()\n await this._storage.set(this._key, { key: toBase64(dek), expiresAt } satisfies SessionRecord)\n zeroize(dek)\n await this._arm(expiresAt)\n })\n }\n\n /** Forget the DEK and cancel the alarm. Safe to call when already locked. */\n async lock(): Promise<void> {\n return this._serial(() => this._lockNow())\n }\n\n async isUnlocked(): Promise<boolean> {\n return this._serial(async () => (await this._read()) !== null)\n }\n\n /**\n * The DEK for one operation (zeroize it after). `locked` when there is none or the\n * timer ran out while the worker was asleep — the record is then removed as well, so\n * a missed alarm cannot keep the key alive.\n */\n async getKey(): Promise<Uint8Array> {\n return this._serial(async () => {\n const record = await this._read()\n if (!record) throw new VaultError('Wallet is locked.', 'locked')\n return fromBase64(record.key)\n })\n }\n\n /**\n * User activity: push the auto-lock out again. No-op when locked. Call it for explicit user\n * gestures only (unlock, send, approve / decline, an action in the wallet's own UI) — not for\n * passive polls, page requests or worker restarts, or the timer never runs out.\n */\n async touch(): Promise<void> {\n return this._serial(async () => {\n const epoch = this._epoch\n const record = await this._read()\n if (!record || epoch !== this._epoch) return\n const expiresAt = this._expiry()\n await this._storage.set(this._key, { ...record, expiresAt } satisfies SessionRecord)\n await this._arm(expiresAt)\n })\n }\n\n get autoLockMs(): number {\n return this._autoLockMs\n }\n\n /**\n * Set the timer period (0 disables). Never pushes the deadline out — call this at every worker\n * start with the stored setting: it re-arms the alarm at the stored deadline (a restart must not\n * count as activity, audit 2026-11-09 E11), and only brings the deadline forward when the new\n * period ends sooner. A longer period (or 0) applies from the next {@link Session.touch} /\n * {@link Session.unlock}; call `touch()` right after when the user changed it explicitly.\n */\n async setAutoLockMs(ms: number): Promise<void> {\n if (!Number.isFinite(ms) || ms < 0) throw new VaultError('Auto-lock must be a non-negative number of milliseconds.', 'invalid-input')\n this._autoLockMs = ms\n return this._serial(async () => {\n const epoch = this._epoch\n const record = await this._read()\n if (!record || epoch !== this._epoch) return\n const cap = this._expiry()\n const expiresAt = cap !== null && (record.expiresAt === null || cap < record.expiresAt) ? cap : record.expiresAt\n if (expiresAt !== record.expiresAt) await this._storage.set(this._key, { ...record, expiresAt } satisfies SessionRecord)\n await this._arm(expiresAt)\n })\n }\n\n onLock(callback: () => void): () => void {\n this._onLock.add(callback)\n return () => this._onLock.delete(callback)\n }\n\n private _serial<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn)\n this._queue = run.catch(() => undefined)\n return run\n }\n\n /** The lock itself; callers are already in the queue. */\n private async _lockNow(): Promise<void> {\n this._epoch++\n const was = await this._storage.get(this._key)\n await this._storage.remove(this._key)\n await this._alarms.clear(this._alarm)\n if (was !== undefined && was !== null) for (const cb of this._onLock) cb()\n }\n\n private _expiry(): number | null {\n return this._autoLockMs > 0 ? this._now() + this._autoLockMs : null\n }\n\n private async _arm(expiresAt: number | null): Promise<void> {\n if (expiresAt !== null) await this._alarms.schedule(this._alarm, expiresAt)\n else await this._alarms.clear(this._alarm)\n }\n\n /** The stored record, or `null` when locked. A record that is there but unreadable locks the wallet (removed, listeners told). */\n private async _read(): Promise<SessionRecord | null> {\n const raw = await this._storage.get(this._key)\n if (raw === undefined || raw === null) return null\n const r = raw as Partial<SessionRecord>\n const expiryOk = r.expiresAt === null || (typeof r.expiresAt === 'number' && Number.isFinite(r.expiresAt))\n if (typeof raw !== 'object' || typeof r.key !== 'string' || !expiryOk || !isKey(r.key)) { await this._lockNow(); return null }\n if (r.expiresAt !== null && r.expiresAt! <= this._now()) { await this._lockNow(); return null }\n return r as SessionRecord\n }\n}\n\n/** A stored DEK: base64 of exactly 32 bytes (the decoded copy is wiped). */\nfunction isKey(text: string): boolean {\n let bytes: Uint8Array\n try { bytes = fromBase64(text) } catch { return false }\n const ok = bytes.length === 32\n zeroize(bytes)\n return ok\n}\n\n/** In-memory `chrome.storage.session` stand-in. */\nexport function memorySessionStorage(): SessionStorage & { data: Map<string, unknown> } {\n const data = new Map<string, unknown>()\n return {\n data,\n async get(key) { return data.get(key) },\n async set(key, value) { data.set(key, structuredClone(value)) },\n async remove(key) { data.delete(key) },\n }\n}\n\n/** In-memory alarms: `fire(name)` from the test, `pending` to inspect. */\nexport function memoryAlarms(): SessionAlarms & { pending: Map<string, number>; fire(name: string): void } {\n const pending = new Map<string, number>()\n const handlers = new Set<(name: string) => void>()\n return {\n pending,\n schedule(name, when) { pending.set(name, when) },\n clear(name) { pending.delete(name) },\n onFire(handler) { handlers.add(handler) },\n fire(name) { pending.delete(name); for (const h of handlers) h(name) },\n }\n}\n","/**\n * Message shapes on the two hops between a dApp and the wallet:\n *\n * ```text\n * page (injected provider, MAIN world)\n * │ window.postMessage — PageRequest ⇄ PageResponse / PageEvent\n * content script (isolated world) — stamps `location.origin`, owns the port\n * │ chrome.runtime.connect(PORT_NAME) — RelayRequest ⇄ RelayResponse / RelayEvent\n * service worker — trusts `port.sender` (set by the browser), never the page\n * ```\n *\n * The page can forge anything it posts, so a page message carries no origin and\n * no identity: the content script adds the origin, and the service worker\n * cross-checks it against `port.sender.origin` ({@link checkSenderOrigin}) — a\n * mismatch is dropped, not answered. Request ids are opaque strings minted by\n * the page side ({@link newRequestId}); the content script does not reuse them\n * across ports.\n */\n\n/** `chrome.runtime.connect({ name })` for content-script ports. */\nexport const PORT_NAME = 'anywalletkit/relay/1'\n/** `window.postMessage` discriminators (both directions). */\nexport const PAGE_TARGET = { toContent: 'anywalletkit/content', toPage: 'anywalletkit/page' } as const\n\n/** CAIP-2 namespace of the provider that spoke. */\nexport type RelayChain = 'eip155' | 'solana' | 'ton' | 'tron' | 'bip122' | 'near'\n\nexport interface RelayError {\n /** EIP-1193 / EIP-1474 numbering for EVM; the same numbers are reused for the other providers. */\n code: number\n message: string\n data?: unknown\n}\n\nexport const RELAY_ERRORS = {\n userRejected: 4001,\n unauthorized: 4100,\n unsupportedMethod: 4200,\n disconnected: 4900,\n chainDisconnected: 4901,\n /** EIP-3326/3085: the chain is not in the wallet (`wallet_switchEthereumChain` → suggest `wallet_addEthereumChain`). */\n chainNotAdded: 4902,\n internal: -32603,\n invalidRequest: -32600,\n invalidParams: -32602,\n /** EIP-1474: a request of the same kind from this origin is already waiting (MetaMask's \"already pending\"). */\n resourceUnavailable: -32002,\n /** EIP-1474: this origin has too many requests waiting. */\n limitExceeded: -32005,\n} as const\n\n// ---- hop 1: page ⇄ content script ----\n\nexport interface PageRequest {\n target: typeof PAGE_TARGET.toContent\n id: string\n chain: RelayChain\n method: string\n params?: unknown\n}\n\nexport interface PageResponse {\n target: typeof PAGE_TARGET.toPage\n id: string\n result?: unknown\n error?: RelayError\n}\n\nexport interface PageEvent {\n target: typeof PAGE_TARGET.toPage\n chain: RelayChain\n event: string\n data?: unknown\n}\n\n// ---- hop 2: content script ⇄ service worker ----\n\nexport interface RelayRequest {\n kind: 'request'\n id: string\n /** `location.origin` of the page, stamped by the content script. */\n origin: string\n chain: RelayChain\n method: string\n params?: unknown\n}\n\nexport interface RelayResponse {\n kind: 'response'\n id: string\n result?: unknown\n error?: RelayError\n}\n\nexport interface RelayEvent {\n kind: 'event'\n chain: RelayChain\n event: string\n data?: unknown\n}\n\nexport type RelayToWorker = RelayRequest\nexport type RelayToContent = RelayResponse | RelayEvent\n\n// ---- guards ----\n\nconst CHAINS: ReadonlySet<string> = new Set<RelayChain>(['eip155', 'solana', 'ton', 'tron', 'bip122', 'near'])\n\nconst isRecord = (x: unknown): x is Record<string, unknown> => typeof x === 'object' && x !== null\nconst isId = (x: unknown): x is string => typeof x === 'string' && x.length > 0 && x.length <= 64\n/** Longest method name a request may carry. */\nexport const RELAY_METHOD_MAX = 128\n/**\n * A method name as the providers spell them (`eth_sendTransaction`, `signAndSendTransaction`,\n * `tron_requestAccounts`): letters, digits and `_`, at most {@link RELAY_METHOD_MAX}. Anything else\n * is dropped at the relay, so a megabyte \"method\" never reaches a regex, a log or an error message\n * (scan 2026-10-27 modules, F5).\n */\nexport const isRelayMethod = (x: unknown): x is string => typeof x === 'string' && x.length > 0 && x.length <= RELAY_METHOD_MAX && /^[A-Za-z0-9_]+$/.test(x)\n\nexport function isPageRequest(x: unknown): x is PageRequest {\n return isRecord(x) && x.target === PAGE_TARGET.toContent && isId(x.id) && CHAINS.has(x.chain as string) && isRelayMethod(x.method)\n}\n\nexport function isPageResponse(x: unknown): x is PageResponse {\n return isRecord(x) && x.target === PAGE_TARGET.toPage && isId(x.id)\n}\n\nexport function isPageEvent(x: unknown): x is PageEvent {\n return isRecord(x) && x.target === PAGE_TARGET.toPage && !('id' in x) && CHAINS.has(x.chain as string) && typeof x.event === 'string'\n}\n\nexport function isRelayRequest(x: unknown): x is RelayRequest {\n return isRecord(x) && x.kind === 'request' && isId(x.id) && typeof x.origin === 'string' && CHAINS.has(x.chain as string) && isRelayMethod(x.method)\n}\n\nexport function isRelayToContent(x: unknown): x is RelayToContent {\n return isRecord(x) && ((x.kind === 'response' && isId(x.id)) || (x.kind === 'event' && typeof x.event === 'string'))\n}\n\nexport function newRequestId(): string {\n return crypto.randomUUID()\n}\n\n/** What a content script's `message` listener receives (structural `MessageEvent`). */\nexport interface PageMessageEvent { data: unknown; origin: string; source: unknown }\n/** The page window the content script shares (structural `window`). */\nexport interface PageWindow { location: { origin: string } }\n\n/**\n * The page's own request, or `null`. A content script must take only messages the page itself\n * posted — `event.source` is the page window and `event.origin` its origin — or an iframe on the\n * page (an ad, an embed) would have its `parent.postMessage` stamped with the site's origin and\n * shown in the approval window as the site (round 3, H6).\n */\nexport function pageRequestFrom(event: PageMessageEvent, page: PageWindow): PageRequest | null {\n if (event.source !== page || event.origin !== page.location.origin) return null\n return isPageRequest(event.data) ? event.data : null\n}\n\n/** The content script's stamp: {@link PageRequest} + the page origin. */\nexport function stampOrigin(request: PageRequest, origin: string): RelayRequest {\n const { id, chain, method } = request\n return 'params' in request ? { kind: 'request', id, origin, chain, method, params: request.params } : { kind: 'request', id, origin, chain, method }\n}\n\n/** What `port.sender` looks like (structural `chrome.runtime.MessageSender`). */\nexport interface PortSender {\n origin?: string | undefined\n url?: string | undefined\n tab?: { id?: number | undefined } | undefined\n frameId?: number | undefined\n}\n\n/**\n * The service worker's check before it believes a stamped origin: it must equal the\n * origin the browser recorded for the port. Returns the trusted origin or `null`.\n */\nexport function checkSenderOrigin(sender: PortSender | undefined, stamped: string): string | null {\n const fromSender = sender?.origin ?? (sender?.url ? safeOrigin(sender.url) : undefined)\n if (!fromSender || fromSender === 'null') return null\n return fromSender === stamped ? fromSender : null\n}\n\nfunction safeOrigin(url: string): string | undefined {\n try { return new URL(url).origin } catch { return undefined }\n}\n\nexport const relayError = (code: number, message: string, data?: unknown): RelayError => (data === undefined ? { code, message } : { code, message, data })\n","/**\n * Adapters over the `chrome.*` APIs, typed structurally so this package needs no\n * `@types/chrome` and tests can pass fakes. Promise forms (MV3) only.\n */\nimport type { SessionAlarms, SessionStorage } from './session.js'\nimport type { VaultEnvelope, VaultStorage } from './vault.js'\n\nexport interface StorageAreaLike {\n get(keys: string | string[]): Promise<Record<string, unknown>>\n set(items: Record<string, unknown>): Promise<void>\n remove(keys: string | string[]): Promise<void>\n /** `chrome.storage.session` only. */\n setAccessLevel?(options: { accessLevel: 'TRUSTED_CONTEXTS' | 'TRUSTED_AND_UNTRUSTED_CONTEXTS' }): Promise<void>\n}\n\nexport interface AlarmsLike {\n create(name: string, info: { when: number }): Promise<void> | void\n clear(name: string): Promise<boolean> | boolean | void\n onAlarm: { addListener(callback: (alarm: { name: string }) => void): void }\n}\n\n/** Stable storage key: existing vaults live under it — never rename. */\nexport const VAULT_STORAGE_KEY = 'forgewallet.vault.v1'\n\n/** The encrypted envelope in `chrome.storage.local` (survives browser restarts; ciphertext only). */\nexport function chromeLocalVaultStorage(area: StorageAreaLike, key = VAULT_STORAGE_KEY): VaultStorage {\n return {\n async get() { const r = await area.get(key); return (r[key] as VaultEnvelope | undefined) ?? null },\n async set(envelope) { await area.set({ [key]: envelope }) },\n async clear() { await area.remove(key) },\n }\n}\n\n/**\n * `chrome.storage.session`: memory-only, gone when the browser exits. Access is\n * pinned to trusted contexts (the default; made explicit so a content script can\n * never read the unlocked key even if a later change opens the area to them).\n */\nexport function chromeSessionStorage(area: StorageAreaLike): SessionStorage {\n const ready = area.setAccessLevel ? area.setAccessLevel({ accessLevel: 'TRUSTED_CONTEXTS' }) : Promise.resolve()\n return {\n async get(key) { await ready; return (await area.get(key))[key] },\n async set(key, value) { await ready; await area.set({ [key]: value }) },\n async remove(key) { await ready; await area.remove(key) },\n }\n}\n\n/** `chrome.alarms` as one-shot named alarms. Chrome rounds alarms to ≥ 30 s in packed extensions. */\nexport function chromeAlarms(alarms: AlarmsLike): SessionAlarms {\n return {\n async schedule(name, when) { await alarms.create(name, { when }) },\n async clear(name) { await alarms.clear(name) },\n onFire(handler) { alarms.onAlarm.addListener((alarm) => handler(alarm.name)) },\n }\n}\n","/**\n * `@anywalletkit/keyring` adapters for the extension. The keyring stores public\n * metadata (names, addresses, flags) through `KeyringStorage` and one secret per\n * key source through `SecretStorage`:\n *\n * - {@link chromeKeyringStorage}: the metadata as plain JSON in `chrome.storage.local`;\n * - {@link vaultSecretStorage}: every secret sealed in the {@link Vault} under the\n * DEK the {@link Session} holds. Each call fetches the DEK, uses it once and\n * zeroizes it; a locked session surfaces as `VaultError('locked')`, which the\n * service worker turns into \"unlock first\" for the UI.\n *\n * The keyring's secret strings (JSON with the mnemonic) are immutable JS values\n * and cannot be zeroized; the keyring reads one per operation and drops it, so\n * their lifetime is one call. The byte buffers this module owns are zeroized.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport type { KeyringState, KeyringStorage, SecretStorage } from '@anywalletkit/keyring'\nimport type { StorageAreaLike } from './chrome.js'\nimport { utf8 } from './codec.js'\nimport type { Session } from './session.js'\nimport type { Vault } from './vault.js'\n\n/** Stable storage key: existing keyrings live under it — never rename. */\nexport const KEYRING_STORAGE_KEY = 'forgewallet.keyring.v1'\n\n/** Keyring metadata (no secrets) in `chrome.storage.local`. */\nexport function chromeKeyringStorage(area: StorageAreaLike, key = KEYRING_STORAGE_KEY): KeyringStorage {\n return {\n async load() { const r = await area.get(key); return (r[key] as KeyringState | undefined) ?? null },\n async save(state) { await area.set({ [key]: state }) },\n }\n}\n\n/** Keyring secrets sealed in the vault; readable only while the session is unlocked. */\nexport function vaultSecretStorage(vault: Vault, session: Session): SecretStorage {\n const withKey = async <T>(fn: (dek: Uint8Array) => Promise<T>): Promise<T> => {\n const dek = await session.getKey()\n try { return await fn(dek) } finally { zeroize(dek) }\n }\n return {\n async get(sourceId) {\n return withKey(async (dek) => {\n const bytes = await vault.getSecret(dek, sourceId)\n if (!bytes) return null\n try { return utf8.decode(bytes) } finally { zeroize(bytes) }\n })\n },\n async set(sourceId, secret) {\n const bytes = utf8.encode(secret)\n try { await withKey((dek) => vault.setSecret(dek, sourceId, bytes)) } finally { zeroize(bytes) }\n },\n async delete(sourceId) {\n await vault.deleteSecret(sourceId)\n },\n }\n}\n","/**\n * Default EVM networks for an extension built on this kit: the chains Vaulty's in-app\n * browser can read and sign on, with the same public RPC failover lists\n * (`mobile/lib/swap2.ts`), no API keys. A wallet build may prepend its own\n * endpoints; `wallet_addEthereumChain` may add a chain the asset catalog\n * (`@anywalletkit/swap2-assets`) knows — an unknown chain id is refused, so a\n * site cannot point the wallet at a look-alike network.\n */\nimport { isPublicHttpsUrl } from '@anywalletkit/networks/url'\nimport { ccChain } from '@anywalletkit/swap2-assets'\nimport { RELAY_ERRORS, relayError, type RelayError } from './relay.js'\nimport type { JsonStorage } from './storage.js'\n\nexport interface EvmNetwork {\n /** CAIP-2, `eip155:<chainId>`. */\n caip2: string\n chainId: number\n name: string\n /** Native currency symbol, 18 decimals on every chain here (on Arc that is the 18-decimal native view of USDC). */\n symbol: string\n /** Tried in order; the client fails over. */\n rpcs: string[]\n explorer?: string\n /** Set when a SITE supplied the RPC list (wallet_addEthereumChain): every sheet on this network says so and simulations are not trusted. */\n custom?: { origin: string; addedAt: number }\n}\n\nexport const DEFAULT_CHAIN = 'eip155:1'\n\nconst net = (chainId: number, name: string, symbol: string, rpcs: string[], explorer?: string): EvmNetwork =>\n explorer === undefined ? { caip2: `eip155:${chainId}`, chainId, name, symbol, rpcs } : { caip2: `eip155:${chainId}`, chainId, name, symbol, rpcs, explorer }\n\nexport const DEFAULT_NETWORKS: readonly EvmNetwork[] = Object.freeze([\n net(1, 'Ethereum', 'ETH', ['https://ethereum-rpc.publicnode.com', 'https://eth.drpc.org'], 'https://etherscan.io'),\n net(8453, 'Base', 'ETH', ['https://base-rpc.publicnode.com', 'https://mainnet.base.org', 'https://base.drpc.org'], 'https://basescan.org'),\n net(56, 'BNB Chain', 'BNB', ['https://bsc-rpc.publicnode.com', 'https://bsc-dataseed.bnbchain.org', 'https://bsc.drpc.org'], 'https://bscscan.com'),\n net(42161, 'Arbitrum', 'ETH', ['https://arbitrum-one-rpc.publicnode.com', 'https://arb1.arbitrum.io/rpc', 'https://arbitrum.drpc.org'], 'https://arbiscan.io'),\n net(10, 'Optimism', 'ETH', ['https://optimism-rpc.publicnode.com', 'https://mainnet.optimism.io', 'https://optimism.drpc.org'], 'https://optimistic.etherscan.io'),\n net(137, 'Polygon', 'POL', ['https://polygon-bor-rpc.publicnode.com', 'https://polygon.drpc.org'], 'https://polygonscan.com'),\n net(43114, 'Avalanche', 'AVAX', ['https://avalanche-c-chain-rpc.publicnode.com', 'https://api.avax.network/ext/bc/C/rpc', 'https://avalanche.drpc.org'], 'https://snowtrace.io'),\n net(999, 'HyperEVM', 'HYPE', ['https://rpc.hyperliquid.xyz/evm', 'https://hyperliquid.drpc.org', 'https://hyperliquid-json-rpc.stakely.io']),\n net(4663, 'Robinhood Chain', 'ETH', ['https://rpc.mainnet.chain.robinhood.com', 'https://robinhood.drpc.org'], 'https://robinhoodchain.blockscout.com'),\n net(324, 'zkSync Era', 'ETH', ['https://mainnet.era.zksync.io', 'https://zksync.drpc.org'], 'https://era.zksync.network'),\n net(42220, 'Celo', 'CELO', ['https://forno.celo.org', 'https://celo.drpc.org'], 'https://celoscan.io'),\n net(4326, 'MegaETH', 'ETH', ['https://mainnet.megaeth.com/rpc']),\n net(130, 'Unichain', 'ETH', ['https://mainnet.unichain.org', 'https://unichain-rpc.publicnode.com'], 'https://uniscan.xyz'),\n net(143, 'Monad', 'MON', ['https://rpc.monad.xyz']),\n // Second operator (Tenderly's public gateway, keyless): rpc.plasma.to alone cannot satisfy a two-operator check.\n net(9745, 'Plasma', 'XPL', ['https://rpc.plasma.to', 'https://plasma.gateway.tenderly.co']),\n net(59144, 'Linea', 'ETH', ['https://rpc.linea.build', 'https://linea-rpc.publicnode.com'], 'https://lineascan.build'),\n net(100, 'Gnosis', 'xDAI', ['https://rpc.gnosischain.com', 'https://gnosis-rpc.publicnode.com'], 'https://gnosisscan.io'),\n net(146, 'Sonic', 'S', ['https://rpc.soniclabs.com', 'https://sonic-rpc.publicnode.com'], 'https://sonicscan.org'),\n net(480, 'World Chain', 'ETH', ['https://worldchain-mainnet.g.alchemy.com/public', 'https://worldchain-mainnet.gateway.tenderly.co'], 'https://worldscan.org'),\n net(1329, 'Sei', 'SEI', ['https://evm-rpc.sei-apis.com'], 'https://seitrace.com'),\n net(57073, 'Ink', 'ETH', ['https://rpc-gel.inkonchain.com'], 'https://explorer.inkonchain.com'),\n net(98866, 'Plume', 'PLUME', ['https://rpc.plume.org'], 'https://explorer.plume.org'),\n net(196, 'X Layer', 'OKB', ['https://rpc.xlayer.tech', 'https://xlayerrpc.okx.com'], 'https://www.okx.com/web3/explorer/xlayer'),\n net(534352, 'Scroll', 'ETH', ['https://rpc.scroll.io', 'https://scroll-rpc.publicnode.com'], 'https://scrollscan.com'),\n net(80094, 'Berachain', 'BERA', ['https://rpc.berachain.com', 'https://berachain-rpc.publicnode.com'], 'https://berascan.com'),\n // Arc (Circle's L1): the gas token is USDC. eth_getBalance / msg.value / gas are accounted in 18-decimal units (the\n // `symbol` here names that native view); the ERC-20 interface at 0x3600…0000 reads the SAME balance in 6 decimals\n // and is what the catalog, LI.FI and CCTP address (see swap2-assets). Balances must show one view, not both.\n net(5042, 'Arc', 'USDC', ['https://rpc.mainnet.arc.io'], 'https://explorer.arc.io'),\n net(5000, 'Mantle', 'MNT', ['https://rpc.mantle.xyz', 'https://mantle-rpc.publicnode.com'], 'https://mantlescan.xyz'),\n net(747474, 'Katana', 'ETH', ['https://rpc.katana.network'], 'https://explorer.katanarpc.com'),\n net(2818, 'Morph', 'ETH', ['https://rpc.morphl2.io', 'https://rpc-quicknode.morphl2.io'], 'https://explorer.morphl2.io'),\n net(14, 'Flare', 'FLR', ['https://flare-api.flare.network/ext/C/rpc', 'https://flare.rpc.thirdweb.com'], 'https://flare-explorer.flare.network'),\n // Elysium by Kinetiq (chain 99901, HYPE gas; Arbitrum Orbit on HyperEVM) — public RPC and explorer checked 2026-11-10.\n // The explorer value is the link base (<root>/tx/<hash>, <root>/address/<a>), not LI.FI's blockExplorerUrls\n // https://elysium.kinetiq.xyz/explorer/ (the overview page; the bare root is the Elysium site home).\n net(99901, 'Elysium', 'HYPE', ['https://rpc.elysium.kinetiq.xyz'], 'https://elysium.kinetiq.xyz'),\n])\n\nexport const chainHex = (caip2: string): string => `0x${Number(caip2.split(':')[1]).toString(16)}`\n\n/** `0x1` / `1` → `eip155:1`; `null` for anything that is not a positive integer chain id. */\nexport function caip2FromChainId(value: unknown): string | null {\n let n: number\n if (typeof value === 'string') {\n const s = value.trim()\n if (/^0x[0-9a-f]+$/i.test(s)) n = Number.parseInt(s, 16)\n else if (/^[0-9]+$/.test(s)) n = Number.parseInt(s, 10)\n else return null\n } else if (typeof value === 'number') n = value\n else return null\n return Number.isSafeInteger(n) && n > 0 ? `eip155:${n}` : null\n}\n\n/** Whether the asset catalog knows this chain — the gate for `wallet_addEthereumChain`. */\nexport function isCatalogChain(caip2: string): boolean {\n return ccChain(caip2) !== undefined\n}\n\n/**\n * Shipped networks plus the ones the user accepted from sites, persisted. Lookup\n * by CAIP-2; a custom entry for a shipped chain is ignored (the build's RPC list\n * wins — a site must not be able to replace Ethereum's endpoints).\n */\nexport class NetworksTable {\n private _custom: EvmNetwork[] | null = null\n private _loading: Promise<EvmNetwork[]> | null = null\n /** add/remove run one after another (scan F22, as PermissionStore). */\n private _queue: Promise<unknown> = Promise.resolve()\n\n constructor(private readonly storage: JsonStorage<EvmNetwork[]>, private readonly defaults: readonly EvmNetwork[] = DEFAULT_NETWORKS) {}\n\n async list(): Promise<EvmNetwork[]> {\n return [...this.defaults, ...(await this.custom())]\n }\n\n async get(caip2: string): Promise<EvmNetwork | null> {\n return this.defaults.find((n) => n.caip2 === caip2) ?? (await this.custom()).find((n) => n.caip2 === caip2) ?? null\n }\n\n add(network: EvmNetwork): Promise<void> {\n return this.serialize(async () => {\n if (this.defaults.some((n) => n.caip2 === network.caip2)) return\n const custom = (await this.custom()).filter((n) => n.caip2 !== network.caip2)\n custom.push(network)\n await this.write(custom)\n })\n }\n\n remove(caip2: string): Promise<void> {\n return this.serialize(async () => {\n const current = await this.custom()\n if (!current.some((n) => n.caip2 === caip2)) return\n await this.write(current.filter((n) => n.caip2 !== caip2))\n })\n }\n\n private serialize<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n /** Cache first (readers see it at once), rolled back when storage refuses. */\n private async write(custom: EvmNetwork[]): Promise<void> {\n const prev = await this.custom()\n this._custom = custom\n try {\n await this.storage.set(custom)\n } catch (e) {\n if (this._custom === custom) this._custom = prev\n throw e\n }\n }\n\n private async custom(): Promise<EvmNetwork[]> {\n if (this._custom) return this._custom\n this._loading ??= this.storage.get().then(\n (s) => (this._custom ??= s ?? []),\n (e: unknown) => { this._loading = null; throw e },\n )\n return this._loading\n }\n\n /**\n * Forget the cached table: the next read asks storage again. For a storage whose answer changes under\n * the table — e.g. one that only hands out the user's networks once the wallet is unlocked.\n */\n reload(): Promise<void> {\n return this.serialize(async () => {\n await this._loading?.catch(() => undefined)\n this._custom = null\n this._loading = null\n })\n }\n}\n\n/**\n * A site must not point the wallet's RPC reads at the user's own network: an RPC URL from a page is\n * kept only when it is https on a public host, with `isPublicHttpsUrl` from `@anywalletkit/networks`\n * (every IPv4 spelling, CGNAT, link-local, mapped IPv6 and `*.local` names included; scan 2026-10-27\n * modules, F37).\n */\nconst isSiteRpcUrl = (u: unknown): u is string => typeof u === 'string' && u.length <= 2048 && isPublicHttpsUrl(u)\n\n/**\n * EIP-3085 `wallet_addEthereumChain` parameter → {@link EvmNetwork}, or the error\n * to answer with. Public https RPC urls only (a private / local host is dropped); the chain id\n * must be in the catalog.\n */\nexport function parseAddChainParams(params: unknown, known: (caip2: string) => boolean = isCatalogChain): EvmNetwork | RelayError {\n const p = (Array.isArray(params) ? params[0] : params) as Record<string, unknown> | undefined\n if (!p || typeof p !== 'object') return relayError(RELAY_ERRORS.invalidParams, 'wallet_addEthereumChain expects one object parameter.')\n const caip2 = caip2FromChainId(p.chainId)\n if (!caip2) return relayError(RELAY_ERRORS.invalidParams, 'chainId must be a 0x-prefixed hex string.')\n if (!known(caip2)) return relayError(RELAY_ERRORS.chainNotAdded, `Chain ${String(p.chainId)} is not in this wallet's catalog.`)\n const rpcs = Array.isArray(p.rpcUrls) ? p.rpcUrls.filter(isSiteRpcUrl) : []\n if (rpcs.length === 0) return relayError(RELAY_ERRORS.invalidParams, 'rpcUrls must contain at least one public https URL (a site cannot add a private / local endpoint).')\n const name = typeof p.chainName === 'string' && p.chainName.trim() ? p.chainName.trim().slice(0, 64) : caip2\n const currency = p.nativeCurrency as { symbol?: unknown; decimals?: unknown } | undefined\n if (currency && currency.decimals !== undefined && currency.decimals !== 18) return relayError(RELAY_ERRORS.invalidParams, 'nativeCurrency.decimals must be 18.')\n const symbol = typeof currency?.symbol === 'string' && /^[A-Za-z0-9]{1,12}$/.test(currency.symbol) ? currency.symbol : 'ETH'\n const explorers = Array.isArray(p.blockExplorerUrls) ? p.blockExplorerUrls.filter((u): u is string => typeof u === 'string' && /^https:\\/\\//i.test(u)) : []\n const network: EvmNetwork = { caip2, chainId: Number(caip2.split(':')[1]), name, symbol, rpcs }\n return explorers[0] ? { ...network, explorer: explorers[0] } : network\n}\n\n// ---- non-EVM chains: the CAIP-2 ids the asset catalog / swap2 engine use, and public endpoints only (Vaulty's lists minus its proxies) ----\n\n/** Solana mainnet as the catalog names it (`solana:mainnet`); the wallet package also accepts the genesis-hash form. */\nexport const SOLANA_CHAIN = 'solana:mainnet'\nexport const SOLANA_RPCS: readonly string[] = Object.freeze(['https://solana-rpc.publicnode.com', 'https://api.mainnet-beta.solana.com'])\nexport const TON_CHAIN = 'ton:-239'\nexport const TON_ENDPOINTS: readonly string[] = Object.freeze(['https://ton.access.orbs.network/1/mainnet/toncenter-api-v2/jsonRPC', 'https://toncenter.com/api/v2/jsonRPC'])\nexport const TRON_CHAIN = 'tron:728126428'\nexport const TRON_PROVIDERS: readonly string[] = Object.freeze(['https://api.trongrid.io'])\nexport const BTC_CHAIN = 'bitcoin:mainnet'\nexport const BTC_ESPLORA: readonly string[] = Object.freeze(['https://mempool.space/api', 'https://blockstream.info/api'])\nexport const NEAR_CHAIN = 'near:mainnet'\nexport const NEAR_PROVIDERS: readonly string[] = Object.freeze(['https://free.rpc.fastnear.com', 'https://rpc.mainnet.near.org'])\n/** Zcash transparent (t1…) accounts over Blockchair's public API, as `@anywalletkit/wallet-zcash` reads and broadcasts them. */\nexport const ZCASH_CHAIN = 'zcash:mainnet'\nexport const ZCASH_BLOCKCHAIR = 'https://api.blockchair.com/zcash'\n\nexport interface ChainDescriptor {\n caip2: string\n key: 'solana' | 'ton' | 'tron' | 'btc' | 'near' | 'zcash'\n name: string\n symbol: string\n decimals: number\n explorerTx: string\n explorerAddress: string\n}\n\nexport const NON_EVM_CHAINS: readonly ChainDescriptor[] = Object.freeze([\n { caip2: SOLANA_CHAIN, key: 'solana', name: 'Solana', symbol: 'SOL', decimals: 9, explorerTx: 'https://solscan.io/tx/', explorerAddress: 'https://solscan.io/account/' },\n { caip2: TON_CHAIN, key: 'ton', name: 'TON', symbol: 'GRAM', decimals: 9, explorerTx: 'https://tonviewer.com/transaction/', explorerAddress: 'https://tonviewer.com/' },\n { caip2: TRON_CHAIN, key: 'tron', name: 'Tron', symbol: 'TRX', decimals: 6, explorerTx: 'https://tronscan.org/#/transaction/', explorerAddress: 'https://tronscan.org/#/address/' },\n { caip2: BTC_CHAIN, key: 'btc', name: 'Bitcoin', symbol: 'BTC', decimals: 8, explorerTx: 'https://mempool.space/tx/', explorerAddress: 'https://mempool.space/address/' },\n { caip2: NEAR_CHAIN, key: 'near', name: 'NEAR', symbol: 'NEAR', decimals: 24, explorerTx: 'https://nearblocks.io/txns/', explorerAddress: 'https://nearblocks.io/address/' },\n { caip2: ZCASH_CHAIN, key: 'zcash', name: 'Zcash', symbol: 'ZEC', decimals: 8, explorerTx: 'https://blockchair.com/zcash/transaction/', explorerAddress: 'https://blockchair.com/zcash/address/' },\n])\n\nexport const nonEvmChain = (caip2: string): ChainDescriptor | undefined => NON_EVM_CHAINS.find((c) => c.caip2 === caip2)\n","import type { StorageAreaLike } from './chrome.js'\n\n/** One JSON value under one key — the shape every small store here needs. */\nexport interface JsonStorage<T> {\n get(): Promise<T | null>\n set(value: T): Promise<void>\n}\n\nexport function chromeJsonStorage<T>(area: StorageAreaLike, key: string): JsonStorage<T> {\n return {\n async get() { return ((await area.get(key))[key] as T | undefined) ?? null },\n async set(value) { await area.set({ [key]: value }) },\n }\n}\n\nexport function memoryJsonStorage<T>(initial: T | null = null): JsonStorage<T> & { value: T | null } {\n const s = {\n value: initial,\n async get() { return s.value === null ? null : structuredClone(s.value) },\n async set(value: T) { s.value = structuredClone(value) },\n }\n return s\n}\n","/**\n * Per-origin permissions: which accounts a site may see and which chain it is\n * on. Nothing here is secret (`chrome.storage.local`, plain JSON); the origin\n * key is the one the browser recorded for the port, never the page's claim.\n */\nimport type { JsonStorage } from './storage.js'\n\nexport interface OriginPermission {\n origin: string\n /** EVM addresses exposed to this origin (checksummed as the keyring stores them). Empty when only another chain is connected. */\n accounts: string[]\n /** CAIP-2 chain the origin currently sees (`eth_chainId`). */\n chain: string\n /** Solana addresses exposed to this origin (Wallet Standard `standard:connect`). */\n solanaAccounts?: string[]\n /** TON addresses exposed to this origin (TON Connect). */\n tonAccounts?: string[]\n /** Tron (TIP-1193), Bitcoin (sats-connect) and NEAR (wallet-selector) addresses. */\n tronAccounts?: string[]\n btcAccounts?: string[]\n nearAccounts?: string[]\n connectedAt: number\n}\n\nexport type PermissionsState = Record<string, OriginPermission>\n\nexport type ChainAccountsKey = 'solanaAccounts' | 'tonAccounts' | 'tronAccounts' | 'btcAccounts' | 'nearAccounts'\nexport const CHAIN_ACCOUNT_KEYS: readonly ChainAccountsKey[] = ['solanaAccounts', 'tonAccounts', 'tronAccounts', 'btcAccounts', 'nearAccounts']\n\nexport class PermissionStore {\n private _state: PermissionsState | null = null\n private _loading: Promise<PermissionsState> | null = null\n /** Every mutation runs here, one after another (scan F22): a read-modify-write never starts from a snapshot another one is about to replace. */\n private _queue: Promise<unknown> = Promise.resolve()\n private readonly _listeners = new Set<(origin: string, permission: OriginPermission | null) => void>()\n\n constructor(private readonly storage: JsonStorage<PermissionsState>) {}\n\n private async state(): Promise<PermissionsState> {\n if (this._state) return this._state\n // One load; a load that resolves after a write must not replace the newer cache.\n this._loading ??= this.storage.get().then(\n (s) => (this._state ??= s ?? {}),\n (e: unknown) => { this._loading = null; throw e },\n )\n return this._loading\n }\n\n /**\n * Run `fn` after every earlier mutation settled. Public mutators wrap their WHOLE read-modify-write\n * in this; `write` itself is unlocked (setAccountsEverywhere calls it in a loop — a lock there too\n * would deadlock). Nothing awaited inside may wait on the user: routers await the approval sheet\n * first and only then call the store.\n */\n private serialize<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n async get(origin: string): Promise<OriginPermission | null> {\n return (await this.state())[origin] ?? null\n }\n\n async list(): Promise<OriginPermission[]> {\n return Object.values(await this.state())\n }\n\n connect(origin: string, accounts: string[], chain: string): Promise<OriginPermission> {\n return this.serialize(async () => {\n if (accounts.length === 0) throw new Error('Connect at least one account.')\n const current = await this.get(origin)\n const permission: OriginPermission = { ...(current ?? {}), origin, accounts: [...accounts], chain, connectedAt: current?.connectedAt ?? Date.now() }\n await this.write(origin, permission)\n return permission\n })\n }\n\n /**\n * Add EVM accounts to an origin's grant (per-site grants): the new ones first, the ones it already\n * holds stay. The chain stays the origin's own when it has one. Used by the router's connect; `connect`\n * replaces the list instead.\n */\n grant(origin: string, accounts: string[], chain: string): Promise<OriginPermission> {\n return this.serialize(async () => {\n if (accounts.length === 0) throw new Error('Connect at least one account.')\n const current = await this.get(origin)\n const merged = [...accounts, ...(current?.accounts ?? []).filter((a) => !accounts.some((x) => x.toLowerCase() === a.toLowerCase()))]\n const permission: OriginPermission = { ...(current ?? {}), origin, accounts: merged, chain: current?.chain ?? chain, connectedAt: current?.connectedAt ?? Date.now() }\n await this.write(origin, permission)\n return permission\n })\n }\n\n /** Connect another chain's accounts to the same origin (one \"connected sites\" list). */\n connectChain(origin: string, key: ChainAccountsKey, accounts: string[], defaultChain: string): Promise<OriginPermission> {\n return this.serialize(async () => {\n if (accounts.length === 0) throw new Error('Connect at least one account.')\n const current = await this.get(origin)\n const permission: OriginPermission = { origin, accounts: current?.accounts ?? [], chain: current?.chain ?? defaultChain, ...(current ?? {}), [key]: [...accounts], connectedAt: current?.connectedAt ?? Date.now() }\n await this.write(origin, permission)\n return permission\n })\n }\n\n /** Drop one chain's accounts; the origin stays connected while any chain remains. A no-op (no write) when there is nothing to drop. */\n disconnectChain(origin: string, key: 'accounts' | ChainAccountsKey): Promise<void> {\n return this.serialize(async () => {\n const current = await this.get(origin)\n if (!current) return\n if (key === 'accounts' ? current.accounts.length === 0 : current[key] === undefined) return\n const next: OriginPermission = { ...current, [key]: key === 'accounts' ? [] : undefined }\n if (key !== 'accounts') delete next[key]\n const anything = next.accounts.length > 0 || CHAIN_ACCOUNT_KEYS.some((k) => (next[k]?.length ?? 0) > 0)\n await this.write(origin, anything ? next : null)\n })\n }\n\n setChain(origin: string, chain: string): Promise<OriginPermission | null> {\n return this.serialize(async () => {\n const current = await this.get(origin)\n if (!current) return null\n const next = { ...current, chain }\n await this.write(origin, next)\n return next\n })\n }\n\n /**\n * @deprecated Rewrites every origin's grant to the active account, which shows that account to sites\n * the user never connected it to (and links accounts across sites). Grants are per site now: the\n * router shows an origin its granted accounts that are also active, and connecting another account\n * adds it to that one origin ({@link grant}). Kept for compatibility; nothing in this package calls it.\n *\n * The active EVM account changed: every origin holding an EVM grant now sees `accounts` (MetaMask behaviour).\n * An origin connected only on another chain (`accounts: []` — Solana/TON/Tron/BTC/NEAR providers, a WalletConnect\n * session without eip155) is skipped: it never passed an EVM connect and must not learn the EVM address (scan F6/F8).\n * Lock never writes `[]` here, so the skip cannot strip a real EVM grant.\n */\n setAccountsEverywhere(accounts: string[]): Promise<OriginPermission[]> {\n return this.serialize(async () => {\n const changed: OriginPermission[] = []\n for (const p of await this.list()) {\n if (p.accounts.length === 0 || sameList(p.accounts, accounts)) continue\n const next = { ...p, accounts: [...accounts] }\n await this.write(p.origin, next)\n changed.push(next)\n }\n return changed\n })\n }\n\n disconnect(origin: string): Promise<void> {\n return this.serialize(async () => {\n if (!(await this.get(origin))) return\n await this.write(origin, null)\n })\n }\n\n onChange(listener: (origin: string, permission: OriginPermission | null) => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n /** Unlocked: callers hold the queue. The cache changes before the await (readers see it at once) and is rolled back when storage refuses. */\n private async write(origin: string, permission: OriginPermission | null): Promise<void> {\n const prev = await this.state()\n const state = { ...prev }\n if (permission) state[origin] = permission\n else delete state[origin]\n this._state = state\n try {\n await this.storage.set(state)\n } catch (e) {\n if (this._state === state) this._state = prev\n throw e\n }\n for (const l of this._listeners) l(origin, permission)\n }\n}\n\nconst sameList = (a: string[], b: string[]) => a.length === b.length && a.every((x, i) => x === b[i])\n","/**\n * \"Same site\" for limits: the registrable domain (eTLD+1) of an origin, and a\n * token bucket keyed by any string. Both exist so a page cannot multiply its\n * allowance by spreading requests over subdomains (`a1.evil.tld`, `a2.evil.tld`…).\n *\n * There is no Public Suffix List in this package (it is large and changes); the\n * helper is conservative instead: the last two labels, or three when the last two\n * are a known multi-label public suffix ({@link MULTI_LABEL_SUFFIXES}: country\n * second-level domains such as `co.uk`, and hosting domains where anyone gets a\n * subdomain, such as `github.io` or `vercel.app`). A suffix that is missing from\n * the list makes unrelated sites under it share one limit (stricter, never looser);\n * pass your own `siteOf` to the queue when you ship a full list.\n */\n\n/**\n * Multi-label public suffixes the helper knows. Two groups: country second-level\n * registries, and hosting platforms that hand out subdomains to anyone (the\n * Public Suffix List's private section).\n */\nexport const MULTI_LABEL_SUFFIXES: ReadonlySet<string> = new Set([\n // country second-level registries\n 'co.uk', 'org.uk', 'me.uk', 'ltd.uk', 'plc.uk', 'net.uk', 'ac.uk', 'gov.uk',\n 'com.au', 'net.au', 'org.au', 'edu.au', 'gov.au', 'id.au',\n 'co.nz', 'org.nz', 'net.nz', 'co.jp', 'ne.jp', 'or.jp', 'ac.jp', 'go.jp', 'co.kr', 'or.kr', 'ne.kr',\n 'com.br', 'net.br', 'org.br', 'com.cn', 'net.cn', 'org.cn', 'com.hk', 'com.tw', 'com.sg', 'com.my',\n 'co.in', 'net.in', 'org.in', 'co.id', 'co.il', 'co.th', 'co.za', 'com.mx', 'com.ar', 'com.co', 'com.tr',\n 'com.ua', 'com.pl', 'com.ru', 'com.vn', 'com.ph', 'com.pk', 'com.ng', 'com.eg', 'com.sa', 'co.ke',\n // hosting platforms: every customer gets its own subdomain\n 'github.io', 'gitlab.io', 'vercel.app', 'now.sh', 'pages.dev', 'workers.dev', 'r2.dev', 'netlify.app', 'netlify.com',\n 'herokuapp.com', 'web.app', 'firebaseapp.com', 'appspot.com', 'azurewebsites.net', 'azurestaticapps.net', 'cloudfront.net',\n 'amplifyapp.com', 'onrender.com', 'fly.dev', 'railway.app', 'up.railway.app', 'deno.dev', 'glitch.me', 'repl.co', 'replit.app',\n 'replit.dev', 'surge.sh', 'webflow.io', 'framer.app', 'framer.website', 'wixsite.com', 'blogspot.com', 'myshopify.com',\n 'notion.site', 'carrd.co', 'gitbook.io', 'readthedocs.io', 'ngrok.io', 'ngrok-free.app', 'loca.lt', 'trycloudflare.com',\n // ENS / IPFS gateways: every name or CID is its own site\n 'eth.limo', 'eth.link', 'ipfs.dweb.link', 'ipns.dweb.link', 'ipfs.w3s.link', 'ipfs.cf-ipfs.com',\n])\n\nconst IPV4 = /^\\d{1,3}(\\.\\d{1,3}){3}$/\n\n/**\n * The site an origin belongs to: `https://a.b.example.co.uk:8443` → `example.co.uk`,\n * `https://x.vercel.app` → `x.vercel.app`. IP addresses and single-label hosts\n * (`localhost`) are their own site. A pseudo-origin that is not a URL (`wc:<topic>`)\n * is returned unchanged.\n */\nexport function siteOf(origin: string): string {\n let host: string\n try {\n const url = new URL(origin)\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return origin\n host = url.hostname.toLowerCase().replace(/\\.$/, '')\n } catch {\n return origin\n }\n if (!host || host.startsWith('[') || host.includes(':') || IPV4.test(host)) return host || origin\n const labels = host.split('.')\n if (labels.length <= 2) return host\n for (const size of [3, 2]) {\n if (labels.length <= size) continue\n if (MULTI_LABEL_SUFFIXES.has(labels.slice(-size).join('.'))) return labels.slice(-(size + 1)).join('.')\n }\n return labels.slice(-2).join('.')\n}\n\nexport interface TokenBucketOptions {\n /** Tokens a key holds when full (the burst). */\n capacity: number\n /** Tokens added per second. */\n refillPerSecond: number\n /** Clock (ms), injectable for tests. */\n now?: () => number\n /** Keys tracked before full buckets are dropped (memory bound). Default 2000. */\n maxKeys?: number\n}\n\n/** A token bucket per key: `take(key)` spends one token, `false` when the key is out of tokens. Memory only. */\nexport class TokenBucket {\n private readonly buckets = new Map<string, { tokens: number; at: number }>()\n constructor(private readonly options: TokenBucketOptions) {}\n\n take(key: string, cost = 1): boolean {\n const now = (this.options.now ?? Date.now)()\n const b = this.refill(key, now)\n if (b.tokens < cost) return false\n b.tokens -= cost\n return true\n }\n\n /** Tokens `key` holds right now (full for an unknown key). */\n available(key: string): number {\n return this.refill(key, (this.options.now ?? Date.now)()).tokens\n }\n\n private refill(key: string, now: number): { tokens: number; at: number } {\n let b = this.buckets.get(key)\n if (!b) {\n if (this.buckets.size >= (this.options.maxKeys ?? 2000)) this.prune(now)\n b = { tokens: this.options.capacity, at: now }\n this.buckets.set(key, b)\n return b\n }\n const elapsed = Math.max(0, now - b.at) / 1000\n b.tokens = Math.min(this.options.capacity, b.tokens + elapsed * this.options.refillPerSecond)\n b.at = now\n return b\n }\n\n /** Drop buckets that are full again (they carry no state); the oldest half when every one is in use. */\n private prune(now: number): void {\n for (const [k, b] of this.buckets) {\n if (b.tokens + (Math.max(0, now - b.at) / 1000) * this.options.refillPerSecond >= this.options.capacity) this.buckets.delete(k)\n }\n if (this.buckets.size >= (this.options.maxKeys ?? 2000)) {\n let drop = Math.ceil(this.buckets.size / 2)\n for (const k of this.buckets.keys()) { if (drop-- <= 0) break; this.buckets.delete(k) }\n }\n }\n}\n","/**\n * The approval queue — Vaulty's `txGate` (mobile/lib/txGate.ts) for an\n * extension. A dApp request that needs the user waits here; ONE approval window\n * is open at a time (`chrome.windows.create({ type: 'popup' })`), the next\n * request opens when the current one is answered. The window losing focus\n * changes nothing: the request stays pending. Closing the window, or declining,\n * rejects with {@link ReviewDeclined} — EIP-1193 4001, \"nothing was signed\".\n *\n * The queue lives in the service worker's memory: an open approval window keeps\n * the worker alive, and if the worker is nevertheless restarted the pending\n * promises die with it — the page gets no answer and retries, which is the\n * failure mode MetaMask has too.\n *\n * Limits keep a page from burying one real request under decoys (SDK-142 M3,\n * audit E17): at most `maxPendingPerOrigin` requests wait per origin, at most\n * `maxPendingPerSite` per registrable domain (subdomains share them), at most\n * `maxPendingTotal` in the whole queue (-32005 for each), a second `connect`\n * while one is pending is refused outright (-32002), and each site may open only\n * so many sheets per minute (`openRate`: a token bucket; running dry starts a\n * cooldown that doubles on every repeat). Origins the wallet names `exempt` (its\n * own pages) skip every limit. `declineOrigin` / `declineSite` drop one origin's\n * or one site's backlog (the page closed; \"decline all from this site\").\n *\n * A follow-up (`request(…, { followUp: true })`) is another sheet for a request\n * the user has just approved — the fee changed before signing. Each approval pays\n * for one follow-up of the same origin, kind and chain: that one skips the limits\n * above and is shown ahead of the requests already waiting. A refused origin\n * stays refused.\n *\n * An origin can carry a transport note (`via`, set by the WalletConnect bridge):\n * the sheet then says the request came over WalletConnect, what the dApp claims\n * to be and what WalletConnect Verify says about that claim — the claim itself is\n * never used as the permission key.\n */\nimport { RELAY_ERRORS } from './relay.js'\nimport { TokenBucket, siteOf as defaultSiteOf } from './site.js'\n\nexport class ReviewDeclined extends Error {\n readonly code = RELAY_ERRORS.userRejected\n constructor(message = 'You declined — nothing was signed.') {\n super(message)\n this.name = 'ReviewDeclined'\n }\n}\n\nexport type ApprovalKind = 'connect' | 'switch-chain' | 'add-chain' | 'sign-message' | 'sign-typed-data' | 'send-transaction' | 'solana-send' | 'swap' | 'earn' | 'chain-send' | 'tron-sign' | 'btc-sign' | 'near-sign' | 'near-signin' | 'wc-session'\n\n/** How a request reached the wallet when it did not come through a content script. */\nexport interface OriginVia {\n transport: 'walletconnect'\n /** What the dApp declared about itself (self-reported, unverified unless `verify` says so). */\n url: string\n name: string\n /** WalletConnect Verify: VALID = the relay saw the request come from `url`'s origin; INVALID = it came from somewhere else; UNKNOWN = not attested. */\n verify: 'VALID' | 'INVALID' | 'UNKNOWN'\n scam?: boolean\n}\n\n/** The queue refused to enqueue (per-origin limits); carries an EIP-1474 code the page understands. */\nexport class QueueLimitError extends Error {\n constructor(readonly code: number, message: string) {\n super(message)\n this.name = 'QueueLimitError'\n }\n}\n\n/** The origin is refused before any window opens (the shipped phishing list); EIP-1193 4100. */\nexport class OriginRefused extends Error {\n readonly code = RELAY_ERRORS.unauthorized\n constructor(message: string) {\n super(message)\n this.name = 'OriginRefused'\n }\n}\n\nexport const APPROVALS_MAX_PENDING_PER_ORIGIN = 3\n/** Requests one site (registrable domain: every subdomain counts) may have waiting. */\nexport const APPROVALS_MAX_PENDING_PER_SITE = 5\n/** Requests the whole queue holds (exempt origins not counted). */\nexport const APPROVALS_MAX_PENDING_TOTAL = 20\n\n/** How fast one site may open sheets: a token bucket per site; running dry refuses for a cooldown that doubles on every repeat. */\nexport interface ApprovalRateOptions {\n /** Sheets a site may open at once. Default 10. */\n burst?: number\n /** Sheets per second a site earns back. Default 1/6 (10 a minute). */\n refillPerSecond?: number\n /** First cooldown after the bucket ran dry. Default 30 s. */\n backoffMs?: number\n /** Longest cooldown; also how long a site must stay quiet for its strikes to reset. Default 10 min. */\n maxBackoffMs?: number\n}\n\nexport interface ApprovalRequest<P = unknown> {\n id: string\n origin: string\n chain: string\n kind: ApprovalKind\n /** What the window shows; shape per kind, public data only. */\n payload: P\n createdAt: number\n /** Phishing / lookalike / punycode notes about the origin, from the queue's `annotate` hook. */\n originWarnings?: string[]\n /** Set when the origin is a transport pseudo-origin (`wc:<topic>`): what the sheet should say about where this came from. */\n via?: OriginVia\n}\n\nexport interface ApprovalQueueOptions {\n /** Called for every request's origin; the lines are shown on the sheet (e.g. the shipped phishing list's verdict). */\n annotate?: (origin: string) => string[]\n /**\n * Called for every request's origin before anything is queued: a reason refuses the request with\n * {@link OriginRefused} (4100) and no window opens. Wire `PhishingDetector.refusal` here — a\n * warning on the sheet is one click away from a signature.\n */\n refuse?: (origin: string) => string | null | undefined\n /** Requests one origin may have waiting (current + queued). Default {@link APPROVALS_MAX_PENDING_PER_ORIGIN}. */\n maxPendingPerOrigin?: number\n /** Requests one site may have waiting. Default {@link APPROVALS_MAX_PENDING_PER_SITE}. */\n maxPendingPerSite?: number\n /** Requests the queue holds in all. Default {@link APPROVALS_MAX_PENDING_TOTAL}. */\n maxPendingTotal?: number\n /** Origin → site for the per-site limits. Default {@link defaultSiteOf siteOf} (conservative eTLD+1; pass a Public Suffix List based one if you ship it). */\n siteOf?: (origin: string) => string\n /** Origins that skip every limit (the wallet's own pages: Send, swaps). They still queue behind other requests. */\n exempt?: (origin: string) => boolean\n /** Sheet-opening rate per site; `false` turns it off. */\n openRate?: ApprovalRateOptions | false\n /** Clock (ms), injectable for tests. */\n now?: () => number\n}\n\n/** Options of one {@link ApprovalQueue.request}. */\nexport interface ApprovalRequestOptions {\n /**\n * Another sheet for a request the user has just approved (the fee changed before signing). It skips\n * the queue and rate limits and is shown ahead of the requests already waiting — once per approval\n * of the same origin, kind and chain; with no such approval behind it, it is an ordinary request.\n * `refuse` still applies.\n */\n followUp?: boolean\n}\n\n/** Follow-ups one origin + kind + chain may have paid for and not used. */\nconst FOLLOW_UP_CREDITS_MAX = 8\n/** Origin + kind + chain entries remembered for follow-ups. */\nconst FOLLOW_UP_KEYS_MAX = 256\n\n/** The window side: open for one request, close when it is answered. `memoryApprovalWindow()` for tests. */\nexport interface ApprovalWindow {\n open(request: ApprovalRequest): Promise<void>\n close(requestId: string): Promise<void>\n /** The user closed the window themself (chrome.windows.onRemoved): the queue declines the request. */\n onClosed(handler: (requestId: string) => void): void\n}\n\ninterface Pending<T = unknown> {\n request: ApprovalRequest\n resolve: (value: T) => void\n reject: (error: Error) => void\n}\n\nexport class ApprovalQueue {\n private _current: Pending | null = null\n private readonly _waiting: Pending[] = []\n private readonly _listeners = new Set<() => void>()\n private readonly _via = new Map<string, OriginVia>()\n private readonly _rate: TokenBucket | null\n /** Per site: cooldown end and strikes (how many times the bucket ran dry recently). */\n private readonly _cooldown = new Map<string, { until: number; strikes: number; last: number }>()\n /** Per origin + kind + chain: approvals that have not been followed up (see {@link ApprovalRequestOptions.followUp}). */\n private readonly _approved = new Map<string, number>()\n\n constructor(private readonly window: ApprovalWindow, private readonly newId: () => string = () => crypto.randomUUID(), private readonly options: ApprovalQueueOptions = {}) {\n window.onClosed((id) => { if (this._current?.request.id === id) this.decline(id) })\n const rate = options.openRate === false ? null : options.openRate ?? {}\n this._rate = rate ? new TokenBucket({ capacity: rate.burst ?? 10, refillPerSecond: rate.refillPerSecond ?? 1 / 6, ...(options.now ? { now: options.now } : {}) }) : null\n }\n\n private site(origin: string): string {\n try { return (this.options.siteOf ?? defaultSiteOf)(origin) } catch { return origin }\n }\n\n private get all(): Pending[] {\n return [...(this._current ? [this._current] : []), ...this._waiting]\n }\n\n /** The per-site rate: a reason to refuse, or null (and one token spent). */\n private rateRefusal(site: string): string | null {\n if (!this._rate) return null\n const rate = this.options.openRate || {}\n const now = (this.options.now ?? Date.now)()\n const max = rate.maxBackoffMs ?? 600_000\n const c = this._cooldown.get(site)\n if (c && now < c.until) return `This site opened too many requests; try again in ${Math.ceil((c.until - now) / 1000)} s.`\n if (this._rate.take(site)) return null\n const strikes = c && now - c.last < max ? c.strikes + 1 : 1\n const wait = Math.min(max, (rate.backoffMs ?? 30_000) * 2 ** (strikes - 1))\n this._cooldown.set(site, { until: now + wait, strikes, last: now })\n if (this._cooldown.size > 1000) for (const [k, v] of this._cooldown) if (now - v.last >= max) this._cooldown.delete(k)\n return `This site opened too many requests; try again in ${Math.ceil(wait / 1000)} s.`\n }\n\n private static followUpKey(r: Pick<ApprovalRequest, 'origin' | 'kind' | 'chain'>): string {\n return `${r.origin}\\n${r.kind}\\n${r.chain}`\n }\n\n /** The user approved `r`: it may be followed up once. */\n private approved(r: ApprovalRequest): void {\n const key = ApprovalQueue.followUpKey(r)\n const n = Math.min((this._approved.get(key) ?? 0) + 1, FOLLOW_UP_CREDITS_MAX)\n this._approved.delete(key)\n this._approved.set(key, n)\n if (this._approved.size > FOLLOW_UP_KEYS_MAX) this._approved.delete(this._approved.keys().next().value!)\n }\n\n /** Spends one approval of the same origin, kind and chain; false when there is none. */\n private spendApproval(r: Pick<ApprovalRequest, 'origin' | 'kind' | 'chain'>): boolean {\n const key = ApprovalQueue.followUpKey(r)\n const n = this._approved.get(key) ?? 0\n if (n <= 0) return false\n if (n === 1) this._approved.delete(key)\n else this._approved.set(key, n - 1)\n return true\n }\n\n /** Enqueue and wait for the user's answer. Refuses (never queues) past the per-origin limits. */\n request<T = unknown>(input: Omit<ApprovalRequest, 'id' | 'createdAt' | 'originWarnings' | 'via'>, opts: ApprovalRequestOptions = {}): Promise<T> {\n let refused: string | null | undefined\n try { refused = this.options.refuse?.(input.origin) } catch (e) { refused = `The wallet could not check this site (${e instanceof Error ? e.message : String(e)}).` }\n if (refused) return Promise.reject(new OriginRefused(refused))\n let exempt = false\n try { exempt = this.options.exempt?.(input.origin) === true } catch { exempt = false }\n const followUp = opts.followUp === true && this.spendApproval(input)\n if (!exempt && !followUp) {\n const all = this.all\n const sameOrigin = all.filter((p) => p.request.origin === input.origin)\n if (input.kind === 'connect' && sameOrigin.some((p) => p.request.kind === 'connect')) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.resourceUnavailable, 'A connect request from this site is already waiting for your answer.'))\n }\n const max = this.options.maxPendingPerOrigin ?? APPROVALS_MAX_PENDING_PER_ORIGIN\n if (sameOrigin.length >= max) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.limitExceeded, `This site already has ${max} requests waiting for you; answer or close them first.`))\n }\n const site = this.site(input.origin)\n const maxSite = this.options.maxPendingPerSite ?? APPROVALS_MAX_PENDING_PER_SITE\n if (all.filter((p) => this.site(p.request.origin) === site).length >= maxSite) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.limitExceeded, `This site already has ${maxSite} requests waiting for you across its subdomains; answer or close them first.`))\n }\n const maxTotal = this.options.maxPendingTotal ?? APPROVALS_MAX_PENDING_TOTAL\n if (all.filter((p) => !this.isExempt(p.request.origin)).length >= maxTotal) {\n return Promise.reject(new QueueLimitError(RELAY_ERRORS.limitExceeded, `The wallet already has ${maxTotal} requests waiting for you; answer or close them first.`))\n }\n const slow = this.rateRefusal(site)\n if (slow) return Promise.reject(new QueueLimitError(RELAY_ERRORS.limitExceeded, slow))\n }\n return new Promise<T>((resolve, reject) => {\n const warnings = this.options.annotate?.(input.origin) ?? []\n const via = this._via.get(input.origin)\n const pending: Pending = { request: { ...input, id: this.newId(), createdAt: Date.now(), ...(warnings.length ? { originWarnings: warnings } : {}), ...(via ? { via } : {}) }, resolve: resolve as (v: unknown) => void, reject }\n if (followUp) this._waiting.unshift(pending)\n else this._waiting.push(pending)\n void this.next()\n })\n }\n\n /** Attach (or clear) the transport note every later request from `origin` carries. */\n setVia(origin: string, via: OriginVia | null): void {\n if (via) this._via.set(origin, via)\n else this._via.delete(origin)\n }\n\n /** The transport note later requests from `origin` carry (WalletConnect Verify's verdict for `wc:<topic>`), if any. */\n viaFor(origin: string): OriginVia | undefined {\n return this._via.get(origin)\n }\n\n private isExempt(origin: string): boolean {\n try { return this.options.exempt?.(origin) === true } catch { return false }\n }\n\n /** Requests waiting for `origin` (current + queued). */\n pendingFor(origin: string): number {\n return this.all.filter((p) => p.request.origin === origin).length\n }\n\n /** Requests waiting for any origin of `site` (current + queued). */\n pendingForSite(site: string): number {\n return this.all.filter((p) => this.site(p.request.origin) === site).length\n }\n\n /** The site (registrable domain) the queue's limits put `origin` under. */\n siteFor(origin: string): string {\n return this.site(origin)\n }\n\n /** Decline everything waiting for `origin` (its last page closed). Returns how many requests were declined. */\n declineOrigin(origin: string, error: Error = new ReviewDeclined('The page was closed — nothing was signed.')): number {\n return this.declineWhere((p) => p.request.origin === origin, error)\n }\n\n /** \"Decline all from this site\": everything waiting for any origin of `site` (see {@link siteFor}). */\n declineSite(site: string, error: Error = new ReviewDeclined()): number {\n return this.declineWhere((p) => this.site(p.request.origin) === site, error)\n }\n\n private declineWhere(match: (p: Pending) => boolean, error: Error): number {\n // Queued ones first: declining the current one opens the next window, which must not be one of these.\n const ids = [...this._waiting.filter(match), ...(this._current && match(this._current) ? [this._current] : [])].map((p) => p.request.id)\n for (const id of ids) this.decline(id, error)\n return ids.length\n }\n\n /** The request currently shown (the window asks for it by id on load). */\n get current(): ApprovalRequest | null {\n return this._current?.request ?? null\n }\n\n get queued(): number {\n return this._waiting.length\n }\n\n resolve(requestId: string, value: unknown): boolean {\n return this.settle(requestId, (p) => { this.approved(p.request); p.resolve(value) })\n }\n\n decline(requestId: string, error: Error = new ReviewDeclined()): boolean {\n return this.settle(requestId, (p) => p.reject(error))\n }\n\n /** Lock, disconnect, shutdown: everything pending is declined. */\n declineAll(error: Error = new ReviewDeclined('The wallet was locked.')): void {\n const all = [...(this._current ? [this._current] : []), ...this._waiting.splice(0)]\n this._approved.clear()\n for (const p of all) p.reject(error)\n if (this._current) void this.window.close(this._current.request.id)\n this._current = null\n this.emit()\n }\n\n onChange(listener: () => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n private settle(requestId: string, fn: (p: Pending) => void): boolean {\n if (this._current?.request.id === requestId) {\n const p = this._current\n this._current = null\n fn(p)\n void this.window.close(requestId).catch(() => undefined)\n this.emit()\n void this.next()\n return true\n }\n const i = this._waiting.findIndex((p) => p.request.id === requestId)\n if (i < 0) return false\n fn(this._waiting.splice(i, 1)[0]!)\n this.emit()\n return true\n }\n\n private async next(): Promise<void> {\n if (this._current || this._waiting.length === 0) return\n const p = this._waiting.shift()!\n this._current = p\n this.emit()\n try {\n await this.window.open(p.request)\n } catch (e) {\n if (this._current === p) {\n this._current = null\n p.reject(e instanceof Error ? e : new Error(String(e)))\n this.emit()\n void this.next()\n }\n }\n }\n\n private emit(): void {\n for (const l of this._listeners) l()\n }\n}\n\n/** In-memory window: tests answer through the queue; `opened` records every request shown. */\nexport function memoryApprovalWindow(): ApprovalWindow & { opened: ApprovalRequest[]; openIds: Set<string>; userClose(id: string): void } {\n let handler: (id: string) => void = () => undefined\n const w = {\n opened: [] as ApprovalRequest[],\n openIds: new Set<string>(),\n async open(request: ApprovalRequest) { w.opened.push(request); w.openIds.add(request.id) },\n async close(id: string) { w.openIds.delete(id) },\n onClosed(h: (id: string) => void) { handler = h },\n userClose(id: string) { w.openIds.delete(id); handler(id) },\n }\n return w\n}\n","/**\n * The request router: what a dApp may ask and what happens to each request.\n * Policy:\n *\n * - the origin is the browser's (checked by the service worker before this runs);\n * - accounts are exposed only to origins the user connected (`eth_requestAccounts`\n * → approval window); `eth_accounts` is `[]` otherwise. Grants are per site: an\n * origin sees the accounts IT was granted that the wallet exposes right now (the\n * active one), connecting another account adds it to that origin only, and a\n * signature must name a granted and exposed account;\n * - chain switching and adding go through the approval window; a chain can be\n * added only if the asset catalog knows it, with https RPCs;\n * - read-only JSON-RPC is answered from the wallet's own clients (the networks\n * table's failover list), never from a URL the page names; `eth_getLogs` from an\n * origin without an EVM grant spans at most {@link GETLOGS_MAX_SPAN_UNCONNECTED} blocks;\n * - `eth_sign` (blind hash signing) is never offered; the other signing methods\n * go to the `sign` hook (the review flow) when the wallet provides one;\n * - everything else is refused with 4200.\n *\n * Errors leave as {@link RouterError} (EIP-1193 codes) or {@link ReviewDeclined}\n * (4001); the service worker turns both into a `RelayResponse.error`.\n */\nimport { UserRejectedError } from '@anywalletkit/core'\nimport { ApprovalQueue, ReviewDeclined } from './approvals.js'\nimport { DEFAULT_CHAIN, NetworksTable, caip2FromChainId, chainHex, parseAddChainParams, type EvmNetwork } from './networks.js'\nimport { PermissionStore, type OriginPermission } from './permissions.js'\nimport { RELAY_ERRORS, isRelayMethod, type RelayChain, type RelayError } from './relay.js'\n\nexport class RouterError extends Error {\n readonly code: number\n readonly data: unknown\n constructor(code: number, message: string, data?: unknown) {\n super(message)\n this.name = 'RouterError'\n this.code = code\n this.data = data\n }\n static from(e: RelayError): RouterError {\n return new RouterError(e.code, e.message, e.data)\n }\n}\n\n/** Options for {@link toRelayError}. */\nexport interface RelayErrorOptions {\n /** Gets every error that is NOT passed to the page, in full — the extension's own log. */\n log?: (error: unknown) => void\n}\n\n/** EIP-1193 provider codes a wallet error may carry to the page. */\nconst PROVIDER_CODES: ReadonlySet<number> = new Set([4001, 4100, 4200, 4900, 4901, 4902])\n/** A node's JSON-RPC error: execution reverted (3) or the reserved -32768…-32000 range. */\nconst isNodeCode = (code: unknown): code is number => typeof code === 'number' && Number.isInteger(code) && (code === 3 || (code >= -32768 && code <= -32000))\n/**\n * A URL in an error message. The scheme is bounded, so a long run of scheme characters (a node's\n * or a page's own text) costs a constant per position instead of a scan to the end of the string;\n * there is no `\\b`, so a URL glued to a word is still caught (scan 2026-10-27 modules, F5).\n */\nconst URL_RE = /[a-z][a-z0-9+.-]{0,31}:\\/\\/[^\\s\"'<>()]+/gi\n/** How much of a message is read at all: the page sees 300 characters of its first line. */\nconst PAGE_TEXT_WINDOW = 1024\n/** A message as a page may see it: no URLs (RPC keys live in their paths and queries), one line, bounded — bounded before the regex runs. */\nconst pageText = (text: string): string => text.slice(0, PAGE_TEXT_WINDOW).split('\\n', 1)[0]!.replace(URL_RE, '[url]').slice(0, 300)\nconst isHexData = (v: unknown): v is string => typeof v === 'string' && /^0x[0-9a-fA-F]*$/.test(v) && v.length <= 2 + 2 * 8192\n\n/**\n * The node's own JSON-RPC error inside `e`, if there is one: viem's `RpcRequestError` (alone or\n * under a typed RPC error) carries the node's code, message (`details`) and data, while its\n * `message` adds the URL and the request body; a fetch-based transport may throw the bare\n * `{code, message, data}` object.\n */\nfunction nodeError(e: unknown): RelayError | undefined {\n for (let cur: unknown = e, depth = 0; cur && typeof cur === 'object' && depth < 8; cur = (cur as { cause?: unknown }).cause, depth++) {\n const o = cur as { name?: unknown; code?: unknown; details?: unknown; shortMessage?: unknown; message?: unknown; data?: unknown }\n if (o.name === 'RpcRequestError' && isNodeCode(o.code)) {\n const text = typeof o.details === 'string' && o.details ? o.details : typeof o.shortMessage === 'string' ? o.shortMessage : 'RPC error'\n return { code: o.code, message: pageText(text), ...(isHexData(o.data) ? { data: o.data } : {}) }\n }\n }\n if (!(e instanceof Error) && typeof e === 'object' && e !== null) {\n const o = e as { code?: unknown; message?: unknown; data?: unknown }\n if (isNodeCode(o.code) && typeof o.message === 'string') return { code: o.code, message: pageText(o.message), ...(isHexData(o.data) ? { data: o.data } : {}) }\n }\n return undefined\n}\n\n/**\n * Any error → the `RelayError` for the page. Wallet refusals keep their EIP-1193 code\n * ({@link RouterError}, {@link ReviewDeclined}, a core `UserRejectedError` → 4001), a node's own\n * JSON-RPC error keeps its code and revert data; their messages lose URLs. Everything else is\n * `-32603 Internal error` on the page and goes to `options.log` in full — transport errors name\n * the RPC URL (often with the provider key in it) and the request.\n */\nexport function toRelayError(e: unknown, options: RelayErrorOptions = {}): RelayError {\n if (e instanceof RouterError) return e.data === undefined ? { code: e.code, message: pageText(e.message) } : { code: e.code, message: pageText(e.message), data: e.data }\n if (e instanceof ReviewDeclined) return { code: e.code, message: pageText(e.message) }\n if (e instanceof UserRejectedError) return { code: RELAY_ERRORS.userRejected, message: pageText(e.message) }\n const node = nodeError(e)\n if (node) return node\n const code = (e as { code?: unknown } | null)?.code\n if (e instanceof Error && typeof code === 'number' && PROVIDER_CODES.has(code)) return { code, message: pageText(e.message) }\n options.log?.(e)\n return { code: RELAY_ERRORS.internal, message: 'Internal error' }\n}\n\n/** Read-only methods answered from our RPC without asking the user. */\nexport const READ_METHODS: ReadonlySet<string> = new Set([\n 'eth_blockNumber', 'eth_call', 'eth_estimateGas', 'eth_feeHistory', 'eth_gasPrice', 'eth_getBalance',\n 'eth_getBlockByHash', 'eth_getBlockByNumber', 'eth_getCode', 'eth_getLogs', 'eth_getStorageAt',\n 'eth_getTransactionByHash', 'eth_getTransactionCount', 'eth_getTransactionReceipt', 'eth_maxPriorityFeePerGas',\n])\n\n/**\n * Blocks an `eth_getLogs` from an origin without an EVM grant may span. A page that is not connected\n * reads recent events (a token's latest transfers, a pool's last swaps), not history: 1000 blocks is\n * ~3.3 h on Ethereum and ~30 min on 2 s chains, and stays inside every public RPC's own range cap,\n * so one call cannot make the wallet's RPC scan millions of blocks for a page nobody connected.\n * Connected origins are not bounded here (the node's own limits apply).\n */\nexport const GETLOGS_MAX_SPAN_UNCONNECTED = 1000\n\n/** Methods that produce a signature — the review flow's business (step 4), never answered here. */\nexport const SIGNING_METHODS: ReadonlySet<string> = new Set(['personal_sign', 'eth_signTypedData_v4', 'eth_signTypedData_v3', 'eth_signTypedData', 'eth_sendTransaction'])\n\nexport interface ConnectApproval {\n /** Addresses the wallet can expose, active account first (empty while locked — the window unlocks first and reloads). */\n accounts: string[]\n}\nexport interface SwitchChainApproval {\n from: EvmNetwork | null\n to: EvmNetwork\n}\nexport interface AddChainApproval {\n network: EvmNetwork\n}\n\nexport interface RouterDeps {\n permissions: PermissionStore\n networks: NetworksTable\n approvals: ApprovalQueue\n /** EVM addresses the wallet exposes, active account first. Empty when locked or without a wallet. */\n accounts(): Promise<string[]>\n /** Read-only JSON-RPC over the network's own RPC list. */\n rpc(network: EvmNetwork, method: string, params: unknown[]): Promise<unknown>\n /** Push an EIP-1193 event to every page of `origin`. */\n emit(origin: string, event: string, data: unknown): void\n /** The review flow for signing methods. Absent → 4200. */\n sign?(input: { origin: string; network: EvmNetwork; method: string; params: unknown[]; accounts: string[] }): Promise<unknown>\n defaultChain?: string\n /**\n * A reason to refuse every request from `origin` (reads, `eth_accounts`, an earlier permission\n * included) with 4100, or nothing. Wire `PhishingDetector.refusal`.\n */\n refuse?(origin: string): string | null | undefined\n}\n\nexport class RequestRouter {\n constructor(private readonly deps: RouterDeps) {}\n\n /** The chain an origin currently sees (its permission's, else the default). */\n async chainFor(origin: string): Promise<EvmNetwork> {\n const permission = await this.deps.permissions.get(origin)\n const wanted = permission?.chain ?? this.deps.defaultChain ?? DEFAULT_CHAIN\n return (await this.deps.networks.get(wanted)) ?? (await this.deps.networks.get(DEFAULT_CHAIN))!\n }\n\n async handle(origin: string, chain: RelayChain, method: string, rawParams: unknown): Promise<unknown> {\n const refused = this.deps.refuse?.(origin)\n if (refused) throw new RouterError(RELAY_ERRORS.unauthorized, refused)\n // Only a method name is echoed back in the refusals below, never whatever text the page sent.\n if (!isRelayMethod(method)) throw new RouterError(RELAY_ERRORS.invalidRequest, 'The request has no valid method name.')\n if (chain !== 'eip155') throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${chain} providers are not available yet.`)\n const params = Array.isArray(rawParams) ? rawParams : rawParams === undefined ? [] : [rawParams]\n const network = await this.chainFor(origin)\n const permission = await this.deps.permissions.get(origin)\n\n switch (method) {\n case 'eth_chainId':\n return chainHex(network.caip2)\n case 'net_version':\n return String(network.chainId)\n case 'eth_accounts':\n return this.visibleAccounts(permission)\n case 'eth_requestAccounts':\n return this.connect(origin, network)\n case 'wallet_getPermissions': {\n // An origin connected only on another chain holds no EVM permission (scan F6/F8); a granted account\n // that is not exposed right now is not listed either (per-site grants).\n const visible = await this.visibleAccounts(permission)\n return visible.length > 0 ? [permissionDescriptor(origin, visible)] : []\n }\n case 'wallet_requestPermissions': {\n const accounts = await this.connect(origin, network)\n return [permissionDescriptor(origin, accounts)]\n }\n case 'wallet_revokePermissions':\n await this.disconnect(origin)\n return null\n case 'wallet_switchEthereumChain': {\n const target = caip2FromChainId((params[0] as { chainId?: unknown } | undefined)?.chainId)\n if (!target) throw new RouterError(RELAY_ERRORS.invalidParams, 'wallet_switchEthereumChain expects [{ chainId }].')\n const to = await this.deps.networks.get(target)\n if (!to) throw new RouterError(RELAY_ERRORS.chainNotAdded, `Chain ${chainHex(target)} is not in this wallet; add it with wallet_addEthereumChain.`)\n await this.switchChain(origin, network, to)\n return null\n }\n case 'wallet_addEthereumChain': {\n const parsed = parseAddChainParams(params)\n if ('code' in parsed) throw RouterError.from(parsed)\n const existing = await this.deps.networks.get(parsed.caip2)\n if (existing) { await this.switchChain(origin, network, existing); return null }\n await this.deps.approvals.request({ origin, chain: network.caip2, kind: 'add-chain', payload: { network: parsed } satisfies AddChainApproval })\n // EIP-3085: the endpoint must answer for the chain it is being added as (a look-alike RPC for a real chain id is the phishing shape).\n let answered: unknown\n try { answered = await this.deps.rpc(parsed, 'eth_chainId', []) } catch (e) { throw new RouterError(RELAY_ERRORS.invalidParams, `The RPC for ${parsed.name} did not answer eth_chainId (${e instanceof Error ? e.message : String(e)}); the network was not added.`) }\n const got = caip2FromChainId(answered)\n if (got !== parsed.caip2) throw new RouterError(RELAY_ERRORS.invalidParams, `The RPC for ${parsed.name} answers chain ${String(answered)}, not ${chainHex(parsed.caip2)}; the network was not added.`)\n await this.deps.networks.add({ ...parsed, custom: { origin, addedAt: Date.now() } })\n if (permission) await this.switchChain(origin, network, parsed, true)\n return null\n }\n case 'eth_sign':\n case 'eth_signTransaction':\n throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${method} (blind signing) is never offered by this wallet.`)\n }\n\n if (READ_METHODS.has(method)) {\n if (method === 'eth_getLogs' && !(permission && permission.accounts.length > 0)) await this.boundLogs(network, params)\n return this.deps.rpc(network, method, params)\n }\n\n if (SIGNING_METHODS.has(method)) {\n if (!this.deps.sign) throw new RouterError(RELAY_ERRORS.unsupportedMethod, `${method} is not available yet.`)\n if (!permission || permission.accounts.length === 0) throw new RouterError(RELAY_ERRORS.unauthorized, 'Connect the wallet first (eth_requestAccounts).')\n const visible = await this.visibleAccounts(permission)\n const named = namedAccount(method, params)\n const inactive = named !== undefined && permission.accounts.some((a) => a.toLowerCase() === named.toLowerCase()) && !visible.some((a) => a.toLowerCase() === named.toLowerCase())\n if (visible.length === 0 || inactive) {\n throw new RouterError(RELAY_ERRORS.unauthorized, 'The account this site asks for is not the wallet\\'s active account (or the wallet is locked). Switch to it in the wallet, or connect the active account (eth_requestAccounts).')\n }\n return this.deps.sign({ origin, network, method, params, accounts: visible })\n }\n\n throw new RouterError(RELAY_ERRORS.unsupportedMethod, `This wallet does not support ${method}.`)\n }\n\n /** What a connected origin sees right now: its permitted accounts that the wallet can expose (none while locked). */\n private async visibleAccounts(permission: OriginPermission | null): Promise<string[]> {\n if (!permission) return []\n const available = await this.deps.accounts()\n return permission.accounts.filter((a) => available.includes(a))\n }\n\n /** An unconnected origin's `eth_getLogs`: a block hash, or a range of at most {@link GETLOGS_MAX_SPAN_UNCONNECTED} blocks. */\n private async boundLogs(network: EvmNetwork, params: unknown[]): Promise<void> {\n const filter = (params[0] ?? {}) as { fromBlock?: unknown; toBlock?: unknown; blockHash?: unknown }\n if (typeof filter !== 'object' || filter === null) throw new RouterError(RELAY_ERRORS.invalidParams, 'eth_getLogs expects a filter object.')\n if (filter.blockHash !== undefined && filter.blockHash !== null) return\n let head: bigint | undefined\n const block = async (tag: unknown): Promise<bigint> => {\n if (tag === undefined || tag === null || tag === 'latest' || tag === 'pending' || tag === 'safe' || tag === 'finalized') {\n head ??= BigInt(String(await this.deps.rpc(network, 'eth_blockNumber', [])))\n return head\n }\n if (tag === 'earliest') return 0n\n if (typeof tag === 'string' && /^0x[0-9a-fA-F]{1,16}$/.test(tag)) return BigInt(tag)\n throw new RouterError(RELAY_ERRORS.invalidParams, 'eth_getLogs: fromBlock / toBlock must be a block tag or a hex block number.')\n }\n const from = await block(filter.fromBlock)\n const to = await block(filter.toBlock)\n if (to - from > BigInt(GETLOGS_MAX_SPAN_UNCONNECTED)) {\n throw new RouterError(RELAY_ERRORS.limitExceeded, `eth_getLogs over more than ${GETLOGS_MAX_SPAN_UNCONNECTED} blocks is answered for connected sites only; narrow the range or connect the wallet.`)\n }\n }\n\n /**\n * Connected and unlocked → the accounts; otherwise the approval window (which\n * unlocks first when needed) picks them, and they are ADDED to this origin's\n * grant (other origins are untouched). Emits `connect` + `accountsChanged`.\n */\n private async connect(origin: string, network: EvmNetwork): Promise<string[]> {\n const existing = await this.visibleAccounts(await this.deps.permissions.get(origin))\n if (existing.length) return existing\n const chosen = await this.deps.approvals.request<unknown>({ origin, chain: network.caip2, kind: 'connect', payload: { accounts: await this.deps.accounts() } satisfies ConnectApproval })\n const available = await this.deps.accounts()\n const accounts = Array.isArray(chosen) ? chosen.filter((a): a is string => typeof a === 'string' && available.includes(a)) : []\n if (accounts.length === 0) throw new ReviewDeclined('No account was selected.')\n await this.deps.permissions.grant(origin, accounts, network.caip2)\n this.deps.emit(origin, 'connect', { chainId: chainHex(network.caip2) })\n this.deps.emit(origin, 'accountsChanged', accounts)\n return accounts\n }\n\n async disconnect(origin: string): Promise<void> {\n if (!(await this.deps.permissions.get(origin))) return\n await this.deps.permissions.disconnect(origin)\n this.deps.emit(origin, 'accountsChanged', [])\n this.deps.emit(origin, 'disconnect', { code: RELAY_ERRORS.disconnected, message: 'The wallet disconnected this site.' })\n }\n\n private async switchChain(origin: string, from: EvmNetwork, to: EvmNetwork, approved = false): Promise<void> {\n if (from.caip2 === to.caip2) return\n const permission = await this.deps.permissions.get(origin)\n if (!permission) throw new RouterError(RELAY_ERRORS.unauthorized, 'Connect the wallet first (eth_requestAccounts).')\n if (!approved) await this.deps.approvals.request({ origin, chain: from.caip2, kind: 'switch-chain', payload: { from, to } satisfies SwitchChainApproval })\n await this.deps.permissions.setChain(origin, to.caip2)\n this.deps.emit(origin, 'chainChanged', chainHex(to.caip2))\n }\n}\n\n/** The address a signing request names (`from` / the signer), when it names one. */\nfunction namedAccount(method: string, params: unknown[]): string | undefined {\n const addr = (x: unknown) => (typeof x === 'string' && /^0x[0-9a-fA-F]{40}$/.test(x) ? x : undefined)\n if (method === 'personal_sign') return addr(params[1]) ?? addr(params[0])\n if (method === 'eth_sendTransaction') return addr((params[0] as { from?: unknown } | undefined)?.from)\n return addr(params[0])\n}\n\nconst permissionDescriptor = (origin: string, accounts: string[]) => ({\n id: crypto.randomUUID(),\n parentCapability: 'eth_accounts',\n invoker: origin,\n caveats: [{ type: 'restrictReturnedAccounts', value: [...accounts] }],\n date: Date.now(),\n})\n","/**\n * Sign-In with Ethereum (EIP-4361) messages, parsed so the sheet can say what a\n * `personal_sign` really is and check the fields a phishing site would lie\n * about: the domain (scheme + host) must be the site asking, the address must\n * be the signing account, the chain must be the site's, the message must not be\n * expired or not-yet-valid, and the nonce must look like one (replay).\n *\n * Everything here is a WARNING: the sheet turns problems into warn checks and\n * the user can still sign. Whenever the first line is an EIP-4361 header the\n * text is treated as a sign-in (scan F9) — a message whose remaining fields do\n * not parse is reported as malformed instead of silently becoming a plain\n * message without the cross-site check.\n */\nimport type { OriginVia } from './approvals.js'\n\nexport interface SiweMessage {\n /** As written in the header: `host[:port]`, optionally prefixed by `scheme://`. */\n domain: string\n address: string\n statement?: string\n uri: string\n version: string\n chainId: number\n nonce: string\n issuedAt: string\n expirationTime?: string\n notBefore?: string\n requestId?: string\n resources: string[]\n}\n\nexport interface SiweInfo {\n message: SiweMessage\n /** Human lines, each a reason the sheet should warn; empty = the sign-in is consistent with the request. */\n problems: string[]\n /** The header said \"sign-in\" but the rest did not parse as EIP-4361 (`message` then holds what could be read). */\n malformed?: boolean\n /**\n * Set when the sign-in names another site than the one asking (its host differs from the page's\n * host, or from a WalletConnect Verify-attested URL): `domain` as written in the message, `origin`\n * the asking site as `scheme://host`. A sheet should make this its headline, not one warning among many.\n */\n crossSite?: { domain: string; origin: string }\n}\n\n/**\n * Characters a sign-in message is refused for: bidi controls (ALM, LRM / RLM, embeddings, overrides,\n * isolates), zero-width space / joiners, word joiner and invisible operators, BOM — they can make the\n * domain or the statement read differently from the bytes that are signed.\n */\nexport const SIWE_FORBIDDEN_CHARS = /[\\u061c\\u200b-\\u200f\\u202a-\\u202e\\u2060-\\u2064\\u2066-\\u2069\\ufeff]/\n\nexport interface SiweContext {\n /** The page that asked, as the browser recorded it (`https://…`), or a transport pseudo-origin (`wc:<topic>`). */\n origin: string\n /** The signing address. */\n account: string\n /** The site's chain. */\n chainId: number\n now?: number\n /** Transport note for pseudo-origins (WalletConnect): the dApp's claimed URL and what Verify said about it. */\n via?: OriginVia\n}\n\n/** First line of an EIP-4361 message; the \"Ethereum account\" literal is what makes it one. */\nconst HEADER_LINE = /^(?<domain>[^\\n]+?) wants you to sign in with your Ethereum account:(?:\\n|$)/\nconst ADDRESS_LINE = /^0x[0-9a-fA-F]{40}$/\nconst FIELD = /^([A-Za-z ]+): (.*)$/\n\ninterface Parsed { message: SiweMessage; missing: string[] }\n\n/** Tolerant parse: `null` only when the first line is not an EIP-4361 header. */\nfunction parseLoose(text: string): Parsed | null {\n const head = HEADER_LINE.exec(text)\n if (!head?.groups) return null\n const lines = text.slice(head[0].length).split('\\n')\n const missing: string[] = []\n const addressLine = lines.shift() ?? ''\n const address = ADDRESS_LINE.test(addressLine) ? addressLine : ''\n if (!address) missing.push('address')\n // Between the address and the `URI:` line: blank lines and at most one statement line.\n // Covers `addr\\n\\nstatement\\n\\nURI`, `addr\\n\\n\\nURI` (no statement, the ABNF form) and `addr\\n\\nURI` (older libraries).\n const uriAt = lines.findIndex((l) => l.startsWith('URI: '))\n const between = (uriAt < 0 ? lines : lines.slice(0, uriAt)).filter((l) => l !== '')\n let statement: string | undefined\n if (uriAt >= 0) {\n if (between.length === 1 && !FIELD.test(between[0]!)) statement = between[0]\n else if (between.length > 0) missing.push('statement layout')\n }\n const fields: Record<string, string> = {}\n const resources: string[] = []\n for (const line of uriAt < 0 ? [] : lines.slice(uriAt)) {\n if (line.startsWith('- ')) { resources.push(line.slice(2)); continue }\n const m = FIELD.exec(line)\n if (m && !(m[1]! in fields)) fields[m[1]!] = m[2]!\n }\n const chainId = Number(fields['Chain ID'])\n if (!fields.URI) missing.push('URI')\n if (!fields.Version) missing.push('Version')\n if (fields['Chain ID'] === undefined || !Number.isInteger(chainId)) missing.push('Chain ID')\n if (!fields.Nonce) missing.push('Nonce')\n if (!fields['Issued At']) missing.push('Issued At')\n const message: SiweMessage = { domain: head.groups.domain!, address, uri: fields.URI ?? '', version: fields.Version ?? '', chainId: Number.isInteger(chainId) ? chainId : NaN, nonce: fields.Nonce ?? '', issuedAt: fields['Issued At'] ?? '', resources }\n if (statement) message.statement = statement\n if (fields['Expiration Time']) message.expirationTime = fields['Expiration Time']\n if (fields['Not Before']) message.notBefore = fields['Not Before']\n if (fields['Request ID']) message.requestId = fields['Request ID']\n return { message, missing }\n}\n\n/** `null` when the text is not a well-formed EIP-4361 message (see {@link describeSiwe} for the tolerant form the sheet uses). */\nexport function parseSiwe(text: string): SiweMessage | null {\n const p = parseLoose(text)\n return p && p.missing.length === 0 ? p.message : null\n}\n\ninterface Where { scheme: string; host: string }\n\n/** `scheme://host[:port]` or bare `host[:port]` (scheme defaults to https, as EIP-4361 says). */\nfunction whereOf(s: string): Where | null {\n try {\n if (!s.includes('://')) {\n // A URL parser, never fetched — and written as the one dynamic `https://` prefix the extension's host gate knows.\n const host = new URL(`https://${s}`).host.toLowerCase()\n return host ? { scheme: 'https', host } : null\n }\n const u = new URL(s)\n return u.host ? { scheme: u.protocol.replace(/:$/, '').toLowerCase(), host: u.host.toLowerCase() } : null\n } catch { return null }\n}\n\n/** A browser origin with a host the wallet can vouch for: http(s) only — `wc:<topic>` and other pseudo-origins have none. */\nfunction originWhere(origin: string): Where | null {\n try {\n const u = new URL(origin)\n return (u.protocol === 'https:' || u.protocol === 'http:') && u.host ? { scheme: u.protocol.slice(0, -1), host: u.host.toLowerCase() } : null\n } catch { return null }\n}\n\n/** Loopback / `*.localhost` (dev servers): plain http is normal there, so no scheme warnings. Takes `host[:port]`. */\nexport function isLocalHost(host: string): boolean {\n const h = host.toLowerCase().replace(/:\\d+$/, '')\n return h === 'localhost' || h === '127.0.0.1' || h === '[::1]' || h.endsWith('.localhost')\n}\n\n/** The checks; `origin` is the page that asked (as the browser recorded it), `account` the signing address, `chainId` the site's chain. */\nexport function siweProblems(m: SiweMessage, ctx: SiweContext): string[] {\n const out: string[] = []\n const domain = whereOf(m.domain)\n let site = originWhere(ctx.origin)\n if (!site) {\n // No browser-recorded host (WalletConnect `wc:<topic>`): only a Verify-attested claim naming the same host counts (scan F10).\n const claimed = ctx.via?.verify === 'VALID' && !ctx.via.scam ? whereOf(ctx.via.url) : null\n if (claimed && domain && claimed.host === domain.host) site = claimed\n else out.push(`The wallet cannot verify which site is asking; this sign-in for ${m.domain} may be replayed there.`)\n }\n if (site) {\n // Scheme as well as host (scan F20/F21): an http:// twin of the site must not collect sign-ins valid for the https one.\n const local = isLocalHost(site.host)\n if (site.scheme === 'http' && !local) out.push(`This sign-in is requested by an insecure page (${site.scheme}://${site.host}); anyone on the network can read or change it and replay the signature on the https site.`)\n if (!domain || domain.host !== site.host) out.push(`The sign-in names ${m.domain} but the request comes from ${site.host} — a sign-in meant for another site would be replayable there.`)\n else if (!local && domain.scheme !== site.scheme) out.push(`The sign-in is for ${domain.scheme}://${domain.host} but the request comes from ${site.scheme}://${site.host}.`)\n const uri = m.uri ? whereOf(m.uri) : null\n if (uri && uri.host !== site.host) out.push(`The URI ${m.uri} is not on ${site.host}.`)\n else if (uri && !local && (uri.scheme === 'http' || uri.scheme === 'https') && uri.scheme !== site.scheme) out.push(`The URI ${m.uri} uses ${uri.scheme}:// but the request comes from ${site.scheme}://${site.host}.`)\n }\n if (m.address && m.address.toLowerCase() !== ctx.account.toLowerCase()) out.push(`The sign-in is for ${m.address}, not the account that would sign (${ctx.account}).`)\n if (Number.isInteger(m.chainId) && m.chainId !== ctx.chainId) out.push(`The sign-in is for chain ${m.chainId}; this site is on chain ${ctx.chainId}.`)\n if (m.version && m.version !== '1') out.push(`Unknown SIWE version ${m.version}.`)\n if (m.nonce && (m.nonce.length < 8 || !/^[A-Za-z0-9]+$/.test(m.nonce))) out.push('The nonce is too short to protect against replay.')\n const now = ctx.now ?? Date.now()\n const exp = m.expirationTime ? Date.parse(m.expirationTime) : NaN\n if (m.expirationTime && (Number.isNaN(exp) || exp <= now)) out.push('The sign-in has already expired.')\n const nbf = m.notBefore ? Date.parse(m.notBefore) : NaN\n if (m.notBefore && (Number.isNaN(nbf) || nbf > now)) out.push('The sign-in is not valid yet (Not Before is in the future).')\n if (m.issuedAt) {\n const iat = Date.parse(m.issuedAt)\n if (Number.isNaN(iat)) out.push('Issued At is not a date.')\n else if (iat > now + 5 * 60_000) out.push('Issued At is in the future.')\n }\n return out\n}\n\n/**\n * The asking site when the sign-in names a different host: the browser-recorded origin, or for a\n * WalletConnect pseudo-origin the URL Verify attested (VALID, not scam). `null` when the hosts agree\n * or when no site can be vouched for at all (that case is a separate \"cannot verify\" problem).\n */\nexport function siweCrossSite(m: SiweMessage, ctx: SiweContext): { domain: string; origin: string } | null {\n const site = originWhere(ctx.origin) ?? (ctx.via?.verify === 'VALID' && !ctx.via.scam ? whereOf(ctx.via.url) : null)\n if (!site) return null\n const domain = whereOf(m.domain)\n return !domain || domain.host !== site.host ? { domain: m.domain, origin: `${site.scheme}://${site.host}` } : null\n}\n\n/** `null` only when the text does not start with an EIP-4361 header; a header with unreadable fields comes back with a \"malformed sign-in message\" problem. */\nexport function describeSiwe(text: string, ctx: SiweContext): SiweInfo | null {\n const p = parseLoose(text)\n if (!p) return null\n const problems = siweProblems(p.message, ctx)\n const cross = siweCrossSite(p.message, ctx)\n const crossSite = cross ? { crossSite: cross } : {}\n if (p.missing.length === 0) return { message: p.message, problems, ...crossSite }\n return { message: p.message, problems: [`This is a malformed sign-in message (EIP-4361): ${p.missing.join(', ')} missing or unreadable — check the site before signing.`, ...problems], malformed: true, ...crossSite }\n}\n","/**\n * Signing requests from dApps (and from the wallet's own Send): classification,\n * transaction preparation, the review stop, the signature.\n *\n * Classification is Vaulty's `signingRequest` (mobile/lib/browser.ts): the\n * address a page names must be one the user connected; typed data bound to\n * another chain than the one the site is on is refused (4901); a transaction\n * must have a `to` (no deployments) and a `chainId`, when given, equal to the\n * site's chain; `eth_sign` never reaches here (the router refuses it).\n *\n * Preparation fills nonce, gas and fees from the wallet's own RPC (never the\n * page's): EIP-1559 cap = 2 × base fee + tip with the tip floored at 0.1 gwei\n * (Vaulty's `evmFees`), legacy `gasPrice` where a chain has no base fee, gas =\n * the page's limit or `eth_estimateGas` × 1.2.\n *\n * The nonce the sheet shows is a guess: the one signed is read AFTER the\n * approval, under a per-account lock that also covers the broadcast, and is\n * never below the wallet's own next nonce (a node may not see the previous\n * send yet). Two requests reviewed at once therefore get consecutive nonces.\n * The fee caps signed are the ones shown, unless the network outgrew them\n * while the sheet was open (EIP-1559: base fee + tip above the shown cap;\n * legacy: a higher gas price) — then the user is asked again with the new\n * numbers (`repriced: true`, `repricedFrom` = the max fee shown before) on a\n * follow-up sheet the queue limits do not refuse, at most {@link MAX_FEE_REASKS}\n * times in a row; declining it signs nothing. A new max fee above the wallet's\n * own ceiling ({@link SignDeps.feeCeiling}) is refused without a sheet.\n *\n * The review payload ({@link SignApproval}) carries what the window shows: the\n * classified request, the prepared fields, the fee, and the preview the wallet\n * attached (tx-preview-evm: decode, simulation, balance changes, checks). Only\n * after the user approves does {@link SignDeps.signerFor} open the key; the\n * handle is disposed (zeroized) in `finally`, the raw transaction goes out via\n * `eth_sendRawTransaction` on the wallet's RPC.\n */\nimport { ApprovalQueue, type OriginVia } from './approvals.js'\nimport type { EvmNetwork } from './networks.js'\nimport { RELAY_ERRORS, type RelayError } from './relay.js'\nimport { RouterError, type RouterDeps } from './router.js'\nimport { SIWE_FORBIDDEN_CHARS, describeSiwe, type SiweInfo } from './siwe.js'\n\n/** The account nonce an RPC reported, refused when it is not a safe integer (a broken or hostile RPC). */\nconst safeNonce = (n: bigint): number => {\n if (n < 0n || n > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error(`The RPC returned an impossible nonce (${n}).`)\n return Number(n.toString())\n}\n\nexport type SignRequestInfo =\n | { kind: 'sign-message'; method: 'personal_sign'; account: string; /** Decoded text when printable, else the hex; invisible / direction-changing characters shown as `⟨U+XXXX⟩` ({@link revealHidden}). */ text: string; /** What is actually signed (hex or utf-8 string). */ raw: string; /** Parsed Sign-In with Ethereum (EIP-4361) with the checks against the asking origin, when the text is one. */ siwe?: SiweInfo; /** `text` had invisible or direction-changing characters (now escaped): the sheet should warn. */ hiddenChars?: true; /** The message is exactly 32 bytes (`0x` + 64 hex): a blind hash signature that CoW Protocol (`ethsign`), Safe (v > 30) and others accept as an order or a transfer. Only with the wallet's opt-in ({@link SignDeps.allowBlindHash}); the sheet must make it a danger screen. */ blindHash?: true }\n | { kind: 'sign-typed-data'; method: string; account: string; /** Pretty-printed JSON, invisible / direction-changing characters escaped. */ text: string; typedData: TypedData; /** `text` had invisible or direction-changing characters (now escaped): the sheet should warn. */ hiddenChars?: true }\n | { kind: 'send-transaction'; method: 'eth_sendTransaction'; account: string; tx: { to: string; value: string; data: string | null; gas: string | null } }\n\nexport interface TypedData {\n domain: Record<string, unknown>\n types: Record<string, Array<{ name: string; type: string }>>\n message: Record<string, unknown>\n primaryType?: string\n}\n\nexport interface PreparedTx {\n chainId: number\n nonce: number\n gasLimit: string\n /** EIP-1559 fields, or `gasPrice` on legacy-fee chains. All 0x hex. */\n maxFeePerGas?: string\n maxPriorityFeePerGas?: string\n gasPrice?: string\n /** gasLimit × max fee, base units. */\n maxFee: string\n /**\n * Set when the page chose the gas limit and the wallet's own `eth_estimateGas` answered: the estimate\n * (0x hex) and whether the page's limit is above max(estimate × 1.5, estimate + 50 000) — then the sheet\n * should warn with the max fee. The page's limit is still the one signed.\n */\n gasCheck?: { estimate: string; excessive: boolean }\n}\n\n/** The approval window's payload for the three signing kinds. */\nexport interface SignApproval {\n request: SignRequestInfo\n network: EvmNetwork\n prepared?: PreparedTx\n /** A second sheet for the same transaction: the network's fee outgrew the cap the first one showed. */\n repriced?: true\n /** With `repriced`: the max fee (`prepared.maxFee`, base units) the sheet before this one showed. */\n repricedFrom?: string\n /** What the wallet attached (tx-preview-evm `TxPreview`, typed-data description…). */\n preview: unknown\n}\n\nexport interface EvmSigner {\n signMessage(message: string | Uint8Array): Promise<string>\n signTypedData(typed: TypedData): Promise<string>\n /** Fully specified tx (chainId, nonce, gas, fees) → signed raw transaction. */\n signTransaction(tx: { chainId: number; nonce: number; to: string; value: bigint; data: string; gasLimit: bigint; maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint; gasPrice?: bigint }): Promise<string>\n}\n\nexport interface SignDeps {\n approvals: ApprovalQueue\n rpc(network: EvmNetwork, method: string, params: unknown[]): Promise<unknown>\n /** Opens the key for `address`; `dispose()` zeroizes it. */\n signerFor(address: string, network: EvmNetwork): Promise<{ signer: EvmSigner; dispose(): void }>\n /** Review data for the window (errors inside are the wallet's to swallow → `null`). */\n preview?(input: { network: EvmNetwork; request: SignRequestInfo; accounts: string[] }): Promise<unknown>\n /** Tip floor per chain id in wei (default 0.1 gwei everywhere). */\n tipFloor?: (chainId: number) => bigint\n /**\n * Whether a personal_sign of a raw 32-byte hash may reach the sheet (read per request). Default: refused — a\n * blind hash signature can be a CoW order or a Safe transaction paying someone else (extension audit E55).\n */\n allowBlindHash?: () => boolean | Promise<boolean>\n /**\n * The most one transaction may cost in fee on `network` (base units), when the wallet has such a limit\n * (the one its signer enforces). A fee that rose above it after the sheet is refused right away, with\n * no second sheet. The first sheet is not checked here: the signer is the guard for it.\n */\n feeCeiling?: (network: EvmNetwork) => bigint | undefined\n}\n\n/** How many times in a row one transaction's fee may be asked again ({@link SignApproval.repriced}); the next rise stops the request, nothing signed. */\nexport const MAX_FEE_REASKS = 3\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/\nconst HEX = /^0x([0-9a-fA-F]{2})*$/\nconst lc = (s: string) => s.toLowerCase()\n\n/**\n * Characters that change how text displays without showing themselves: every format character\n * (Unicode Cf — bidi embeddings / overrides / isolates, LRM / RLM / ALM, zero-width space / joiners,\n * word joiner, BOM, soft hyphen, tag characters…), line / paragraph separators, the invisible Hangul\n * fillers, and C0 / C1 controls other than tab, newline and carriage return.\n */\nconst INVISIBLE = /[\\p{Cf}\\u2028\\u2029\\u115f\\u1160\\u3164\\uffa0\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]/gu\n\n/**\n * Text for a review sheet: every invisible or direction-changing character replaced by a visible\n * `⟨U+XXXX⟩`, so the order on screen is the order of the bytes (a right-to-left override can make\n * \"exe.gnp\" read as \"png.exe\"). `hidden` says whether anything was replaced — the sheet should warn.\n */\nexport function revealHidden(text: string): { text: string; hidden: boolean } {\n let hidden = false\n const out = text.replace(INVISIBLE, (c) => {\n hidden = true\n return `⟨U+${c.codePointAt(0)!.toString(16).toUpperCase().padStart(4, '0')}⟩`\n })\n return { text: out, hidden }\n}\n\n/**\n * Vaulty's `messageText`: hex that decodes to printable text is shown decoded; binary payloads stay hex.\n * Invisible and direction-changing characters come back escaped ({@link revealHidden}).\n */\nexport function messageText(value: unknown): string {\n return shownMessage(value).text\n}\n\n/** {@link messageText} plus whether it escaped anything. */\nfunction shownMessage(value: unknown): { text: string; hidden: boolean } {\n if (typeof value !== 'string') return { text: '', hidden: false }\n if (!HEX.test(value)) return revealHidden(value)\n try {\n const bytes = Uint8Array.from(value.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16))\n const s = new TextDecoder('utf-8', { fatal: true }).decode(bytes)\n return /^[\\x09\\x0a\\x0d\\x20-\\x7e\\u00a0-\\uffff]*$/.test(s) ? revealHidden(s) : { text: value, hidden: false }\n } catch {\n return { text: value, hidden: false }\n }\n}\n\n/**\n * The message as the signer will sign it: hex decoded when it is valid UTF-8, whatever\n * its printability (scan 2026-10-23 F7 — the SIWE checks must read the bytes that get\n * signed, not the hex fallback `messageText` shows for unprintable text).\n */\nexport function decodedMessage(value: unknown): string | null {\n if (typeof value !== 'string') return null\n if (!HEX.test(value)) return value\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(Uint8Array.from(value.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16)))\n } catch {\n return null\n }\n}\n\n/** Control characters other than tab / newline / carriage return — never part of an honest EIP-4361 message. */\nconst HIDDEN_CONTROL = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]/\n\nconst err = (code: number, message: string): RelayError => ({ code, message })\n\n/** Signing method + params → what the window reviews, or the error to answer with. */\n/** A personal_sign message that is a raw 32-byte hash: what an `ethsign`-style verifier turns into an order or a transfer. */\nconst BLIND_HASH = /^0x[0-9a-fA-F]{64}$/\n\nexport function classifySignRequest(input: { network: EvmNetwork; method: string; params: unknown[]; accounts: string[]; /** The asking page (browser-recorded) — needed for the SIWE domain check. */ origin?: string; /** Transport note for pseudo-origins (WalletConnect Verify), for the SIWE check. */ via?: OriginVia; now?: number; /** Let a 32-byte hash personal_sign reach the sheet (marked `blindHash`) instead of refusing it. Default false. */ allowBlindHash?: boolean }): SignRequestInfo | RelayError {\n const { method, params } = input\n const owned = new Set(input.accounts.map(lc))\n const ours = (a: unknown): a is string => typeof a === 'string' && ADDRESS.test(a) && owned.has(lc(a))\n const checksum = (a: string) => input.accounts.find((x) => lc(x) === lc(a)) ?? a\n\n if (method === 'personal_sign') {\n // [message, address] per spec; some dApps send [address, message].\n let [msg, addr] = params\n if (ours(msg) && !ours(addr)) [msg, addr] = [addr, msg]\n if (!ours(addr)) return err(RELAY_ERRORS.unauthorized, 'personal_sign for an address this wallet does not hold.')\n if (typeof msg !== 'string') return err(RELAY_ERRORS.invalidParams, 'personal_sign expects a message string.')\n // 32 raw bytes are signed as an EIP-191 \"\\n32\" message: CoW Protocol's ethsign orders, Safe owner signatures (v > 30)…\n const blindHash = BLIND_HASH.test(msg)\n if (blindHash && !input.allowBlindHash) return err(RELAY_ERRORS.unsupportedMethod, 'This site asks you to sign a raw 32-byte hash (blind signing). It can be a swap order or a transfer (e.g. CoW Protocol) paying someone else, so this wallet refuses it. \"Allow blind hash signatures\" in Options turns on a review for such requests.')\n const shown = shownMessage(msg)\n const text = shown.text\n const signed = decodedMessage(msg) ?? text\n const siwe = input.origin ? describeSiwe(signed, { origin: input.origin, account: checksum(addr), chainId: input.network.chainId, ...(input.via ? { via: input.via } : {}), ...(input.now !== undefined ? { now: input.now } : {}) }) : null\n // A sign-in message with hidden control characters would show as an opaque hex blob while\n // a lenient verifier still accepts it: refuse it outright.\n if (siwe && HIDDEN_CONTROL.test(signed)) return err(RELAY_ERRORS.invalidParams, 'This sign-in message contains hidden control characters — refused.')\n // Bidi controls and zero-width characters can make the domain or statement read differently from what is signed.\n if (siwe && SIWE_FORBIDDEN_CHARS.test(signed)) return err(RELAY_ERRORS.invalidParams, 'This sign-in message contains invisible or text-direction characters — refused.')\n return { kind: 'sign-message', method, account: checksum(addr), text, raw: msg, ...(siwe ? { siwe } : {}), ...(shown.hidden ? { hiddenChars: true as const } : {}), ...(blindHash ? { blindHash: true as const } : {}) }\n }\n\n if (method === 'eth_signTypedData_v4' || method === 'eth_signTypedData_v3' || method === 'eth_signTypedData') {\n const [addr, data] = params\n if (!ours(addr)) return err(RELAY_ERRORS.unauthorized, 'signTypedData for an address this wallet does not hold.')\n let parsed: TypedData\n try {\n parsed = (typeof data === 'string' ? JSON.parse(data) : data) as TypedData\n } catch {\n return err(RELAY_ERRORS.invalidParams, 'Typed data is not valid JSON.')\n }\n if (!parsed || typeof parsed !== 'object' || typeof parsed.domain !== 'object' || typeof parsed.types !== 'object' || typeof parsed.message !== 'object') {\n return err(RELAY_ERRORS.invalidParams, 'Typed data needs domain, types and message.')\n }\n const cid = parsed.domain.chainId\n if (cid !== undefined && cid !== null && Number(cid) !== input.network.chainId) {\n // A domain bound to another chain than the one the site is on is the classic cross-chain replay / phishing shape.\n return err(RELAY_ERRORS.chainDisconnected, `Typed data is for chain ${String(cid)}; this site is on ${input.network.name} (${input.network.chainId}).`)\n }\n const shown = revealHidden(JSON.stringify(parsed, bigintSafe, 2))\n return { kind: 'sign-typed-data', method, account: checksum(addr), text: shown.text, typedData: parsed, ...(shown.hidden ? { hiddenChars: true as const } : {}) }\n }\n\n if (method === 'eth_sendTransaction') {\n const tx = (params[0] ?? {}) as { from?: unknown; to?: unknown; value?: unknown; data?: unknown; gas?: unknown; gasLimit?: unknown; chainId?: unknown; type?: unknown; authorizationList?: unknown }\n if (!ours(tx.from)) return err(RELAY_ERRORS.unauthorized, 'Transaction from an address this wallet does not hold.')\n // EIP-7702: a delegation hands the whole account to a contract; >80 % of early delegations went to sweepers. Sites never get one from this wallet.\n if ((Array.isArray(tx.authorizationList) && tx.authorizationList.length > 0) || tx.type === '0x4' || tx.type === 4) return err(RELAY_ERRORS.unsupportedMethod, 'EIP-7702 delegations (authorizationList / type 4) are never signed for a site by this wallet.')\n if (typeof tx.to !== 'string' || !ADDRESS.test(tx.to)) return err(RELAY_ERRORS.invalidParams, 'Contract deployment is not supported (a transaction needs a valid `to`).')\n if (tx.chainId !== undefined && tx.chainId !== null && Number(tx.chainId) !== input.network.chainId) return err(RELAY_ERRORS.chainDisconnected, 'Transaction chainId differs from the selected chain.')\n let value: string\n try {\n value = BigInt((tx.value as string | number | bigint | undefined) ?? 0).toString()\n } catch {\n return err(RELAY_ERRORS.invalidParams, 'Bad transaction value.')\n }\n const data = typeof tx.data === 'string' && tx.data !== '0x' ? tx.data : null\n if (data !== null && !HEX.test(data)) return err(RELAY_ERRORS.invalidParams, 'Transaction data is not hex.')\n const gasRaw = tx.gas ?? tx.gasLimit\n const gas = typeof gasRaw === 'string' && /^0x[0-9a-fA-F]+$/.test(gasRaw) ? gasRaw : null\n return { kind: 'send-transaction', method, account: checksum(tx.from), tx: { to: tx.to, value, data, gas } }\n }\n\n return err(RELAY_ERRORS.unsupportedMethod, `This wallet does not support ${method}.`)\n}\n\nconst bigintSafe = (_k: string, v: unknown) => (typeof v === 'bigint' ? v.toString() : v)\nconst hex = (n: bigint) => `0x${n.toString(16)}`\nconst big = (v: unknown): bigint => BigInt(v as string)\nconst MIN_TIP_WEI = 100_000_000n // 0.1 gwei\n\ntype Fees = { base: bigint; tip: bigint } | { gasPrice: bigint }\n\n/** The network's fee right now: base fee + floored tip, or the legacy gas price. */\nasync function readFees(deps: Pick<SignDeps, 'rpc' | 'tipFloor'>, network: EvmNetwork, block?: { baseFeePerGas?: string | null } | null): Promise<Fees> {\n const b = block === undefined ? ((await deps.rpc(network, 'eth_getBlockByNumber', ['latest', false])) as { baseFeePerGas?: string | null } | null) : block\n const base = b?.baseFeePerGas != null ? big(b.baseFeePerGas) : null\n if (base === null) return { gasPrice: big(await deps.rpc(network, 'eth_gasPrice', [])) }\n const floor = deps.tipFloor?.(network.chainId) ?? MIN_TIP_WEI\n const nodeTip = await (deps.rpc(network, 'eth_maxPriorityFeePerGas', []) as Promise<string>).then(big).catch(() => 0n)\n return { base, tip: nodeTip > floor ? nodeTip : floor }\n}\n\nfunction withFees(chainId: number, nonce: number, gasLimit: bigint, fees: Fees): PreparedTx {\n if ('gasPrice' in fees) return { chainId, nonce, gasLimit: hex(gasLimit), gasPrice: hex(fees.gasPrice), maxFee: (gasLimit * fees.gasPrice).toString() }\n const maxFeePerGas = fees.base * 2n + fees.tip\n return { chainId, nonce, gasLimit: hex(gasLimit), maxFeePerGas: hex(maxFeePerGas), maxPriorityFeePerGas: hex(fees.tip), maxFee: (gasLimit * maxFeePerGas).toString() }\n}\n\n/** True when `shown` can no longer pay for inclusion at `now` (the user must see the new numbers). */\nfunction outgrown(shown: PreparedTx, now: Fees): boolean {\n if ('gasPrice' in now) return shown.gasPrice === undefined || now.gasPrice > big(shown.gasPrice)\n return shown.maxFeePerGas === undefined || now.base + now.tip > big(shown.maxFeePerGas)\n}\n\n/**\n * A cap more than this many times what the network asks now is lowered to the current fees at\n * signing. Signers hold a caller-set fee rate against the network's quote and refuse one far above\n * it, so a cap shown during a spike that has since passed would be refused after the user said yes.\n */\nconst STALE_FEE_FACTOR = 4n\n\n/** True when `shown` sits far above `fresh` (a fee spike passed while the sheet was open). */\nfunction overpriced(shown: PreparedTx, fresh: PreparedTx): boolean {\n if (shown.gasPrice !== undefined && fresh.gasPrice !== undefined) return big(shown.gasPrice) > STALE_FEE_FACTOR * big(fresh.gasPrice)\n if (shown.maxFeePerGas !== undefined && fresh.maxFeePerGas !== undefined) return big(shown.maxFeePerGas) > STALE_FEE_FACTOR * big(fresh.maxFeePerGas)\n return false\n}\n\n/** A page's gas limit above max(estimate × 1.5, estimate + 50 000) is flagged on the sheet (never replaced). */\nexport function gasLimitExcessive(limit: bigint, estimate: bigint): boolean {\n const a = (estimate * 3n) / 2n\n const b = estimate + 50_000n\n return limit > (a > b ? a : b)\n}\n\n/**\n * Nonce, gas, fees from the wallet's RPC. A gas limit the page set is used as given, but it is checked\n * against the wallet's own estimate ({@link PreparedTx.gasCheck}); a failed estimate (a call that\n * reverts now) leaves the check out instead of failing the request.\n */\nexport async function prepareTransaction(deps: Pick<SignDeps, 'rpc' | 'tipFloor'>, network: EvmNetwork, from: string, tx: { to: string; value: string; data: string | null; gas: string | null }): Promise<PreparedTx> {\n const call = { from, to: tx.to, value: hex(BigInt(tx.value)), ...(tx.data ? { data: tx.data } : {}) }\n const estimate = () => deps.rpc(network, 'eth_estimateGas', [call])\n const [nonceHex, block, gasHex] = await Promise.all([\n deps.rpc(network, 'eth_getTransactionCount', [from, 'pending']),\n deps.rpc(network, 'eth_getBlockByNumber', ['latest', false]) as Promise<{ baseFeePerGas?: string | null } | null>,\n tx.gas ? estimate().then((v) => v, () => null) : estimate(),\n ])\n const nonce = safeNonce(big(nonceHex))\n if (!tx.gas) {\n const estimated = big(gasHex)\n return withFees(network.chainId, nonce, (estimated * 120n + 99n) / 100n, await readFees(deps, network, block))\n }\n const limit = big(tx.gas)\n const prepared = withFees(network.chainId, nonce, limit, await readFees(deps, network, block))\n let est: bigint | null = null\n try { est = typeof gasHex === 'string' ? big(gasHex) : null } catch { est = null }\n return est !== null && est > 0n ? { ...prepared, gasCheck: { estimate: hex(est), excessive: gasLimitExcessive(limit, est) } } : prepared\n}\n\n/** The router's `sign` hook: classify → prepare → review → sign (→ broadcast). */\nexport function createSignHandler(deps: SignDeps): NonNullable<RouterDeps['sign']> {\n // Per chain + account: the tail of the sign-and-broadcast queue and the next nonce this worker\n // handed out. Memory only — a restarted service worker starts again from the node's count.\n const tails = new Map<string, Promise<unknown>>()\n const nextNonce = new Map<string, number>()\n const serial = <T>(key: string, fn: () => Promise<T>): Promise<T> => {\n const run = (tails.get(key) ?? Promise.resolve()).then(fn, fn)\n const tail = run.then(() => undefined, () => undefined)\n tails.set(key, tail)\n void tail.then(() => { if (tails.get(key) === tail) tails.delete(key) })\n return run\n }\n\n return async ({ origin, network, method, params, accounts }) => {\n const via = deps.approvals.viaFor(origin)\n const allowBlindHash = method === 'personal_sign' && deps.allowBlindHash ? await deps.allowBlindHash() : false\n const info = classifySignRequest({ network, method, params, accounts, origin, ...(via ? { via } : {}), ...(allowBlindHash ? { allowBlindHash: true } : {}) })\n if ('code' in info) throw RouterError.from(info)\n\n const prepared = info.kind === 'send-transaction' ? await prepareTransaction(deps, network, info.account, info.tx) : undefined\n const preview = deps.preview ? await deps.preview({ network, request: info, accounts }).catch(() => null) : null\n const payload: SignApproval = { request: info, network, ...(prepared ? { prepared } : {}), preview }\n await deps.approvals.request({ origin, chain: network.caip2, kind: info.kind, payload })\n\n if (info.kind === 'send-transaction') {\n const key = `${network.caip2}|${lc(info.account)}`\n return serial(key, async () => {\n let shown = prepared!\n let reasks = 0\n for (;;) {\n const [nonceHex, fees] = await Promise.all([deps.rpc(network, 'eth_getTransactionCount', [info.account, 'pending']), readFees(deps, network)])\n const local = nextNonce.get(key) ?? 0\n const nodeNonce = safeNonce(big(nonceHex))\n const nonce = nodeNonce > local ? nodeNonce : local\n if (outgrown(shown, fees)) {\n const next = withFees(network.chainId, nonce, big(shown.gasLimit), fees)\n const ceiling = deps.feeCeiling?.(network)\n if (ceiling !== undefined && BigInt(next.maxFee) > ceiling) throw new RouterError(RELAY_ERRORS.internal, `The network fee rose above the wallet's limit for ${network.name}; nothing was signed.`)\n if (reasks >= MAX_FEE_REASKS) throw new RouterError(RELAY_ERRORS.internal, 'The network fee kept rising while you were reviewing; nothing was signed. Try again later.')\n reasks++\n // The same transaction, approved once already: a follow-up sheet, not a new request of the site.\n await deps.approvals.request({ origin, chain: network.caip2, kind: info.kind, payload: { ...payload, prepared: next, repriced: true, repricedFrom: shown.maxFee } }, { followUp: true })\n shown = next\n continue // the network may have moved again while the second sheet was open\n }\n // A lower cap than the one approved needs no second sheet: the user pays at most what they saw.\n const fresh = withFees(network.chainId, nonce, big(shown.gasLimit), fees)\n if (overpriced(shown, fresh)) shown = fresh\n const handle = await deps.signerFor(info.account, network)\n let raw: string\n try {\n raw = await handle.signer.signTransaction({\n chainId: shown.chainId, nonce, to: info.tx.to, value: BigInt(info.tx.value), data: info.tx.data ?? '0x', gasLimit: BigInt(shown.gasLimit),\n ...(shown.gasPrice !== undefined ? { gasPrice: BigInt(shown.gasPrice) } : { maxFeePerGas: BigInt(shown.maxFeePerGas!), maxPriorityFeePerGas: BigInt(shown.maxPriorityFeePerGas!) }),\n })\n } finally {\n handle.dispose()\n }\n const hash = await deps.rpc(network, 'eth_sendRawTransaction', [raw])\n nextNonce.set(key, nonce + 1)\n return hash\n }\n })\n }\n\n const handle = await deps.signerFor(info.account, network)\n try {\n switch (info.kind) {\n case 'sign-message':\n return await handle.signer.signMessage(HEX.test(info.raw) ? Uint8Array.from(info.raw.slice(2).match(/../g) ?? [], (b) => Number.parseInt(b, 16)) : info.raw)\n case 'sign-typed-data':\n return await handle.signer.signTypedData(info.typedData)\n }\n } finally {\n handle.dispose()\n }\n }\n}\n","/**\n * Pre-approvals — the second half of Vaulty's `txGate` (mobile/lib/txGate.ts).\n * A flow that reviewed a WHOLE plan in one sheet (a swap: approvals + source\n * leg) registers one matcher per operation it is about to perform; the\n * reviewed account then lets exactly those operations through without a second\n * window, each once, within `ttlMs`, and only for the account that reviewed the\n * plan. Anything else still stops at the review.\n */\nexport type GatedOp = (\n | { kind: 'evm-tx'; caip2: string; to: string; data?: string; value: bigint }\n /** EIP-712 data about to be signed: `typedDataHash` is `typedDataHash(typed)` from `@anywalletkit/wallet-evm` — the digest the account signs. */\n | { kind: 'evm-typed-data'; caip2: string; typedDataHash: string }\n | { kind: 'solana-transfer'; to: string; amount: bigint; token?: string }\n | { kind: 'solana-tx'; to: string; value: bigint }\n | { kind: 'solana-serialized'; serializedTx: string }\n /** A module-built Solana transaction message (instructions), reviewed as a plan. */\n | { kind: 'solana-message' }\n /** TON / Tron / Bitcoin / NEAR send or token transfer (amount in base units; token = jetton master / TRC-20 / NEP-141 id). */\n | { kind: 'chain-tx'; chain: string; to: string; amount: bigint; token?: string | undefined; memo?: string | undefined }\n) & {\n /** The account about to sign or send. A pre-approval bound to an account passes only ops that name it. */\n account?: string | undefined\n}\n\nexport type GateMatcher = (op: GatedOp) => boolean\n\nconst HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/\n/** Same account: EVM addresses in any case, anything else exactly. */\nconst sameAccount = (a: string, b: string): boolean => a === b || (HEX_ADDRESS.test(a) && a.toLowerCase() === b.toLowerCase())\n\nexport class ReviewGate {\n private approved: { match: GateMatcher; until: number; account?: string }[] = []\n\n constructor(private readonly now: () => number = Date.now) {}\n\n /**\n * Each matcher passes ONE operation, within `ttlMs` (default 10 min). With `account`, only an op\n * whose `account` is that account (an op without one does not pass). `reviewSwapPlan` and\n * `reviewEarnPlan` always bind.\n */\n preApprove(matchers: GateMatcher[], ttlMs = 10 * 60_000, account?: string): void {\n const until = this.now() + ttlMs\n this.approved.push(...matchers.map((match) => ({ match, until, ...(account ? { account } : {}) })))\n }\n\n /** True (and the matcher is spent) when a pre-approval covers `op`. */\n consume(op: GatedOp): boolean {\n const now = this.now()\n this.approved = this.approved.filter((a) => a.until > now)\n const i = this.approved.findIndex((a) => (a.account === undefined || (op.account !== undefined && sameAccount(a.account, op.account))) && a.match(op))\n if (i < 0) return false\n this.approved.splice(i, 1)\n return true\n }\n\n get pending(): number {\n return this.approved.length\n }\n\n clear(): void {\n this.approved = []\n }\n}\n\nconst lc = (s: string) => s.toLowerCase()\n\n/** Matcher for an exact EVM call: same chain, `to`, calldata and value. */\nexport function evmCallMatcher(expected: { caip2: string; to: string; data?: string | undefined; value: bigint }): GateMatcher {\n const data = expected.data && expected.data !== '0x' ? lc(expected.data) : undefined\n return (op) =>\n op.kind === 'evm-tx' &&\n op.caip2 === expected.caip2 &&\n lc(op.to) === lc(expected.to) &&\n (op.data && op.data !== '0x' ? lc(op.data) : undefined) === data &&\n op.value === expected.value\n}\n\n/** Matcher for one EIP-712 payload on one chain, by the digest the account signs (`typedDataHash` from `@anywalletkit/wallet-evm`). */\nexport function typedDataMatcher(expected: { caip2: string; typedDataHash: string }): GateMatcher {\n const hash = lc(expected.typedDataHash)\n return (op) => op.kind === 'evm-typed-data' && op.caip2 === expected.caip2 && lc(op.typedDataHash) === hash\n}\n\n/** Matcher for a non-EVM send: same chain, recipient, amount, token and memo. */\nexport function chainTxMatcher(expected: { chain: string; to: string; amount: bigint; token?: string | undefined; memo?: string | undefined }): GateMatcher {\n return (op) => op.kind === 'chain-tx' && op.chain === expected.chain && op.to === expected.to && op.amount === expected.amount && (op.token ?? '') === (expected.token ?? '') && (op.memo ?? '') === (expected.memo ?? '')\n}\n","/**\n * Swaps for the extension, the DIRECT path of Vaulty mobile's `lib/swap2.ts`:\n * the providers run in the service worker and talk to their APIs themselves.\n *\n * - {@link quoteRoutes}: dry quotes from every provider that can serve the\n * pair, delivered progressively (`onUpdate` fires as each venue answers), with\n * BEST / FASTEST tags and every refusal named.\n * TODO: replace with `CrossChainRouter.getQuotes` (net-USD ranking,\n * RouteSet). Until then this fan-out over the public `CrossChainProvider`\n * interface ranks by output amount.\n * - {@link reviewSwapPlan}: the engine's `reviewExecution` hook — one sheet for\n * the whole plan (approvals + source leg) BEFORE anything is signed; on\n * approval exactly those operations are pre-approved in the {@link ReviewGate}\n * so the reviewed account lets them through once; a decline aborts with\n * nothing sent (`ReviewDeclined`, 4001).\n */\nimport type { CrossChainProvider, Quote, QuoteParams, Swap2ExecutionPlan } from '@anywalletkit/protocol-swap2-core'\nimport { slippageFloor, validQuote } from '@anywalletkit/protocol-swap2-core'\nimport { typedDataHash } from '@anywalletkit/wallet-evm'\nimport { ApprovalQueue } from './approvals.js'\nimport { ReviewGate, chainTxMatcher, evmCallMatcher, typedDataMatcher, type GateMatcher } from './gate.js'\nimport type { TypedData } from './signing.js'\n\nexport interface RouteView {\n provider: string\n destAmount: string\n minDestAmount: string\n feeUsd: number\n /** On-chain pool venues take the fee inside the output; \"$0.00\" would mislead. */\n feeNote?: string\n etaSeconds: number\n validUntilMs: number\n tags: ('best' | 'fastest')[]\n /** Why this route is not a plain pick: a flagged route is never BEST (see {@link rank}). Absent when there is nothing to say. */\n warnings?: RouteWarning[]\n}\n\n/**\n * What the wallet cannot vouch for on a route — data for the app's list and sheet, never a refusal:\n * - `min-below-slippage`: the provider's minimum sits `minGapBps` under its own quote, further than the `slippageBps`\n * the app asked for (a backend that inflates the output and drops the minimum would otherwise win BEST);\n * - `deposit-address`: the route pays an address the provider's server assigns (a 1Click deposit address, a THORChain\n * inbound vault on a non-EVM source chain, a Bitcoin deposit address), so where the funds end up is that server's\n * word, not calldata the wallet can check.\n */\nexport type RouteWarning =\n | { kind: 'min-below-slippage'; slippageBps: number; minGapBps: number }\n | { kind: 'deposit-address' }\n\n/** The app's route policy inputs for {@link rank}. */\nexport interface RankOptions {\n /** The slippage the quotes were requested at (bps): a route whose minimum sits further under its output is flagged and never BEST. */\n slippageBps?: number\n /**\n * Providers whose routes pay an address their server assigns (NEAR Intents 1Click): flagged, and BEST only when no\n * route from any other provider exists. Which providers these are is the app's call.\n */\n depositAddressProviders?: readonly string[]\n /**\n * The same flag per route, for a provider that pays a server-assigned address only on some routes (a THORChain\n * inbound vault on a non-EVM source chain, a Bitcoin deposit address) and verifiable calldata on the rest. A route is\n * flagged when its provider is listed above OR this returns true; a throw counts as flagged. BEST goes to a flagged\n * route only when every route is flagged. Which routes these are is the app's call.\n */\n depositAddressRoute?: (quote: Quote) => boolean\n}\n\nexport interface RouteListView {\n routes: RouteView[]\n /** Providers still quoting. */\n pending: string[]\n /** Provider → why it sat out (refusal, error, timeout). */\n refusals: Record<string, string>\n /** The quotes themselves, by provider, for execution with the same numbers the user saw. */\n quotes: Record<string, Quote>\n}\n\nexport interface QuoteRoutesOptions {\n onUpdate?: (view: RouteListView) => void\n /** See {@link RankOptions.depositAddressProviders}; the slippage comes from `params.slippageBps`. */\n depositAddressProviders?: readonly string[]\n /** {@link RankOptions.depositAddressRoute} with the request next to the quote (a quote does not name its source chain). */\n depositAddressRoute?: (quote: Quote, params: QuoteParams) => boolean\n /** Per-provider wall clock (default 20 s). */\n timeoutMs?: number\n signal?: AbortSignal\n now?: () => number\n}\n\n/** Dry quotes from every enabled provider that claims the route, progressively. */\nexport async function quoteRoutes(providers: readonly CrossChainProvider[], params: QuoteParams, options: QuoteRoutesOptions = {}): Promise<RouteListView> {\n const timeoutMs = options.timeoutMs ?? 20_000\n const from = { chain: params.sourceChain, token: params.sourceToken }\n const to = { chain: params.destChain, token: params.destToken }\n const refusals: Record<string, string> = {}\n const quotes: Record<string, Quote> = {}\n const candidates: CrossChainProvider[] = []\n for (const p of providers) {\n let enabled = false\n try { enabled = p.enabled() } catch { /* fail closed */ }\n if (!enabled) continue\n if (params.sourceChain === params.destChain && !p.supportsSameChain) { refusals[p.name] = 'does not do same-chain swaps'; continue }\n let serves = false\n try { serves = p.supportsRoute(from, to) } catch (e) { refusals[p.name] = e instanceof Error ? e.message : String(e); continue }\n if (!serves) { refusals[p.name] = 'does not serve this pair'; continue }\n candidates.push(p)\n }\n const pending = new Set(candidates.map((p) => p.name))\n const depositAddressRoute = options.depositAddressRoute\n const rankOptions: RankOptions = {\n ...(params.slippageBps !== undefined ? { slippageBps: params.slippageBps } : {}),\n ...(options.depositAddressProviders ? { depositAddressProviders: options.depositAddressProviders } : {}),\n ...(depositAddressRoute ? { depositAddressRoute: (q: Quote) => depositAddressRoute(q, params) } : {}),\n }\n // The requested slippage is the providers' input; a quote whose minimum still lands under it is shown with a\n // warning (rank), not refused: quote-value issues are warnings, never blocks.\n const { slippageBps: _slippage, ...shapeParams } = params\n const view = (): RouteListView => ({ routes: rank(Object.values(quotes), rankOptions), pending: [...pending], refusals: { ...refusals }, quotes: { ...quotes } })\n const emit = () => options.onUpdate?.(view())\n emit()\n await Promise.all(\n candidates.map(async (p) => {\n const ctrl = new AbortController()\n const timer = setTimeout(() => ctrl.abort(new Error(`no answer within ${Math.round(timeoutMs / 1000)} s`)), timeoutMs)\n const onAbort = () => ctrl.abort(options.signal?.reason)\n options.signal?.addEventListener('abort', onAbort, { once: true })\n let refusal: string | undefined\n try {\n // Race the signal too: a provider that ignores it must not hold the list open forever.\n const aborted = new Promise<never>((_, reject) => ctrl.signal.addEventListener('abort', () => reject(ctrl.signal.reason instanceof Error ? ctrl.signal.reason : new Error(String(ctrl.signal.reason ?? 'cancelled'))), { once: true }))\n const q = await Promise.race([p.getQuote({ ...params, dry: true, onRefusal: (r) => { refusal = r } }, ctrl.signal), aborted])\n if (q && validQuote(q, { ...shapeParams, dry: true }, p.name)) quotes[p.name] = q\n else refusals[p.name] = refusal ?? (q ? 'returned an invalid quote' : 'no route for this pair right now')\n } catch (e) {\n refusals[p.name] = ctrl.signal.aborted ? String(ctrl.signal.reason instanceof Error ? ctrl.signal.reason.message : ctrl.signal.reason ?? 'cancelled') : e instanceof Error ? e.message : String(e)\n } finally {\n clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n pending.delete(p.name)\n emit()\n }\n }),\n )\n return view()\n}\n\n/** How far `min` sits under `dest`, in whole bps (rounded up, so a gap is never understated). */\nfunction gapBps(dest: bigint, min: bigint): number {\n if (dest <= 0n || min >= dest) return 0\n return Number((((dest - min) * 10_000n + dest - 1n) / dest).toString()) // ≤ 10 000: min ≥ 0\n}\n\n/**\n * Highest output first (same destination token for every quote); FASTEST = lowest ETA among them.\n *\n * BEST goes to the highest output among the routes without a {@link RouteWarning} that bars it: never a route whose\n * minimum is below the requested slippage, and a deposit-address route only when every route is one (no route with\n * verifiable calldata exists).\n * The BEST route is listed first; the rest keep the output order. With no route eligible there is no BEST.\n */\nexport function rank(quotes: Quote[], options: RankOptions = {}): RouteView[] {\n const sorted = [...quotes].sort((a, b) => (BigInt(b.destAmount) > BigInt(a.destAmount) ? 1 : BigInt(b.destAmount) < BigInt(a.destAmount) ? -1 : a.feeUsd - b.feeUsd || a.etaSeconds - b.etaSeconds))\n const fastest = sorted.length ? sorted.reduce((f, q) => (q.etaSeconds < f.etaSeconds ? q : f)) : null\n const depositProviders = new Set(options.depositAddressProviders ?? [])\n const paysAssignedAddress = (q: Quote): boolean => {\n if (depositProviders.has(q.provider)) return true\n if (!options.depositAddressRoute) return false\n // A policy hook that fails says nothing about the route: the warning is the safe side.\n try { return options.depositAddressRoute(q) === true } catch { return true }\n }\n const assigned = new Map(sorted.map((q) => [q, paysAssignedAddress(q)] as const))\n const s = options.slippageBps\n const warningsOf = (q: Quote): RouteWarning[] => {\n const w: RouteWarning[] = []\n if (s !== undefined && Number.isInteger(s) && s >= 0 && s < 10_000) {\n const dest = BigInt(q.destAmount)\n const min = BigInt(q.minDestAmount)\n if (min < slippageFloor(dest, s)) w.push({ kind: 'min-below-slippage', slippageBps: s, minGapBps: gapBps(dest, min) })\n }\n if (assigned.get(q)) w.push({ kind: 'deposit-address' })\n return w\n }\n const warned = new Map(sorted.map((q) => [q, warningsOf(q)] as const))\n const verifiableExists = sorted.some((q) => !assigned.get(q))\n const best = sorted.find((q) => {\n const w = warned.get(q)!\n return !w.some((x) => x.kind === 'min-below-slippage') && !(w.some((x) => x.kind === 'deposit-address') && verifiableExists)\n })\n const ordered = best ? [best, ...sorted.filter((q) => q !== best)] : sorted\n return ordered.map((q) => {\n const poolFee = q.providerData?.poolFee\n const feeNote = typeof poolFee === 'string' && poolFee && q.feeUsd === 0 ? (poolFee === 'pools' ? 'pool fees in price' : `pool ${poolFee} in price`) : undefined\n const tags: RouteView['tags'] = []\n if (q === best) tags.push('best')\n if (fastest && q.provider === fastest.provider) tags.push('fastest')\n const warnings = warned.get(q)!\n return { provider: q.provider, destAmount: q.destAmount, minDestAmount: q.minDestAmount, feeUsd: q.feeUsd, etaSeconds: q.etaSeconds, validUntilMs: q.validUntilMs, tags, ...(feeNote ? { feeNote } : {}), ...(warnings.length ? { warnings } : {}) }\n })\n}\n\n/** Vaulty's execution floor: 50 bps under the quoted minimum rides normal drift while the user reviews, still refuses a real reprice. */\nexport const FLOOR_TOLERANCE_BPS = 50n\nexport function executionFloor(minDestAmount: bigint): bigint {\n const floor = (minDestAmount * (10_000n - FLOOR_TOLERANCE_BPS)) / 10_000n\n return floor > 0n ? floor : minDestAmount\n}\n\n// ---- the review stop ----\n\nexport interface SwapReviewMeta {\n /** Who runs the flow (the wallet's origin). */\n origin: string\n /** The account that signs the plan: the gate passes the plan's operations for this account only. */\n account: string\n providerLabel: string\n fromSymbol: string\n fromDecimals: number\n toSymbol: string\n toDecimals: number\n fromChainName: string\n toChainName: string\n /** All of the user's addresses — recipient own/foreign. */\n own: string[]\n /** The slippage the swap was quoted at (bps): a plan minimum further under its output is warned on the sheet (never refused). */\n slippageBps?: number\n /**\n * The route pays an address the provider's server assigned (a NEAR Intents 1Click deposit address, a THORChain\n * inbound vault on a non-EVM source chain, a Bitcoin deposit address — the app's call per route): the sheet warns,\n * and the recipient check does not pass on `plan.recipient` alone — the transaction does not carry it.\n */\n depositAddressAssignedByProvider?: boolean\n}\n\n/** What the swap sheet renders. Amounts are base-unit strings. */\nexport interface SwapApproval {\n provider: string\n providerLabel: string\n fromChain: string\n toChain: string\n fromChainName: string\n toChainName: string\n send: { symbol: string; decimals: number; amount: string }\n receive: { symbol: string; decimals: number; amount: string; min: string }\n recipient: { address: string; isOwn: boolean }\n refundAddress: string\n feeUsd: number\n etaSeconds: number\n validUntilMs: number\n approvals: { token: string; spender: string; amount: string }[]\n source:\n | { kind: 'call'; to: string; data?: string; value: string; deposit?: string }\n | { kind: 'token-transfer'; token: string; recipient: string; amount: string; memo?: string }\n | { kind: 'serialized' }\n /** The EIP-712 order the account signs (gasless routes): `typedData` to render, `text` pretty JSON. */\n | { kind: 'typed-order'; typedData: TypedData; text: string }\n checks: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n /** With `meta.slippageBps`: how far the minimum sits under the output, and whether that is more than the slippage. */\n slippage?: { bps: number; minGapBps: number; below: boolean }\n /** With `meta.depositAddressAssignedByProvider`: the funds go to an address the provider's server named. */\n depositAssignedByProvider?: true\n}\n\nconst APPROVE_SELECTOR = '0x095ea7b3'\nconst TRANSFER_SELECTOR = '0xa9059cbb'\nconst pad = (hexNoPrefix: string) => hexNoPrefix.toLowerCase().padStart(64, '0')\nexport const encodeApproveCalldata = (spender: string, amount: bigint): string => `${APPROVE_SELECTOR}${pad(spender.slice(2))}${pad(amount.toString(16))}`\nconst lc = (s: string) => s.toLowerCase()\n\n/** A plain native send or ERC-20 transfer pays a provider deposit address (1Click-style). */\nfunction depositOf(s: { to: string; data?: string }, approvals: number): string | undefined {\n if (approvals > 0) return undefined\n if (!s.data || s.data === '0x') return s.to\n if (!s.data.startsWith(TRANSFER_SELECTOR) || s.data.length < 10 + 64) return undefined\n return `0x${s.data.slice(10 + 24, 10 + 64)}`\n}\n\n/** bps as a short percentage: 50 → \"0.5%\", 1000 → \"10%\", 125 → \"1.25%\". */\nconst pct = (bps: number): string => `${Number((bps / 100).toFixed(2))}%`\n\nexport function swapApprovalPayload(plan: Swap2ExecutionPlan, meta: SwapReviewMeta): SwapApproval {\n const isOwn = meta.own.some((a) => lc(a) === lc(plan.recipient))\n const assigned = meta.depositAddressAssignedByProvider === true\n const checks: SwapApproval['checks'] = [{ status: 'ok', label: `Built by the ${meta.providerLabel} module` }]\n const depositCheck: SwapApproval['checks'][number] = assigned\n ? { status: 'warn', label: `Deposit address assigned by the ${meta.providerLabel} server — funds go to an address the wallet cannot verify` }\n : { status: 'ok', label: `Deposit address from the ${meta.providerLabel} quote` }\n const s = plan.source\n let source: SwapApproval['source']\n if (s.kind === 'call') {\n const deposit = depositOf(s, plan.approvals.length)\n source = { kind: 'call', to: s.to, ...(s.data ? { data: s.data } : {}), value: s.value.toString(), ...(deposit ? { deposit } : {}) }\n checks.push(deposit || assigned ? depositCheck : { status: 'ok', label: `Calls the ${meta.providerLabel} contract` })\n } else if (s.kind === 'token-transfer') {\n source = { kind: 'token-transfer', token: s.token, recipient: s.recipient, amount: s.amount.toString(), ...(s.memo ? { memo: s.memo } : {}) }\n checks.push(depositCheck)\n } else if (s.kind === 'serialized') {\n source = { kind: 'serialized' }\n checks.push({ status: 'ok', label: 'Balance changes are proven before signing (SDK guard)' })\n } else {\n const typedData = parseTypedOrder(s.typedData)\n source = { kind: 'typed-order', typedData, text: JSON.stringify(typedData, null, 2) }\n checks.push({ status: 'ok', label: 'Signed order — no transaction is sent from your wallet' })\n }\n for (const a of plan.approvals) checks.push(a.amount > plan.sourceAmount ? { status: 'warn', label: 'Approval is larger than this swap needs' } : { status: 'ok', label: 'Approval is exactly the amount needed' })\n if (plan.approvals.length > 1) checks.push({ status: 'ok', label: `${plan.approvals.length} approvals (reset to 0 first)` })\n // A deposit-address leg does not carry the recipient: \"your address\" is only the provider server's promise.\n checks.push(!isOwn\n ? { status: 'warn', label: `Funds arrive at ${plan.recipient.slice(0, 6)}…${plan.recipient.slice(-4)}, not your address` }\n : assigned\n ? { status: 'unknown', label: `Delivery to your address is the ${meta.providerLabel} server’s promise — this transaction does not enforce it` }\n : { status: 'ok', label: 'Funds arrive at your address' })\n let slippage: SwapApproval['slippage']\n const sb = meta.slippageBps\n if (sb !== undefined && Number.isInteger(sb) && sb >= 0 && sb < 10_000) {\n const below = plan.minDestAmount < slippageFloor(plan.destAmount, sb)\n slippage = { bps: sb, minGapBps: gapBps(plan.destAmount, plan.minDestAmount), below }\n checks.push(below\n ? { status: 'warn', label: `Minimum is ${pct(slippage.minGapBps)} under the quote — more than your ${pct(sb)} slippage` }\n : { status: 'ok', label: `Minimum within your ${pct(sb)} slippage` })\n }\n return {\n provider: plan.provider, providerLabel: meta.providerLabel, fromChain: plan.fromChain, toChain: plan.destChain, fromChainName: meta.fromChainName, toChainName: meta.toChainName,\n send: { symbol: meta.fromSymbol, decimals: meta.fromDecimals, amount: plan.sourceAmount.toString() },\n receive: { symbol: meta.toSymbol, decimals: meta.toDecimals, amount: plan.destAmount.toString(), min: plan.minDestAmount.toString() },\n recipient: { address: plan.recipient, isOwn }, refundAddress: plan.refundAddress, feeUsd: plan.feeUsd, etaSeconds: plan.etaSeconds, validUntilMs: plan.validUntilMs,\n approvals: plan.approvals.map((a) => ({ token: a.token, spender: a.spender, amount: a.amount.toString() })),\n source, checks,\n ...(slippage ? { slippage } : {}),\n ...(assigned ? { depositAssignedByProvider: true as const } : {}),\n }\n}\n\nfunction parseTypedOrder(json: string): TypedData {\n const t = JSON.parse(json) as TypedData\n if (!t || typeof t !== 'object' || !t.domain || typeof t.domain !== 'object' || !t.types || typeof t.types !== 'object' || !t.message || typeof t.message !== 'object') throw new Error('The swap order is not EIP-712 typed data.')\n return t\n}\n\n/** Matchers for exactly the operations the plan will perform, in the engine's order. */\nexport function planMatchers(plan: Swap2ExecutionPlan): GateMatcher[] {\n const m: GateMatcher[] = plan.approvals.map((a) => evmCallMatcher({ caip2: plan.fromChain, to: a.token, data: encodeApproveCalldata(a.spender, a.amount), value: 0n }))\n const s = plan.source\n if (s.kind === 'call') {\n if (plan.fromChain.startsWith('eip155:')) m.push(evmCallMatcher({ caip2: plan.fromChain, to: s.to, data: s.data, value: s.value }))\n else if (plan.fromChain.startsWith('solana:')) m.push((op) => op.kind === 'solana-tx' && op.to === s.to && op.value === s.value)\n else m.push(chainTxMatcher({ chain: plan.fromChain, to: s.to, amount: s.value, memo: s.memo }))\n } else if (s.kind === 'token-transfer') {\n if (plan.fromChain.startsWith('eip155:')) m.push(evmCallMatcher({ caip2: plan.fromChain, to: s.token, data: `${TRANSFER_SELECTOR}${pad(s.recipient.slice(2))}${pad(s.amount.toString(16))}`, value: 0n }))\n else if (plan.fromChain.startsWith('solana:')) m.push((op) => op.kind === 'solana-transfer' && op.to === s.recipient && op.amount === s.amount && (op.token ?? '') === s.token)\n else m.push(chainTxMatcher({ chain: plan.fromChain, to: s.recipient, amount: s.amount, token: s.token, memo: s.memo }))\n } else if (s.kind === 'serialized') {\n m.push((op) => op.kind === 'solana-serialized' && op.serializedTx === s.serializedTx)\n } else {\n // The order itself, by the EIP-712 digest the account will sign (the engine's domain / type clean-up does not change it).\n m.push(typedDataMatcher({ caip2: plan.fromChain, typedDataHash: typedDataHash(parseTypedOrder(s.typedData) as Parameters<typeof typedDataHash>[0]) }))\n }\n return m\n}\n\n/** The engine's `reviewExecution`: one sheet for the plan; approve → pre-approve exactly its operations; decline → nothing sent. */\nexport function reviewSwapPlan(approvals: ApprovalQueue, gate: ReviewGate, meta: SwapReviewMeta): (plan: Swap2ExecutionPlan) => Promise<void> {\n if (typeof meta.account !== 'string' || !meta.account) throw new TypeError('reviewSwapPlan needs meta.account: the gate passes the plan for that account only.')\n return async (plan) => {\n const matchers = planMatchers(plan) // a plan that cannot be matched is refused before the sheet\n const payload = swapApprovalPayload(plan, meta)\n await approvals.request({ origin: meta.origin, chain: plan.fromChain, kind: 'swap', payload })\n gate.clear()\n gate.preApprove(matchers, Math.max(60_000, plan.validUntilMs - Date.now() + 5 * 60_000), meta.account)\n }\n}\n","/**\n * Pending swaps across service-worker restarts: records in `chrome.storage.local`,\n * a `chrome.alarms` tick every minute while anything is active, resumable by\n * the swap2 id (`awk1.<provider>.<intent>[.<sourceTxHash>]`), the provider's\n * `trackIntent` as the only source of truth.\n *\n * States (the provider's `IntentState` plus the wallet's own `claiming`):\n * pending ──deposit seen──▶ pending (depositReceived)\n * pending ──attested (CCTP)──▶ action-required ──user claims──▶ claiming ──mint seen──▶ completed\n * pending ──▶ completed | failed | refunded | refund-pending | partial | cancelled | expired\n * A tracker error leaves the record as it was (with `lastError`); a record older\n * than `giveUpAfterMs` with no progress becomes `expired` so the alarm stops.\n */\nimport { SWAP2_ID_PREFIX, type IntentStatus } from '@anywalletkit/protocol-swap2-core'\nimport type { JsonStorage } from './storage.js'\n\nexport type SwapRecordStatus = IntentStatus['state'] | 'claiming'\n\nexport interface SwapRecord {\n /** swap2 id — `awk1.<provider>.<intentId>[.<sourceTxHash>[.<claimTxHash>]]`. */\n id: string\n provider: string\n fromChain: string\n toChain: string\n fromToken: string\n toToken: string\n /** Base units. */\n amountIn: string\n destAmount: string\n recipient: string\n sourceTxHash: string | null\n destTxHash: string | null\n status: SwapRecordStatus\n depositReceived?: boolean\n /** Two-phase routes: where and whether the claim can be built now. */\n claim?: { chain: string; ready: boolean }\n createdAt: number\n updatedAt: number\n /** Last tracker problem (RPC/API), kept until the next successful check. */\n lastError?: string\n checks: number\n}\n\nexport const ACTIVE_STATUSES: ReadonlySet<SwapRecordStatus> = new Set<SwapRecordStatus>(['pending', 'action-required', 'refund-pending', 'partial', 'claiming'])\n\n/**\n * `awk1.<provider>.<intentId>[.<sourceTxHash>[.<claimTxHash>[.ok]]]` — the 4th segment is on the id `claimSwap2`\n * returns, and `.ok` after it when the destination account saw the claim succeed (`destTxConfirmed`).\n */\nexport function parseSwapId(id: string): { provider: string; intentId: string; sourceTxHash?: string; destTxHash?: string; destTxConfirmed?: true } | null {\n if (!id.startsWith(`${SWAP2_ID_PREFIX}.`)) return null\n const parts = id.slice(SWAP2_ID_PREFIX.length + 1).split('.')\n if (parts.length < 2 || parts.length > 5 || !parts[0] || !parts[1]) return null\n if (parts[4] !== undefined && (parts[4] !== 'ok' || !parts[3])) return null\n const provider = decodeURIComponent(parts[0])\n const intentId = decodeURIComponent(parts[1])\n const sourceTxHash = parts[2] ? decodeURIComponent(parts[2]) : undefined\n const destTxHash = parts[3] ? decodeURIComponent(parts[3]) : undefined\n if (destTxHash && !sourceTxHash) return null\n return { provider, intentId, ...(sourceTxHash ? { sourceTxHash } : {}), ...(destTxHash ? { destTxHash } : {}), ...(parts[4] !== undefined ? { destTxConfirmed: true as const } : {}) }\n}\n\nexport class SwapsStore {\n private _records: SwapRecord[] | null = null\n private readonly _listeners = new Set<() => void>()\n /**\n * add / update / remove run here one after another, each reading the list inside its turn: an\n * alarm tick's update that read the list before a new swap was added would otherwise write the\n * old list back and drop the swap.\n */\n private _queue: Promise<unknown> = Promise.resolve()\n\n constructor(private readonly storage: JsonStorage<SwapRecord[]>) {}\n\n async list(): Promise<SwapRecord[]> {\n return [...(await this._all())].sort((a, b) => b.createdAt - a.createdAt)\n }\n\n async get(id: string): Promise<SwapRecord | null> {\n return (await this.list()).find((r) => r.id === id) ?? null\n }\n\n async active(): Promise<SwapRecord[]> {\n return (await this.list()).filter((r) => ACTIVE_STATUSES.has(r.status))\n }\n\n add(record: SwapRecord): Promise<void> {\n return this._serial(async () => {\n const all = (await this._all()).filter((r) => r.id !== record.id)\n await this.write([...all, record])\n })\n }\n\n update(id: string, patch: Partial<SwapRecord>): Promise<SwapRecord | null> {\n return this._serial(async () => {\n const all = [...(await this._all())]\n const i = all.findIndex((r) => r.id === id)\n if (i < 0) return null\n const next = { ...all[i]!, ...patch, updatedAt: patch.updatedAt ?? Date.now() }\n all[i] = next\n await this.write(all)\n return next\n })\n }\n\n remove(id: string): Promise<void> {\n return this._serial(async () => {\n await this.write((await this._all()).filter((r) => r.id !== id))\n })\n }\n\n onChange(listener: () => void): () => void {\n this._listeners.add(listener)\n return () => this._listeners.delete(listener)\n }\n\n private async _all(): Promise<SwapRecord[]> {\n this._records ??= (await this.storage.get()) ?? []\n return this._records\n }\n\n private _serial<T>(fn: () => Promise<T>): Promise<T> {\n const run = this._queue.then(fn, fn)\n this._queue = run.then(() => undefined, () => undefined)\n return run\n }\n\n private async write(records: SwapRecord[]): Promise<void> {\n await this.storage.set(records)\n this._records = records\n for (const l of this._listeners) l()\n }\n}\n\nexport interface SwapTrackerDeps {\n store: SwapsStore\n /** The provider's view of the swap (`CrossChainRouter.trackIntent`). */\n status(record: SwapRecord): Promise<IntentStatus>\n /** Start / stop the periodic alarm (`chrome.alarms.create(name, { periodInMinutes: 1 })`). */\n alarm: { start(): Promise<void> | void; stop(): Promise<void> | void }\n now?: () => number\n /** No progress for this long → `expired` (default 48 h). */\n giveUpAfterMs?: number\n}\n\nexport class SwapTracker {\n private readonly now: () => number\n private ticking: Promise<void> | null = null\n\n constructor(private readonly deps: SwapTrackerDeps) {\n this.now = deps.now ?? Date.now\n }\n\n /** Record a just-executed swap and make sure the alarm runs. */\n async track(input: Omit<SwapRecord, 'createdAt' | 'updatedAt' | 'checks' | 'status' | 'destTxHash'> & { status?: SwapRecordStatus }): Promise<SwapRecord> {\n const t = this.now()\n const record: SwapRecord = { ...input, status: input.status ?? 'pending', destTxHash: null, createdAt: t, updatedAt: t, checks: 0 }\n await this.deps.store.add(record)\n await this.deps.alarm.start()\n return record\n }\n\n /** After the user's claim transaction went out: keep polling until the provider sees the mint. */\n async claimed(id: string, destTxHash: string): Promise<void> {\n await this.deps.store.update(id, { status: 'claiming', destTxHash, claim: undefined as never })\n await this.deps.alarm.start()\n }\n\n /** One alarm tick: check every active record once; stop the alarm when nothing is active. Concurrent ticks coalesce. */\n tick(): Promise<void> {\n this.ticking ??= this.run().finally(() => { this.ticking = null })\n return this.ticking\n }\n\n private async run(): Promise<void> {\n const active = await this.deps.store.active()\n if (active.length === 0) { await this.deps.alarm.stop(); return }\n const giveUp = this.deps.giveUpAfterMs ?? 48 * 60 * 60_000\n for (const record of active) {\n const patch: Partial<SwapRecord> = { checks: record.checks + 1, updatedAt: this.now() }\n try {\n const s = await this.deps.status(record)\n patch.lastError = undefined as never\n if (s.depositReceived !== undefined) patch.depositReceived = s.depositReceived\n if (s.destTxHash) patch.destTxHash = s.destTxHash\n if (s.claim) patch.claim = s.claim\n // Our own claim is out: the provider still says action-required until it sees the mint; keep \"claiming\".\n patch.status = record.status === 'claiming' && (s.state === 'action-required' || s.state === 'pending') ? 'claiming' : s.state\n } catch (e) {\n patch.lastError = e instanceof Error ? e.message : String(e)\n if (this.now() - record.createdAt > giveUp) patch.status = 'expired'\n }\n await this.deps.store.update(record.id, patch)\n }\n if ((await this.deps.store.active()).length === 0) await this.deps.alarm.stop()\n }\n}\n","/**\n * Earn plan review — the Earn modules' counterpart of the swap sheet. A module\n * that exposes its plan (Aave / Morpho `planSupply` & co: ERC-20 approvals\n * first, then the call) gets ONE sheet for the whole plan; on approval exactly\n * those calls are pre-approved in the {@link ReviewGate} so the module's own\n * `supply()` / `withdraw()` / … passes through the reviewed account without a\n * second window. Modules without a plan API (Mellow, Lido, SSV, Jito) are\n * reviewed per transaction by the reviewed account itself — still every send.\n */\nimport { ApprovalQueue } from './approvals.js'\nimport { ReviewGate, evmCallMatcher, type GateMatcher } from './gate.js'\nimport type { EvmNetwork } from './networks.js'\n\nexport interface EarnTx {\n to: string\n data?: string | undefined\n /** Base units, decimal string. */\n value: string\n}\n\nexport interface EarnPlan {\n approvals: EarnTx[]\n tx: EarnTx\n}\n\nexport interface EarnReviewMeta {\n origin: string\n /** The account that sends the plan: the gate passes its calls for this account only. */\n account: string\n /** 'Aave v3', 'Morpho', … */\n module: string\n /** 'Supply', 'Withdraw', 'Borrow', 'Repay', 'Stake', … */\n action: string\n network: EvmNetwork\n /** Human lines the sheet shows (asset, amount, APY, market/vault, health factor…). */\n facts: { k: string; v: string }[]\n /** What the module says about the plan (its own refusals never reach here — they throw before). */\n checks?: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n /** tx-preview-evm result for approvals + call, attached by the wallet (JSON-safe) or null. */\n preview?: unknown\n}\n\nexport interface EarnApproval {\n module: string\n action: string\n network: EvmNetwork\n facts: { k: string; v: string }[]\n approvals: EarnTx[]\n tx: EarnTx\n checks: { status: 'ok' | 'warn' | 'unknown'; label: string }[]\n preview: unknown\n}\n\nconst APPROVE_SELECTOR = '0x095ea7b3'\n\nexport function earnPlanMatchers(network: EvmNetwork, plan: EarnPlan): GateMatcher[] {\n return [...plan.approvals, plan.tx].map((t) => evmCallMatcher({ caip2: network.caip2, to: t.to, data: t.data, value: BigInt(t.value) }))\n}\n\nexport function earnApprovalPayload(plan: EarnPlan, meta: EarnReviewMeta): EarnApproval {\n const checks = [{ status: 'ok' as const, label: `Built by the ${meta.module} module` }, ...(meta.checks ?? [])]\n for (const a of plan.approvals) {\n if (!a.data?.startsWith(APPROVE_SELECTOR)) checks.push({ status: 'warn', label: `Unexpected pre-call to ${a.to.slice(0, 8)}…` })\n }\n if (plan.approvals.length > 1) checks.push({ status: 'ok', label: `${plan.approvals.length} approvals (reset to 0 first)` })\n return { module: meta.module, action: meta.action, network: meta.network, facts: meta.facts, approvals: plan.approvals, tx: plan.tx, checks, preview: meta.preview ?? null }\n}\n\n/** One sheet for the plan; approve → pre-approve exactly its calls; decline → ReviewDeclined, nothing sent. */\nexport async function reviewEarnPlan(approvals: ApprovalQueue, gate: ReviewGate, meta: EarnReviewMeta, plan: EarnPlan): Promise<void> {\n if (typeof meta.account !== 'string' || !meta.account) throw new TypeError('reviewEarnPlan needs meta.account: the gate passes the plan for that account only.')\n await approvals.request({ origin: meta.origin, chain: meta.network.caip2, kind: 'earn', payload: earnApprovalPayload(plan, meta) })\n gate.preApprove(earnPlanMatchers(meta.network, plan), 10 * 60_000, meta.account)\n}\n","/**\n * TON Connect protocol v2 for the extension's JS bridge. Request parsing, error codes and the\n * signature digests live in one place, `@anywalletkit/wallet-ton/tonconnect`, shared with the\n * WalletConnect transport (`@anywalletkit/walletconnect-ton`); this module re-exports them and\n * keeps the bridge-side helpers (the page origin as the proof domain, relay errors as TON Connect\n * codes). The wallet side (keys, sheet, broadcast) lives in the extension; nothing here touches a key.\n *\n * To SIGN, use `WalletAccountTon.signTonProof` / `signTonConnectData` (wallet-ton): they build the\n * same digests from the request and the account's own address. `account.sign()` refuses these\n * 32-byte digests — 32 raw bytes may as well be the hash of a transfer — so the digest functions\n * here are for checking a proof, not for feeding `sign()`.\n */\nimport { TONCONNECT_ERRORS, TonConnectError, tonAddressParts, tonProofDigest, tonSignDataDigest, type TonSignDataPayload } from '@anywalletkit/wallet-ton/tonconnect'\n\nexport {\n TONCONNECT_ERRORS, TONCONNECT_MAX_MESSAGES, TONCONNECT_NETWORKS, TONCONNECT_SIGN_DATA_MAX, TonConnectError,\n parseConnectRequest, parseSendTransaction, parseSignData, tonConnectRawAddress, tonConnectFriendlyAddress, sameTonConnectAddress,\n type TonConnectRequest, type TonConnectMessage, type TonConnectSendTransaction, type TonConnectParseOptions, type TonConnectSendOptions, type TonSignDataPayload,\n} from '@anywalletkit/wallet-ton/tonconnect'\n\n/** Workchain and 32-byte account hash of a TON address. */\nexport interface TonAddressParts { workchain: number; hash: Uint8Array }\n\nconst parts = (a: TonAddressParts) => {\n if (a.hash.length !== 32) throw new TonConnectError(TONCONNECT_ERRORS.unknown, 'address hash must be 32 bytes')\n return { workChain: a.workchain, hash: a.hash }\n}\n\n/** The 32-byte digest a wallet signs for `ton_proof` — to verify a proof; sign with `WalletAccountTon.signTonProof`. */\nexport function tonProofMessage(input: { address: TonAddressParts; domain: string; timestamp: number; payload: string }): Uint8Array {\n return tonProofDigest(parts(input.address), { domain: input.domain, timestamp: input.timestamp, payload: input.payload })\n}\n\n/** The 32-byte digest a wallet signs for `signData` (text / binary) — to verify; sign with `WalletAccountTon.signTonConnectData`. */\nexport function tonSignDataMessage(input: { address: TonAddressParts; domain: string; timestamp: number; payload: TonSignDataPayload }): Uint8Array {\n return tonSignDataDigest(parts(input.address), { domain: input.domain, timestamp: input.timestamp, payload: input.payload })\n}\n\n/** `0:abcd…` → parts. Friendly addresses are the wallet package's job (it hands us the raw form). */\nexport function parseRawAddress(raw: string): TonAddressParts {\n if (!/^-?\\d+:[0-9a-fA-F]{64}$/.test(raw)) throw new TonConnectError(TONCONNECT_ERRORS.unknown, `not a raw TON address: ${raw}`)\n try {\n const p = tonAddressParts(raw)\n return { workchain: p.workChain, hash: p.hash }\n } catch {\n throw new TonConnectError(TONCONNECT_ERRORS.unknown, `not a raw TON address: ${raw}`)\n }\n}\n\n/** The dApp's domain for proofs, from the page origin (host only, as the spec's `domain.value`). */\nexport function proofDomain(origin: string): string {\n try { return new URL(origin).host } catch { throw new TonConnectError(TONCONNECT_ERRORS.badRequest, `bad origin ${origin}`) }\n}\n\n/** Our relay errors → TON Connect error codes. */\nexport function tonConnectErrorCode(e: unknown): number {\n if (e instanceof TonConnectError || (e as { name?: unknown } | null)?.name === 'TonConnectError') return (e as TonConnectError).code\n const code = (e as { code?: unknown })?.code\n if (code === 4001) return TONCONNECT_ERRORS.userDeclined\n if (code === 4100) return TONCONNECT_ERRORS.unknownApp\n if (code === 4200) return TONCONNECT_ERRORS.methodNotSupported\n if (code === -32602) return TONCONNECT_ERRORS.badRequest\n return TONCONNECT_ERRORS.unknown\n}\n","/**\n * Phishing / impersonation checks on a page's host, against a SHIPPED list\n * (never fetched at runtime — decision 10). The list format is MetaMask's\n * eth-phishing-detect `config.json`: `blacklist` / `whitelist` (hosts; a listed\n * domain covers its subdomains), `fuzzylist` + `tolerance` (well-known hosts a\n * lookalike is measured against by Levenshtein distance). On top: punycode\n * (`xn--`) labels are flagged, because mixed-script lookalikes are the common\n * impersonation shape.\n */\nexport interface PhishingList {\n version?: number\n tolerance?: number\n blacklist: readonly string[]\n whitelist?: readonly string[]\n fuzzylist?: readonly string[]\n /** The wallet's own additions to the fuzzylist (the big dApps our users visit): same semantics. */\n extraFuzzylist?: readonly string[]\n}\n\nexport interface HostCheck {\n host: string\n /** On the blocklist (or a subdomain of a listed domain): refuse to inject / connect. */\n blocked: boolean\n /** Human lines for the approval window; empty when nothing is odd. */\n warnings: string[]\n}\n\nexport class PhishingDetector {\n private readonly black: Set<string>\n private readonly white: Set<string>\n private readonly fuzzy: string[]\n private readonly tolerance: number\n\n constructor(list: PhishingList) {\n this.black = new Set(list.blacklist.map(normalizeHost))\n this.white = new Set((list.whitelist ?? []).map(normalizeHost))\n this.fuzzy = [...new Set([...(list.fuzzylist ?? []), ...(list.extraFuzzylist ?? [])].map(normalizeHost))]\n this.tolerance = list.tolerance ?? 1\n }\n\n get size(): number {\n return this.black.size\n }\n\n check(hostOrOrigin: string): HostCheck {\n const host = hostOf(hostOrOrigin)\n const warnings: string[] = []\n if (!host) return { host, blocked: false, warnings }\n if (matchesList(host, this.white)) return { host, blocked: false, warnings }\n if (matchesList(host, this.black)) return { host, blocked: true, warnings: ['This site is on the shipped phishing list.'] }\n if (host.split('.').some((l) => l.startsWith('xn--'))) warnings.push('The address uses punycode (xn--): it may imitate another site with look-alike characters.')\n const look = this.lookalike(host)\n if (look) warnings.push(`The address looks like ${look} but is not that site.`)\n else {\n const brand = this.brandInLabel(host)\n if (brand) warnings.push(`The address contains the name of ${brand.known} (“${brand.label}”) but is not that site.`)\n }\n return { host, blocked: false, warnings }\n }\n\n /**\n * Why `hostOrOrigin` must be refused outright, or `null`: a host on the blocklist (or under a\n * listed domain) and not on the allowlist. Lookalikes and punycode only warn ({@link check}).\n * Wire it as `ApprovalQueueOptions.refuse` and `RouterDeps.refuse`.\n */\n refusal(hostOrOrigin: string): string | null {\n return this.check(hostOrOrigin).blocked ? 'This site is on the wallet\\'s phishing list; the wallet refuses its requests.' : null\n }\n\n /**\n * `metamask.io-login.com`, `app-uniswap.com`, `uniswap.org.evil.net`: a known site's name used as (part of) a label\n * of a host that is not that site. Names shorter than 5 characters are skipped (too many honest matches).\n */\n brandInLabel(host: string): { known: string; label: string } | null {\n const labels = host.split('.')\n for (const known of this.fuzzy) {\n if (host === known || host.endsWith(`.${known}`)) return null\n const name = stripForFuzzy(known).split('.').pop() ?? ''\n if (name.length < 5) continue\n const hit = labels.find((l) => l.includes(name))\n if (hit) return { known, label: hit }\n }\n return null\n }\n\n /** eth-phishing-detect's fuzzy check: the host (minus the TLD and a www.) within `tolerance` edits of a known one. */\n lookalike(host: string): string | null {\n const probe = stripForFuzzy(host)\n const probeName = probe.split('.').pop() ?? probe\n for (const known of this.fuzzy) {\n if (host === known || host.endsWith(`.${known}`)) return null // the real site or one of its subdomains\n const stripped = stripForFuzzy(known)\n if (levenshtein(probe, stripped) <= this.tolerance) return known // same name on another TLD counts as a lookalike\n // `uniswep.org` vs the listed `app.uniswap.org`: compare the registrable labels too (names ≥ 5 chars)\n const name = stripped.split('.').pop() ?? stripped\n if (name.length >= 5 && name !== probeName && levenshtein(probeName, name) <= this.tolerance) return known\n }\n return null\n }\n}\n\nexport const normalizeHost = (h: string): string => h.trim().toLowerCase().replace(/\\.$/, '')\n\nexport function hostOf(hostOrOrigin: string): string {\n try { return normalizeHost(new URL(hostOrOrigin.includes('://') ? hostOrOrigin : `https://${hostOrOrigin}`).hostname) } catch { return normalizeHost(hostOrOrigin) }\n}\n\n/** `a.b.c` matches a list containing `a.b.c`, `b.c` (parent) — never `c` alone unless listed. */\nfunction matchesList(host: string, list: Set<string>): boolean {\n const parts = host.split('.')\n for (let i = 0; i < parts.length - 1; i++) if (list.has(parts.slice(i).join('.'))) return true\n return list.has(host)\n}\n\nfunction stripForFuzzy(host: string): string {\n const parts = host.replace(/^www\\./, '').split('.')\n if (parts.length > 1) parts.pop() // TLD\n return parts.join('.')\n}\n\nexport function levenshtein(a: string, b: string): number {\n if (a === b) return 0\n const m = a.length, n = b.length\n if (m === 0) return n\n if (n === 0) return m\n let prev = Array.from({ length: n + 1 }, (_, j) => j)\n for (let i = 1; i <= m; i++) {\n const cur = [i]\n for (let j = 1; j <= n; j++) cur[j] = Math.min(prev[j]! + 1, cur[j - 1]! + 1, prev[j - 1]! + (a[i - 1] === b[j - 1] ? 0 : 1))\n prev = cur\n }\n return prev[n]!\n}\n","/**\n * WebAuthn assertion verification for \"passkey on every signature\": the approval\n * page asks the authenticator to sign a challenge the service worker derived from\n * the request, and the worker checks the assertion against the public key the\n * vault stored at registration. The ceremony itself (`navigator.credentials`) runs\n * in an extension page; this module is pure WebCrypto so it is testable and the\n * worker never trusts the page's word that the user touched the authenticator.\n *\n * ES256 (COSE -7, P-256 + SHA-256) only — the only algorithm registration asks\n * for. The signature is DER (WebAuthn) and converted to the raw r‖s WebCrypto\n * wants.\n */\nimport { fromBase64, toArrayBuffer } from './codec.js'\nimport { fromBase64Url } from './vault.js'\n\nexport interface AssertionInput {\n /** `PublicKeyCredential.rawId`, base64url. */\n credentialId: string\n /** `AuthenticatorAssertionResponse.authenticatorData`, base64url. */\n authenticatorData: string\n /** `AuthenticatorAssertionResponse.clientDataJSON`, base64url. */\n clientDataJSON: string\n /** `AuthenticatorAssertionResponse.signature` (DER), base64url. */\n signature: string\n}\n\nexport interface AssertionExpectations {\n /** SPKI public key of the credential, base64 (what `getPublicKey()` returned at registration). */\n publicKey: string\n /** COSE alg of the key; only -7 is accepted. */\n alg: number\n /** The challenge the worker handed the page (raw bytes; the page sent it base64url in clientDataJSON). */\n challenge: Uint8Array\n /** `chrome-extension://<id>` */\n origin: string\n /** The RP id the credential was created for (the extension id); its SHA-256 must be the first 32 bytes of authenticatorData. */\n rpId: string\n /** Require the UV flag (user verification: biometric / PIN) — on for signing. */\n requireUserVerification?: boolean\n crypto?: Crypto\n}\n\nexport type AssertionVerdict = { ok: true; counter: number } | { ok: false; reason: string }\n\nconst FLAG_UP = 0x01\nconst FLAG_UV = 0x04\n\n/** Verify one assertion. Never throws on bad input — a verdict with the reason, so the worker can refuse in-band. */\nexport async function verifyAssertion(input: AssertionInput, expect: AssertionExpectations): Promise<AssertionVerdict> {\n const c = expect.crypto ?? globalThis.crypto\n try {\n if (expect.alg !== -7) return { ok: false, reason: `unsupported algorithm ${expect.alg} (ES256 only)` }\n const authData = fromBase64Url(input.authenticatorData)\n const clientData = fromBase64Url(input.clientDataJSON)\n const signature = fromBase64Url(input.signature)\n if (authData.length < 37) return { ok: false, reason: 'authenticatorData too short' }\n // 1. client data: type, challenge, origin\n let client: { type?: unknown; challenge?: unknown; origin?: unknown; crossOrigin?: unknown }\n try { client = JSON.parse(new TextDecoder().decode(clientData)) as typeof client } catch { return { ok: false, reason: 'clientDataJSON is not JSON' } }\n if (client.type !== 'webauthn.get') return { ok: false, reason: `clientData.type is ${String(client.type)}` }\n if (client.origin !== expect.origin) return { ok: false, reason: `assertion origin ${String(client.origin)} is not ${expect.origin}` }\n if (client.crossOrigin === true) return { ok: false, reason: 'cross-origin assertion' }\n if (typeof client.challenge !== 'string' || !equal(fromBase64Url(client.challenge), expect.challenge)) return { ok: false, reason: 'challenge does not match this request' }\n // 2. authenticator data: rpIdHash, flags, counter\n const rpIdHash = new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(new TextEncoder().encode(expect.rpId))))\n if (!equal(authData.subarray(0, 32), rpIdHash)) return { ok: false, reason: 'rpIdHash does not match this extension' }\n const flags = authData[32]!\n if (!(flags & FLAG_UP)) return { ok: false, reason: 'user presence flag not set' }\n if (expect.requireUserVerification !== false && !(flags & FLAG_UV)) return { ok: false, reason: 'user verification flag not set' }\n const counter = ((authData[33]! << 24) | (authData[34]! << 16) | (authData[35]! << 8) | authData[36]!) >>> 0\n // 3. signature over authenticatorData ‖ SHA-256(clientDataJSON)\n const clientHash = new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(clientData)))\n const signed = new Uint8Array(authData.length + clientHash.length)\n signed.set(authData, 0)\n signed.set(clientHash, authData.length)\n const raw = derToRaw(signature)\n if (!raw) return { ok: false, reason: 'signature is not a DER ECDSA signature' }\n const key = await c.subtle.importKey('spki', toArrayBuffer(fromBase64(expect.publicKey)), { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify'])\n const ok = await c.subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, key, toArrayBuffer(raw), toArrayBuffer(signed))\n return ok ? { ok: true, counter } : { ok: false, reason: 'signature does not verify against the registered passkey' }\n } catch (e) {\n return { ok: false, reason: e instanceof Error ? e.message : String(e) }\n }\n}\n\n/** DER `SEQUENCE { INTEGER r, INTEGER s }` → 64-byte r‖s; `null` when malformed. */\nexport function derToRaw(der: Uint8Array): Uint8Array | null {\n if (der[0] !== 0x30) return null\n let i = 2\n if (der[1]! & 0x80) i = 2 + (der[1]! & 0x7f)\n const int = (): Uint8Array | null => {\n if (der[i] !== 0x02) return null\n const len = der[i + 1]!\n const start = i + 2\n i = start + len\n let v = der.subarray(start, start + len)\n while (v.length > 32 && v[0] === 0) v = v.subarray(1)\n if (v.length > 32) return null\n const out = new Uint8Array(32)\n out.set(v, 32 - v.length)\n return out\n }\n const r = int()\n if (!r) return null\n const s = int()\n if (!s) return null\n const raw = new Uint8Array(64)\n raw.set(r, 0)\n raw.set(s, 32)\n return raw\n}\n\n/** Raw r‖s → DER (tests build assertions with WebCrypto, which signs raw). */\nexport function rawToDer(raw: Uint8Array): Uint8Array {\n const enc = (v: Uint8Array): number[] => {\n let i = 0\n while (i < v.length - 1 && v[i] === 0) i++\n let body = Array.from(v.subarray(i))\n if (body[0]! & 0x80) body = [0, ...body]\n return [0x02, body.length, ...body]\n }\n const r = enc(raw.subarray(0, 32))\n const s = enc(raw.subarray(32, 64))\n return Uint8Array.from([0x30, r.length + s.length, ...r, ...s])\n}\n\n/**\n * The challenge for one approval request: SHA-256 over the request id, kind,\n * origin and payload, so an assertion made for one sheet cannot answer another.\n */\nexport async function approvalChallenge(request: { id: string; kind: string; origin: string; payload: unknown }, c: Crypto = globalThis.crypto): Promise<Uint8Array> {\n const text = JSON.stringify([request.id, request.kind, request.origin, request.payload])\n return new Uint8Array(await c.subtle.digest('SHA-256', toArrayBuffer(new TextEncoder().encode(text))))\n}\n\nfunction equal(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n let d = 0\n for (let i = 0; i < a.length; i++) d |= a[i]! ^ b[i]!\n return d === 0\n}\n","/**\n * Address poisoning: an attacker sends dust from an address whose first and\n * last characters match one the user actually paid, hoping the next copy-paste\n * picks the wrong one. The wallet has no transaction history, so it keeps its\n * own book of recipients the user confirmed (per chain) and warns when a new\n * recipient looks like one of them without being it. \"Fresh address\" (no\n * activity on chain) is the other half of the signal; the EVM preview computes it.\n */\nimport type { JsonStorage } from './storage.js'\n\nexport type RecipientsState = Record<string, string[]>\n\n/** How many characters at each end must match (after any `0x`). */\nexport const LOOKALIKE_PREFIX = 4\nexport const LOOKALIKE_SUFFIX = 4\n\nconst norm = (a: string) => a.trim().toLowerCase().replace(/^0x/, '')\n\n/** A known recipient that `address` imitates (same start and end, different address), or `null`. */\nexport function lookalikeOf(address: string, known: readonly string[]): string | null {\n const a = norm(address)\n if (a.length < LOOKALIKE_PREFIX + LOOKALIKE_SUFFIX + 1) return null\n for (const k of known) {\n const b = norm(k)\n if (b === a || b.length !== a.length) continue\n if (a.startsWith(b.slice(0, LOOKALIKE_PREFIX)) && a.endsWith(b.slice(-LOOKALIKE_SUFFIX))) return k\n }\n return null\n}\n\n/** Recipients the user confirmed on each chain (`eip155`, `solana`, …), newest last, capped. */\nexport class RecipientBook {\n private _state: RecipientsState | null = null\n\n constructor(private readonly storage: JsonStorage<RecipientsState>, private readonly cap = 500) {}\n\n private async state(): Promise<RecipientsState> {\n this._state ??= (await this.storage.get()) ?? {}\n return this._state\n }\n\n async list(namespace: string): Promise<string[]> {\n return [...((await this.state())[namespace] ?? [])]\n }\n\n async remember(namespace: string, address: string): Promise<void> {\n const s = { ...(await this.state()) }\n const list = (s[namespace] ?? []).filter((a) => norm(a) !== norm(address))\n list.push(address)\n s[namespace] = list.slice(-this.cap)\n await this.storage.set(s)\n this._state = s\n }\n\n /** Forget the cached book: the next read asks storage again (e.g. a storage that only answers once the wallet is unlocked). */\n reload(): void {\n this._state = null\n }\n\n /** `known` → the address is one the user paid before; `lookalike` → it imitates one. */\n async check(namespace: string, address: string): Promise<{ known: boolean; lookalike: string | null }> {\n const list = await this.list(namespace)\n const known = list.some((a) => norm(a) === norm(address))\n return { known, lookalike: known ? null : lookalikeOf(address, list) }\n }\n}\n","/**\n * Integrity for the small JSON stores a wallet keeps in `chrome.storage.local` (settings, per-site\n * permissions). That area is not authenticated: anything that can write it — a compromised renderer\n * that reaches the extension's storage, a copied-back profile — could switch a security setting off\n * or plant a site grant. {@link macJsonStorage} wraps a {@link JsonStorage} so each value carries an\n * HMAC-SHA256 under a key derived from the vault key ({@link deriveStorageMacKey}); a value without a\n * valid MAC is not trusted.\n *\n * What the wrapper does NOT know is when a key exists: the wallet supplies it (`key()`, `null` while\n * locked). Without one it can neither verify nor sign, and the options say what happens then:\n * reads hand back the stored value unverified (default) or nothing; writes store the value without a\n * MAC — it fails verification once a key is there, so a write made while locked can only lose data,\n * never add trust — or are refused. Verifying once a key appears (at unlock) is the wallet's job\n * ({@link MacJsonStorage.read}).\n *\n * A MAC proves the value was written by someone holding the key; on its own it does not prove it is\n * the latest such value (an older signed value copied back verifies). Give the stores one\n * {@link storageVersionLedger} (`versions`) and each signed value also carries a version the ledger\n * must agree with: an older value, or a deleted one, reads as `stale`. What that can and cannot\n * detect is spelled out at {@link storageVersionLedger}. Rotating the vault key retires every old\n * MAC: re-sign the ledger, then the stores, with `rekey`.\n */\nimport { zeroize } from '@anywalletkit/core'\nimport { fromBase64, toArrayBuffer, toBase64, utf8, withSecretBuffer } from './codec.js'\nimport { VaultError } from './errors.js'\nimport type { JsonStorage } from './storage.js'\n\n/** Field of the stored envelope that holds the MAC (base64), or `null` for a value written without a key. */\nexport const STORAGE_MAC_FIELD = 'anywalletkit.mac/1'\n/** Field of the stored envelope that holds the value's version (a positive integer, inside the MAC) when the store has a {@link storageVersionLedger}. */\nexport const STORAGE_VERSION_FIELD = 'anywalletkit.ver/1'\nconst HKDF_INFO = 'anywalletkit/storage-mac/1'\nconst KEY_BYTES = 32\n\n/**\n * The storage MAC key: HKDF-SHA256(ikm = DEK, salt = none, info = \"anywalletkit/storage-mac/1\"), 32\n * bytes. One-way — it reveals nothing about the DEK — so a wallet may keep it in\n * `chrome.storage.session` while locked. The same DEK always gives the same key; a rotated DEK a new one.\n */\nexport async function deriveStorageMacKey(dek: Uint8Array, crypto: Crypto = globalThis.crypto): Promise<Uint8Array> {\n if (dek.length !== 32) throw new VaultError('Vault key must be 32 bytes.', 'invalid-input')\n const ikm = await withSecretBuffer(dek, (b) => crypto.subtle.importKey('raw', b, 'HKDF', false, ['deriveBits']))\n const bits = await crypto.subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt: new ArrayBuffer(0), info: toArrayBuffer(utf8.encode(HKDF_INFO)) }, ikm, KEY_BYTES * 8)\n return new Uint8Array(bits)\n}\n\n/**\n * What a read found:\n * - `ok`: a value with a valid MAC;\n * - `empty`: nothing stored;\n * - `unsigned`: a value without a MAC (written before the wrapper existed, or while no key was there);\n * - `invalid`: a MAC that does not match (edited, from another store, or under another key);\n * - `no-key`: something is stored but there is no key to check it with;\n * - `stale` (only with a {@link storageVersionLedger}): the MAC is valid — or nothing is stored — but\n * this is not the latest value the ledger knows: an older signed value put back, a deleted one, or\n * a ledger that was itself removed, edited or rolled back.\n */\nexport type MacState = 'ok' | 'empty' | 'unsigned' | 'invalid' | 'no-key' | 'stale'\n\nexport interface MacRead<T> {\n state: MacState\n /** The stored value — verified only when `state` is `ok`. */\n value: T | null\n /** With a ledger, for a value whose MAC is valid: its version (`0` = signed before versions existed). */\n version?: number\n}\n\nexport interface MacJsonStorageOptions {\n /** Names the store inside the MAC: a value signed for one store does not verify in another. */\n label: string\n /** The MAC key ({@link deriveStorageMacKey}), or `null` when the wallet has none (locked). The wrapper zeroizes the copy it gets. */\n key: () => Promise<Uint8Array | null>\n /** `get()` without a key: the stored value unverified (`'unverified'`, default) or `null`. */\n readWithoutKey?: 'unverified' | 'null'\n /** `set()` without a key: store the value with no MAC (`'unsigned'`, default — it fails verification later) or throw `VaultError('locked')`. */\n writeWithoutKey?: 'unsigned' | 'refuse'\n /**\n * Rollback protection: the ledger shared by the wallet's signed stores. Every signed write takes the\n * store's next version (inside the MAC) and records it; a read whose version the ledger does not\n * agree with is `stale`. The label must not contain a line break.\n */\n versions?: StorageVersionLedger\n}\n\nexport interface MacJsonStorage<T> extends JsonStorage<T> {\n /** The verified value (`null` when empty, unsigned or invalid); without a key, per `readWithoutKey`. */\n get(): Promise<T | null>\n /** Sign with the current key; without one, per `writeWithoutKey`. */\n set(value: T): Promise<void>\n /** The stored value and what verification found, under `key` (default: the current key). */\n read(key?: Uint8Array): Promise<MacRead<T>>\n /** Store `value` signed under `key` (default: the current key; refused without one). */\n write(value: T, key?: Uint8Array): Promise<void>\n /**\n * Re-sign the stored value under `newKey` when it verifies under `oldKey`; anything else is left as it is. Returns what `oldKey` found.\n * With a ledger: rekey the ledger first ({@link StorageVersionLedger.rekey}); the value keeps its version, and is re-signed only when the\n * re-signed ledger agrees with it (`stale` otherwise).\n */\n rekey(oldKey: Uint8Array, newKey: Uint8Array): Promise<MacState>\n}\n\ntype Stored<T> = { [STORAGE_MAC_FIELD]: string | null; [STORAGE_VERSION_FIELD]?: number; value: T }\n\n/** Wrap `inner` (e.g. `chromeJsonStorage(chrome.storage.local, key)`) with a MAC; see the module comment. */\nexport function macJsonStorage<T>(inner: JsonStorage<unknown>, options: MacJsonStorageOptions): MacJsonStorage<T> {\n const { label, versions } = options\n if (versions && label.includes('\\n')) throw new VaultError('A versioned store label has no line break.', 'invalid-input')\n const readWithoutKey = options.readWithoutKey ?? 'unverified'\n const writeWithoutKey = options.writeWithoutKey ?? 'unsigned'\n /** The caller's key, or a fresh one from the provider; zeroized after `fn`. */\n const withKey = async <R>(given: Uint8Array | undefined, fn: (key: Uint8Array | null) => Promise<R>): Promise<R> => {\n const key = given ? Uint8Array.from(given) : await options.key()\n try { return await fn(key) } finally { if (key) zeroize(key) }\n }\n /** What is stored and what its MAC says under `key` — the ledger is not asked here. `version`: 0 for a value signed without one. */\n const stored = async (key: Uint8Array | null): Promise<MacRead<T>> => {\n const raw = await inner.get()\n if (raw === null || raw === undefined) return { state: 'empty', value: null }\n const envelope = isStored<T>(raw)\n const value = (envelope ? raw.value : raw) as T\n if (!envelope || raw[STORAGE_MAC_FIELD] === null) return { state: 'unsigned', value }\n if (!key) return { state: 'no-key', value }\n if (!versions) return { state: (await verify(key, label, value, raw[STORAGE_MAC_FIELD]!)) ? 'ok' : 'invalid', value }\n const version = STORAGE_VERSION_FIELD in raw ? (raw as Record<string, unknown>)[STORAGE_VERSION_FIELD] : 0\n if (version !== 0 && !isVersion(version)) return { state: 'invalid', value }\n if (!(await verify(key, label, value, raw[STORAGE_MAC_FIELD]!, version || undefined))) return { state: 'invalid', value }\n return { state: 'ok', value, version }\n }\n const put = async (key: Uint8Array, value: T, version?: number): Promise<void> => {\n const mac = await sign(key, label, value, version)\n await inner.set((version === undefined ? { [STORAGE_MAC_FIELD]: mac, value } : { [STORAGE_MAC_FIELD]: mac, [STORAGE_VERSION_FIELD]: version, value }) satisfies Stored<T>)\n }\n /** The version of the value stored now when `key` signed it (a write goes above it even when the ledger never recorded it). */\n const seen = async (key: Uint8Array): Promise<number> => {\n const r = await stored(key)\n return r.state === 'ok' ? (r.version ?? 0) : 0\n }\n const read = (given?: Uint8Array): Promise<MacRead<T>> => withKey(given, async (key) => {\n if (!versions || !key) return stored(key)\n // Value and ledger are read in one exclusive step: a write between the two would look like a rollback.\n return versions.exclusive(async (ledger) => {\n const r = await stored(key)\n if (r.state === 'empty') return (await ledger.check(label, null, key)) === 'ok' ? r : { state: 'stale', value: null }\n if (r.state !== 'ok') return r\n return (await ledger.check(label, r.version ?? 0, key)) === 'ok' ? r : { ...r, state: 'stale' }\n })\n })\n const write = (value: T, given?: Uint8Array): Promise<void> => withKey(given, async (key) => {\n if (!key) throw new VaultError('The wallet is locked: unlock it to change this.', 'locked')\n if (!versions) return put(key, value)\n await versions.exclusive((ledger) => ledger.advance(label, key, () => seen(key), (version) => put(key, value, version)))\n })\n return {\n read,\n write,\n async get() {\n const r = await read()\n if (r.state === 'ok') return r.value\n if (r.state === 'no-key' && readWithoutKey === 'unverified') return r.value\n return null\n },\n async set(value) {\n await withKey(undefined, async (key) => {\n if (key) return write(value, key)\n if (writeWithoutKey === 'refuse') throw new VaultError('The wallet is locked: unlock it to change this.', 'locked')\n await inner.set({ [STORAGE_MAC_FIELD]: null, value } satisfies Stored<T>)\n })\n },\n async rekey(oldKey, newKey) {\n if (!versions) {\n const r = await read(oldKey)\n if (r.state === 'ok') await write(r.value as T, newKey)\n return r.state\n }\n return versions.exclusive(async (ledger) => {\n const r = await stored(oldKey)\n if (r.state === 'empty') return (await ledger.check(label, null, newKey)) === 'ok' ? 'empty' : 'stale'\n if (r.state !== 'ok') return r.state\n const version = r.version ?? 0\n if ((await ledger.check(label, version, newKey)) !== 'ok') return 'stale'\n // Same version under the new key; a value from before versions existed takes its first one now.\n if (version > 0) await put(newKey, r.value as T, version)\n else await ledger.advance(label, newKey, async () => 0, (v) => put(newKey, r.value as T, v))\n return 'ok'\n })\n },\n }\n}\n\nfunction isStored<T>(raw: unknown): raw is Stored<T> {\n if (typeof raw !== 'object' || raw === null || !(STORAGE_MAC_FIELD in raw) || !('value' in raw)) return false\n const mac = (raw as Record<string, unknown>)[STORAGE_MAC_FIELD]\n return mac === null || typeof mac === 'string'\n}\n\nasync function hmacKey(key: Uint8Array, usage: 'sign' | 'verify'): Promise<CryptoKey> {\n if (key.length !== KEY_BYTES) throw new VaultError('A storage MAC key is 32 bytes.', 'invalid-input')\n return withSecretBuffer(key, (b) => globalThis.crypto.subtle.importKey('raw', b, { name: 'HMAC', hash: 'SHA-256' }, false, [usage]))\n}\n\n/**\n * label ‖ \"\\n\" ‖ canonical JSON (object keys sorted, `undefined` dropped — what a JSON store gives back);\n * with a version: label ‖ \"\\n\" ‖ version ‖ \"\\n\" ‖ canonical JSON. The two forms cannot collide: canonical\n * JSON has no raw line break, and a versioned label has none either.\n */\nfunction macInput(label: string, value: unknown, version?: number): ArrayBuffer {\n return toArrayBuffer(utf8.encode(version === undefined ? `${label}\\n${canonicalJson(value)}` : `${label}\\n${version}\\n${canonicalJson(value)}`))\n}\n\nasync function sign(key: Uint8Array, label: string, value: unknown, version?: number): Promise<string> {\n return toBase64(new Uint8Array(await globalThis.crypto.subtle.sign('HMAC', await hmacKey(key, 'sign'), macInput(label, value, version))))\n}\n\nasync function verify(key: Uint8Array, label: string, value: unknown, mac: string, version?: number): Promise<boolean> {\n let bytes: Uint8Array\n try { bytes = fromBase64(mac) } catch { return false }\n return globalThis.crypto.subtle.verify('HMAC', await hmacKey(key, 'verify'), toArrayBuffer(bytes), macInput(label, value, version))\n}\n\nconst isVersion = (x: unknown): x is number => typeof x === 'number' && Number.isSafeInteger(x) && x > 0\n\n/** Deterministic JSON: the same data gives the same text whatever order its keys were stored in. */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(sortKeys(JSON.parse(JSON.stringify(value ?? null)) as unknown))\n}\n\nfunction sortKeys(x: unknown): unknown {\n if (Array.isArray(x)) return x.map(sortKeys)\n if (x === null || typeof x !== 'object') return x\n const out: Record<string, unknown> = {}\n for (const k of Object.keys(x).sort()) out[k] = sortKeys((x as Record<string, unknown>)[k])\n return out\n}\n\n/** What a {@link StorageVersionLedger} holds, as {@link StorageVersionLedger.read} found it. */\nexport interface StorageVersions {\n /** `ok`; `empty` (no manifest and none expected); `invalid` (unsigned, edited, or another key); `stale` (missing or older than this browser session has seen). */\n state: 'ok' | 'empty' | 'invalid' | 'stale'\n /** Goes up by one with every manifest write. `0` when there is no readable manifest. */\n epoch: number\n /** Where this manifest's numbering started: a store's first version is `base + 1`. */\n base: number\n /** After {@link StorageVersionLedger.condemn}: a store the manifest does not list is not trusted, stored or not. */\n sealed: boolean\n /** The latest version of each store, by label. */\n versions: Record<string, number>\n}\n\n/** The ledger operations a store runs inside {@link StorageVersionLedger.exclusive}. */\nexport interface StorageVersionOps {\n /**\n * Is `version` the latest for `label`? `null` = nothing is stored, `0` = a signed value without a\n * version. A value exactly one ahead of the manifest is accepted and recorded (an interrupted write).\n */\n check(label: string, version: number | null, key: Uint8Array): Promise<'ok' | 'stale'>\n /**\n * One write: `write(version)` stores the value signed with the next version, then the manifest records\n * it. `seen()` is the version of the value stored now (0 when none this key signed). A missing manifest\n * is created first; a refused one is replaced by a sealed one ({@link StorageVersionLedger.condemn}).\n */\n advance(label: string, key: Uint8Array, seen: () => Promise<number>, write: (version: number) => Promise<void>): Promise<number>\n}\n\nexport interface StorageVersionLedgerOptions {\n /** Where the manifest lives — the same area as the stores it covers (`chrome.storage.local`). */\n manifest: JsonStorage<unknown>\n /**\n * The highest manifest epoch seen, kept where a write to the stores' area cannot reach it and where it\n * dies with the browser session (`chrome.storage.session`). `set(null)` clears it.\n */\n mark: JsonStorage<unknown>\n /** Names the manifest inside its MAC. No store may use it. */\n label?: string\n /**\n * Accept a validly signed value that carries no version (written before the ledger existed) for a\n * store the manifest has no record of. Off by default: such a value can be replayed for as long as it\n * is accepted, so switch it on only to migrate, write every store once, and switch it off again.\n */\n acceptUnversioned?: boolean\n /** Milliseconds since the epoch — where a new manifest starts numbering. */\n now?: () => number\n}\n\nexport interface StorageVersionLedger {\n /** Run `fn` with no other ledger operation in between (stores use it for read-and-check and for a write). Do not nest. */\n exclusive<R>(fn: (ops: StorageVersionOps) => Promise<R>): Promise<R>\n /**\n * Stop trusting everything signed so far: a fresh, sealed manifest numbered above all it replaces.\n * Every store then reads `stale` — also one with nothing stored — until it is written again.\n */\n condemn(key: Uint8Array): Promise<void>\n /** Re-sign the manifest under `newKey` when it is `ok` under `oldKey` (one epoch up); otherwise it is left as it is. Returns what `oldKey` found. Then rekey the stores. */\n rekey(oldKey: Uint8Array, newKey: Uint8Array): Promise<StorageVersions['state']>\n /** The manifest as `key` sees it. */\n read(key: Uint8Array): Promise<StorageVersions>\n /** Forget manifest and mark — only when the stores are wiped with them (a new vault). */\n reset(): Promise<void>\n}\n\nconst LEDGER_LABEL = 'anywalletkit/storage-versions/1'\ntype Manifest = Omit<StorageVersions, 'state'>\ntype Loaded = { state: 'ok'; manifest: Manifest } | { state: 'empty' | 'invalid' | 'stale'; manifest?: Manifest }\n\n/**\n * Rollback protection for {@link macJsonStorage} stores: one signed manifest that says which version\n * of each store is the latest.\n *\n * - Every signed value carries its version inside the MAC. A write stores the value with the store's\n * next version, then the manifest (its `epoch` goes up by one), then the session mark. A value the\n * manifest lists another version for — or lists, when nothing is stored — is `stale`: putting ONE\n * store back, or deleting it, is caught, across browser restarts too.\n * - The manifest lives next to the stores, so the whole area can be put back together. `mark` — the\n * highest epoch seen, in session storage — catches that for as long as the browser session lives: a\n * manifest older than the mark, or missing while there is a mark, makes every store `stale`.\n * - A manifest that is unsigned, edited or under another key makes every store `stale`. So does a\n * signed value with a version when there is no manifest at all.\n * - A worker killed between the value and the manifest write leaves a value exactly one version ahead.\n * That is accepted and recorded: only the key holder can sign that version, so it is the wallet's own\n * last write. Until it is recorded the previous value still verifies — the same as the interrupted\n * write never having happened.\n *\n * What it cannot see: the whole area (manifest and stores together) put back to an earlier state when\n * there is no mark — after a browser restart, or an extension reload — and likewise everything deleted\n * together. Nothing an extension can store survives that and is out of the same writer's reach; it is\n * what restoring a profile backup looks like. Versions start from the clock (`now`) so that a manifest\n * created after a loss does not hand out numbers already used; a clock set far back defeats that.\n *\n * The ledger never repairs on a read (beyond recording an interrupted write): the wallet decides what\n * a `stale` store falls back to, calls {@link StorageVersionLedger.condemn} when the manifest itself was\n * refused, and writes the stores again.\n */\nexport function storageVersionLedger(options: StorageVersionLedgerOptions): StorageVersionLedger {\n const label = options.label ?? LEDGER_LABEL\n const acceptUnversioned = options.acceptUnversioned ?? false\n const now = options.now ?? Date.now\n let tail: Promise<unknown> = Promise.resolve()\n const queue = <R>(fn: () => Promise<R>): Promise<R> => {\n const run = tail.then(fn, fn)\n tail = run.then(() => undefined, () => undefined)\n return run\n }\n const high = async (): Promise<number> => {\n const v = await options.mark.get()\n return isVersion(v) ? v : 0\n }\n const parse = async (raw: unknown, key: Uint8Array): Promise<Manifest | null> => {\n if (!isStored<unknown>(raw) || raw[STORAGE_MAC_FIELD] === null) return null\n const epoch = (raw as Record<string, unknown>)[STORAGE_VERSION_FIELD]\n const v = raw.value as Partial<Manifest> | null\n if (!isVersion(epoch) || typeof v !== 'object' || v === null || !isVersion(v.base) || typeof v.sealed !== 'boolean') return null\n if (typeof v.versions !== 'object' || v.versions === null || !Object.values(v.versions).every(isVersion)) return null\n if (!(await verify(key, label, v, raw[STORAGE_MAC_FIELD]!, epoch))) return null\n return { epoch, base: v.base, sealed: v.sealed, versions: { ...v.versions } }\n }\n const load = async (key: Uint8Array): Promise<Loaded> => {\n const mark = await high()\n const raw = await options.manifest.get()\n if (raw === null || raw === undefined) return { state: mark > 0 ? 'stale' : 'empty' }\n const manifest = await parse(raw, key)\n if (!manifest) return { state: 'invalid' }\n if (manifest.epoch < mark) return { state: 'stale', manifest }\n // Ahead of the mark: a new browser session, or the mark write after this manifest never happened.\n if (manifest.epoch > mark) await options.mark.set(manifest.epoch)\n return { state: 'ok', manifest }\n }\n /** Manifest first, mark second: a mark is never ahead of what is on disk. */\n const store = async (m: Manifest, key: Uint8Array): Promise<void> => {\n const value = { base: m.base, sealed: m.sealed, versions: m.versions }\n await options.manifest.set({ [STORAGE_MAC_FIELD]: await sign(key, label, value, m.epoch), [STORAGE_VERSION_FIELD]: m.epoch, value })\n if (m.epoch > (await high())) await options.mark.set(m.epoch)\n }\n /** A new manifest numbered above the clock, the mark and whatever the old one (when it still verified) knew. */\n const fresh = async (sealed: boolean, prior: Manifest | undefined, key: Uint8Array): Promise<Manifest> => {\n const floor = Math.max(await high(), Math.floor(now()), prior ? Math.max(prior.epoch, prior.base, ...Object.values(prior.versions)) : 0)\n if (!Number.isSafeInteger(floor + 2)) throw new VaultError('Storage version out of range.', 'invalid-input')\n const m: Manifest = { epoch: floor + 1, base: floor + 1, sealed, versions: {} }\n await store(m, key)\n return m\n }\n const record = (m: Manifest, name: string, version: number, key: Uint8Array): Promise<void> =>\n store({ ...m, epoch: m.epoch + 1, versions: { ...m.versions, [name]: version } }, key)\n const named = (name: string): void => {\n if (name === label || name.includes('\\n')) throw new VaultError('Not a store label.', 'invalid-input')\n }\n const ops: StorageVersionOps = {\n async check(name, version, key) {\n named(name)\n const l = await load(key)\n // No manifest and none expected: nothing was ever versioned here.\n if (l.state === 'empty') return version === null || (version === 0 && acceptUnversioned) ? 'ok' : 'stale'\n if (l.state !== 'ok') return 'stale'\n const m = l.manifest\n const listed = m.versions[name]\n if (listed === undefined && version === null) return m.sealed ? 'stale' : 'ok'\n if (listed === undefined && version === 0) return !m.sealed && acceptUnversioned ? 'ok' : 'stale'\n if (version === null || version === 0) return 'stale'\n if (version === listed) return 'ok'\n if (version !== (listed ?? m.base) + 1) return 'stale'\n // The interrupted write. Recording it is best effort: the next read tries again.\n await record(m, name, version, key).catch(() => undefined)\n return 'ok'\n },\n async advance(name, key, seen, write) {\n named(name)\n const l = await load(key)\n const before = await seen()\n // No manifest, yet a value that carries a version: the manifest was lost, so the new one is sealed too.\n const m = l.state === 'ok' ? l.manifest : await fresh(l.state !== 'empty' || before > 0, l.manifest, key)\n const version = Math.max(m.versions[name] ?? m.base, before) + 1\n if (!Number.isSafeInteger(version)) throw new VaultError('Storage version out of range.', 'invalid-input')\n await write(version)\n await record(m, name, version, key)\n return version\n },\n }\n return {\n exclusive: (fn) => queue(() => fn(ops)),\n condemn: (key) => queue(async () => { await fresh(true, (await load(key)).manifest, key) }),\n rekey: (oldKey, newKey) => queue(async () => {\n const l = await load(oldKey)\n if (l.state === 'ok') await store({ ...l.manifest, epoch: l.manifest.epoch + 1 }, newKey)\n return l.state\n }),\n read: (key) => queue(async () => {\n const l = await load(key)\n return { state: l.state, ...(l.manifest ?? { epoch: 0, base: 0, sealed: false, versions: {} }) }\n }),\n reset: () => queue(async () => {\n await options.manifest.set(null)\n await options.mark.set(null)\n }),\n }\n}\n"],"mappings":"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","names":["kek","kdf","import_core","import_core","import_core","handle","lc","lc","import_protocol_swap2_core","parts","APPROVE_SELECTOR","import_tonconnect","parts","import_core","HKDF_INFO","crypto"]}