kawasekit 0.5.0 → 0.7.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/signer/errors.ts","../../src/signer/gate.ts","../../src/policy/spending-policy.ts","../../src/x402/errors.ts","../../src/chains/avalanche.ts","../../src/chains/ethereum.ts","../../src/chains/kaia.ts","../../src/chains/polygon.ts","../../src/chains/index.ts","../../src/tokens/jpyc.ts","../../src/tokens/known-assets.ts","../../src/tokens/asset-domain.ts","../../src/tokens/eip3009.ts","../../src/signer/local.ts","../../src/signer/mpc-2p-wire.ts","../../src/signer/mpc-2p.ts"],"names":["getAddress","viemAvalanche","viemAvalancheFuji","viemMainnet","viemSepolia","viemKaia","viemKairos","viemPolygon","viemPolygonAmoy","isAddress","parseSignature","hashTypedData","toHex","recoverAddress","serializeSignature"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * PolicyGatedSigner error types.\n *\n * @packageDocumentation\n */\n\n/**\n * Thrown for a construction-time / configuration error in a PolicyGatedSigner\n * adapter — e.g. a `local` signer constructed without the required\n * `acknowledgeAdvisory: true`, or a non-bypassable signer asserted on an\n * advisory one (`assertNonBypassable`). Policy *denials* are NOT errors — they\n * are returned as a typed {@link PolicyRejection} in {@link SignResult}.\n *\n * @example\n * ```ts\n * import { createLocalPolicyGatedSigner, PolicyGatedSignerConfigError } from \"kawasekit/signer\";\n *\n * try {\n * // @ts-expect-error — acknowledgeAdvisory is required\n * createLocalPolicyGatedSigner({ account, policy, asset });\n * } catch (error) {\n * if (error instanceof PolicyGatedSignerConfigError) {\n * console.error(`${error.field}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class PolicyGatedSignerConfigError extends Error {\n\t/** The offending config field. */\n\treadonly field: string;\n\t/** Short machine-readable reason. */\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid PolicyGatedSigner config (${field}): ${reason}`, options);\n\t\tthis.name = \"PolicyGatedSignerConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown by the `mpc-2p` cryptographic adapter when the co-signer is\n * **unreachable or the ceremony could not complete** — endpoint down, TLS\n * failure, connection dropped mid-ceremony, timeout, a malformed/missing\n * terminal frame, or an internal protocol anomaly. It is a transient / internal\n * error on the throws channel (M6-0: throws are reserved for internal/config\n * errors), **distinct from a policy denial**.\n *\n * This is the **no-silent-fallback** guarantee (RFC m6-3a constraint 3 / W8):\n * the adapter has no local-signing path, so an unavailable wire NEVER yields an\n * `{ ok: true }` signature and NEVER a {@link PolicyRejection}. A `rejection`\n * means \"the owner decided no\" (audit-meaningful); a `CoSignUnavailableError`\n * means \"the owner did not decide\" — the caller may retry the *same* intent\n * (the backend's idempotency keeps a retry safe).\n *\n * @example\n * ```ts\n * try {\n * const result = await mpc2pSigner.sign(intent);\n * if (!result.ok) handleDenial(result.rejection); // owner said no\n * } catch (error) {\n * if (error instanceof CoSignUnavailableError) retryLater(); // wire was down\n * }\n * ```\n */\nexport class CoSignUnavailableError extends Error {\n\t/**\n\t * `true` when the failure is the **transient transport class** (connect failed /\n\t * connection dropped) — the only class the adapter's bounded retry replays\n\t * (RFC m6-3a §4.7: never a delivered rejection, never a ban/identifiable-abort,\n\t * never a protocol anomaly or timeout). Defaults to `false`.\n\t */\n\treadonly transient: boolean;\n\n\tconstructor(message: string, options?: { cause?: unknown; transient?: boolean }) {\n\t\tsuper(message, options?.cause === undefined ? undefined : { cause: options.cause });\n\t\tthis.name = \"CoSignUnavailableError\";\n\t\tthis.transient = options?.transient ?? false;\n\t}\n}\n","/**\n * The enforcement-level type-gate — the compile-time (and runtime) mechanism\n * that prevents an advisory signer from being substituted for an enforcing one.\n *\n * @packageDocumentation\n */\n\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { NonBypassableEnforcement, PolicyGatedSigner } from \"./types\";\n\n/**\n * Compile-time gate: accepts only a non-bypassable signer\n * (`cryptographic` | `hardware`). Passing an `advisory` (or `integrator`) signer\n * is a **compile error**, because `PolicyGatedSigner<\"advisory\">` is not\n * assignable to `PolicyGatedSigner<NonBypassableEnforcement>` (covariant `E`).\n *\n * Use it at the boundary of a bounded/regulated flow so wiring an advisory\n * signer into it fails the build, not silently at runtime.\n *\n * @example\n * ```ts\n * function payBounded(signer: PolicyGatedSigner<NonBypassableEnforcement>) { ... }\n *\n * requireNonBypassable(mpc2pSigner); // ✓ ok — cryptographic\n * // requireNonBypassable(localSigner); // ✗ compile error — advisory\n * ```\n */\nexport function requireNonBypassable<E extends NonBypassableEnforcement>(\n\tsigner: PolicyGatedSigner<E>,\n): PolicyGatedSigner<E> {\n\treturn signer;\n}\n\n/**\n * Runtime mirror of {@link requireNonBypassable}, for plain-JS call sites and as\n * defense-in-depth. Throws {@link PolicyGatedSignerConfigError} if the signer is\n * advisory/integrator (i.e. bypassable). On success, narrows the signer type to\n * {@link NonBypassableEnforcement}.\n */\nexport function assertNonBypassable(\n\tsigner: PolicyGatedSigner,\n): asserts signer is PolicyGatedSigner<NonBypassableEnforcement> {\n\tif (signer.enforcement === \"advisory\" || signer.enforcement === \"integrator\") {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"enforcement\",\n\t\t\t`expected a non-bypassable signer (cryptographic | hardware), got \"${signer.enforcement}\" — an ${signer.enforcement} signer's policy can be bypassed by a key-holder`,\n\t\t);\n\t}\n}\n","/**\n * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner\n * (M6). One declarative {@link SpendingPolicy} (session + expiry, per-token\n * `maxPerSign` + cumulative cap, recipient allowlist, `revoked`) and one pure,\n * deny-closed evaluator {@link evaluateSpendingPolicy}.\n *\n * The same specification is enforced SDK-side (the `local` adapter) and, for the\n * `mpc-2p` adapter, re-implemented backend-side in Rust (the `kawasekit-mpc-2p`\n * co-signer); a shared conformance corpus\n * (`__fixtures__/spending-policy.vectors.json`) keeps the two in lockstep.\n * The evaluator is **check-only** — it reads `SpendState` and never mutates it;\n * the cumulative-cap *commit* (folding a successful spend back in via\n * {@link mergeSpendState}) is the adapter's job, and atomic+authoritative\n * commit is a property of the `cryptographic` adapter only.\n *\n * This is the **x402-EOA** policy path. The smart-account / ZeroDev session-key\n * path is `createJpycDailyLimitPolicies` (`./daily-limit`) — a sibling, not a\n * replacement.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { PaymentIntent, PolicyRejection } from \"../signer/types\";\n\n/** Per-token spend limits. A token absent from the policy's `perToken` is NOT allowed. */\nexport interface TokenLimit {\n\treadonly token: Address;\n\t/** Max value per single signature, token base units. Generalizes `maxAmountPerSign` (threat 1.14). */\n\treadonly maxPerSign: bigint;\n\t/** Optional total across the session. `undefined` = uncapped. MUST be `>= maxPerSign`. */\n\treadonly cumulativeCap?: bigint;\n}\n\n/**\n * Policy-as-data evaluated for every {@link PaymentIntent}. Deny-closed\n * throughout: a token not listed in `perToken` is rejected, and\n * `recipientAllowlist` is **required** — `\"any\"` (unrestricted) is a conscious,\n * greppable choice, never a silent default.\n */\nexport interface SpendingPolicy {\n\treadonly version: \"1\";\n\t/** Session id + expiry (unix seconds). An authorization may not outlive the session. */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/**\n\t * Recipient restriction (**required** — no silent allow-open default):\n\t * `\"any\"` = unrestricted, `[]` = deny-all, `[...]` = allowlist. Making\n\t * `\"any\"` explicit keeps the policy deny-closed like `perToken`.\n\t */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\treadonly revoked: boolean;\n}\n\n/**\n * Cross-call cumulative spend, per token. Injected into the evaluator (never a\n * module global). For the `local` adapter this is a single-process, caller-managed\n * **read-only view**; the authoritative ledger lives in the `cryptographic`\n * adapter's backend.\n */\nexport interface SpendState {\n\treadonly spentPerToken: readonly { readonly token: Address; readonly spent: bigint }[];\n}\n\n/** The outcome of {@link evaluateSpendingPolicy}. */\nexport type PolicyDecision =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly rejection: PolicyRejection };\n\n/** Thrown by {@link createSpendingPolicy} on a malformed policy. */\nexport class SpendingPolicyConfigError extends Error {\n\treadonly field: string;\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid SpendingPolicy (${field}): ${reason}`, options);\n\t\tthis.name = \"SpendingPolicyConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\nfunction deny(reason: PolicyRejection[\"reason\"], detail: string): PolicyDecision {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Evaluate a {@link SpendingPolicy} against a decoded {@link PaymentIntent}.\n *\n * Pure, deterministic, no I/O. Deny-closed; the first failing check wins. All\n * amount comparisons are `bigint`; all address equality uses `getAddress()` on\n * both sides. **Reads `state`, never mutates it** — see {@link mergeSpendState}.\n * `detail` strings never contain the nonce or any signature.\n *\n * @example\n * ```ts\n * const decision = evaluateSpendingPolicy(policy, intent, state, BigInt(Math.floor(Date.now() / 1000)));\n * if (!decision.ok) console.warn(decision.rejection.reason);\n * ```\n */\nexport function evaluateSpendingPolicy(\n\tpolicy: SpendingPolicy,\n\tintent: PaymentIntent,\n\tstate: SpendState,\n\tnowSeconds: bigint,\n): PolicyDecision {\n\tif (policy.revoked) {\n\t\treturn deny(\"revoked\", \"the spending policy has been revoked\");\n\t}\n\tif (nowSeconds > policy.session.notAfter) {\n\t\treturn deny(\"expired\", `session expired at ${policy.session.notAfter} (now ${nowSeconds})`);\n\t}\n\tif (intent.validBefore > policy.session.notAfter) {\n\t\treturn deny(\n\t\t\t\"expired\",\n\t\t\t`authorization validBefore ${intent.validBefore} outlives the session (notAfter ${policy.session.notAfter})`,\n\t\t);\n\t}\n\n\tconst intentToken = getAddress(intent.token);\n\tconst limit = policy.perToken.find((l) => getAddress(l.token) === intentToken);\n\tif (limit === undefined) {\n\t\treturn deny(\"token_not_allowed\", `token ${intentToken} is not in the policy`);\n\t}\n\n\tif (policy.recipientAllowlist !== \"any\") {\n\t\tconst to = getAddress(intent.to);\n\t\tconst allowed = policy.recipientAllowlist.some((a) => getAddress(a) === to);\n\t\tif (!allowed) {\n\t\t\treturn deny(\"recipient_not_allowed\", `recipient ${to} is not on the allowlist`);\n\t\t}\n\t}\n\n\tif (intent.value > limit.maxPerSign) {\n\t\treturn deny(\n\t\t\t\"amount_exceeds_per_sign\",\n\t\t\t`value ${intent.value} exceeds maxPerSign ${limit.maxPerSign}`,\n\t\t);\n\t}\n\n\tif (limit.cumulativeCap !== undefined) {\n\t\tconst spent = state.spentPerToken.find((s) => getAddress(s.token) === intentToken)?.spent ?? 0n;\n\t\tif (spent + intent.value > limit.cumulativeCap) {\n\t\t\treturn deny(\n\t\t\t\t\"amount_exceeds_cumulative\",\n\t\t\t\t`spent ${spent} + value ${intent.value} exceeds cumulativeCap ${limit.cumulativeCap}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n\n/** Parameters for {@link createSpendingPolicy}. */\nexport interface CreateSpendingPolicyParams {\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/** Required: `\"any\"` (unrestricted), `[]` (deny-all), or an allowlist. No silent default. */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\t/** Defaults to `false`. */\n\treadonly revoked?: boolean;\n}\n\n/**\n * Validate + normalize a {@link SpendingPolicy}. Checksums all addresses\n * (`getAddress`), rejects an empty `perToken` (deny-closed), a non-positive\n * `maxPerSign`/`cumulativeCap`, a `cumulativeCap < maxPerSign`, and duplicate\n * tokens. Throws {@link SpendingPolicyConfigError} on violation.\n *\n * @example\n * ```ts\n * const policy = createSpendingPolicy({\n * session: { id: conversationId, notAfter: BigInt(deadline) },\n * perToken: [{ token: JPYC, maxPerSign: 1_000n, cumulativeCap: 10_000n }],\n * recipientAllowlist: [merchant],\n * });\n * ```\n */\nexport function createSpendingPolicy(params: CreateSpendingPolicyParams): SpendingPolicy {\n\tif (typeof params.session.id !== \"string\" || params.session.id === \"\") {\n\t\tthrow new SpendingPolicyConfigError(\"session.id\", \"must be a non-empty string\");\n\t}\n\tif (params.session.notAfter <= 0n) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"session.notAfter\",\n\t\t\t`must be a positive unix-seconds bigint, got ${params.session.notAfter}`,\n\t\t);\n\t}\n\tif (params.perToken.length === 0) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"perToken\",\n\t\t\t\"must list at least one token (the policy is deny-closed)\",\n\t\t);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst perToken: readonly TokenLimit[] = params.perToken.map((l) => {\n\t\tconst token = getAddress(l.token);\n\t\tif (seen.has(token)) {\n\t\t\tthrow new SpendingPolicyConfigError(\"perToken\", `duplicate token ${token}`);\n\t\t}\n\t\tseen.add(token);\n\t\tif (l.maxPerSign <= 0n) {\n\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\"perToken.maxPerSign\",\n\t\t\t\t`must be positive, got ${l.maxPerSign} for ${token}`,\n\t\t\t);\n\t\t}\n\t\tif (l.cumulativeCap !== undefined) {\n\t\t\tif (l.cumulativeCap <= 0n) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`must be positive, got ${l.cumulativeCap} for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (l.cumulativeCap < l.maxPerSign) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`cumulativeCap (${l.cumulativeCap}) must be >= maxPerSign (${l.maxPerSign}) for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { token, maxPerSign: l.maxPerSign, cumulativeCap: l.cumulativeCap };\n\t\t}\n\t\treturn { token, maxPerSign: l.maxPerSign };\n\t});\n\n\tconst recipientAllowlist =\n\t\tparams.recipientAllowlist === \"any\"\n\t\t\t? \"any\"\n\t\t\t: params.recipientAllowlist.map((a) => getAddress(a));\n\n\treturn {\n\t\tversion: \"1\",\n\t\tsession: { id: params.session.id, notAfter: params.session.notAfter },\n\t\tperToken,\n\t\trecipientAllowlist,\n\t\trevoked: params.revoked ?? false,\n\t};\n}\n\n/**\n * Fold a successful spend back into a {@link SpendState} (pure; returns a new\n * state). The caller of the `local` adapter uses this to keep `cumulativeCap`\n * meaningful across calls — `local` does not own an authoritative ledger.\n */\nexport function mergeSpendState(\n\tstate: SpendState,\n\tspend: { readonly token: Address; readonly value: bigint },\n): SpendState {\n\tconst token = getAddress(spend.token);\n\tconst exists = state.spentPerToken.some((s) => getAddress(s.token) === token);\n\tconst spentPerToken = exists\n\t\t? state.spentPerToken.map((s) =>\n\t\t\t\tgetAddress(s.token) === token ? { token, spent: s.spent + spend.value } : s,\n\t\t\t)\n\t\t: [...state.spentPerToken, { token, spent: spend.value }];\n\treturn { spentPerToken };\n}\n","/**\n * Typed errors thrown by the `kawasekit/x402` modules.\n *\n * Centralised so that consumers can `instanceof`-discriminate without importing\n * deep paths. Additional error classes are added here as the corresponding\n * modules come online (server, facilitator, …).\n *\n * @packageDocumentation\n */\n\nimport type { PolicyRejection } from \"../signer/types\";\n\n/**\n * Thrown when an x402 wire-format payload is malformed: invalid base64, invalid\n * JSON, or a value that cannot represent the expected schema.\n *\n * Carries the offending header / context name so callers can produce actionable\n * log lines without re-parsing the message string.\n *\n * @example\n * ```ts\n * import { decodePaymentSignatureHeader, X402InvalidPayloadError } from \"kawasekit\";\n *\n * try {\n * decodePaymentSignatureHeader(headerValue);\n * } catch (error) {\n * if (error instanceof X402InvalidPayloadError) {\n * console.warn(`reject ${error.context}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402InvalidPayloadError extends Error {\n\t/** Logical name of the payload that failed (e.g. `\"PAYMENT-SIGNATURE\"`). */\n\treadonly context: string;\n\t/** Short machine-readable reason code. */\n\treadonly reason: string;\n\n\tconstructor(context: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid ${context} payload: ${reason}`, options);\n\t\tthis.name = \"X402InvalidPayloadError\";\n\t\tthis.context = context;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown when an x402 SDK construction-time configuration is invalid: an\n * unknown `asset.kind`, a known asset id that kawasekit does not ship a\n * domain for, missing required fields on an `unsafeOverride`, etc.\n *\n * Distinct from {@link X402InvalidPayloadError} (which describes wire-format\n * problems): config errors are integrator bugs, not adversarial inputs.\n *\n * @example\n * ```ts\n * import { createX402PaymentSigner, X402InvalidConfigError } from \"kawasekit\";\n *\n * try {\n * createX402PaymentSigner({\n * network: \"testnet\",\n * account,\n * // @ts-expect-error — kind: \"foo\" is not a known kind\n * asset: { kind: \"foo\" },\n * });\n * } catch (error) {\n * if (error instanceof X402InvalidConfigError) {\n * console.error(`${error.field}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402InvalidConfigError extends Error {\n\t/** Logical name of the config field that failed (e.g. `\"asset\"`). */\n\treadonly field: string;\n\t/** Short machine-readable reason code. */\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid ${field} config: ${reason}`, options);\n\t\tthis.name = \"X402InvalidConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown by {@link createX402PaymentSigner} (the `signer` variant) when the bound\n * `PolicyGatedSigner` refuses to sign — i.e. its `sign()` returned\n * `{ ok: false }`. Carries the typed {@link PolicyRejection} so callers can\n * branch on `reason`. This is the policy-driven analog of the `account`\n * variant's `maxAmountPerSign` throw ({@link X402InvalidPayloadError}): the\n * `X402PaymentSigner.sign()` surface returns a payload or throws, unchanged.\n *\n * @example\n * ```ts\n * import { X402PolicyRejectedError } from \"kawasekit\";\n *\n * try {\n * await signer.sign({ paymentRequirements });\n * } catch (error) {\n * if (error instanceof X402PolicyRejectedError) {\n * console.warn(`policy refused: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402PolicyRejectedError extends Error {\n\t/** The policy rejection reason (e.g. `\"amount_exceeds_per_sign\"`). */\n\treadonly reason: PolicyRejection[\"reason\"];\n\t/** The full typed rejection (its `detail` never contains the nonce or signature). */\n\treadonly rejection: PolicyRejection;\n\n\tconstructor(rejection: PolicyRejection, options?: { cause?: unknown }) {\n\t\tsuper(`x402 payment rejected by policy: ${rejection.reason} (${rejection.detail})`, options);\n\t\tthis.name = \"X402PolicyRejectedError\";\n\t\tthis.reason = rejection.reason;\n\t\tthis.rejection = rejection;\n\t}\n}\n","import { avalanche as viemAvalanche, avalancheFuji as viemAvalancheFuji } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Avalanche C-Chain — priority 3 production chain.\n *\n * Snowman BFT gives sub-`2 s` **deterministic finality**, so\n * `defaultConfirmations` of `2` is ample — deep confirmations add latency for\n * no extra safety. JPYC is live at the same address as the other chains.\n *\n * The x402 EOA-payer path works today; the smart-account path via ZeroDev is\n * not yet verified on Avalanche.\n */\nexport const avalanche = {\n\t...viemAvalanche,\n\tisTestnet: false,\n\tdefaultConfirmations: 2,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Avalanche Fuji testnet. JPYC is live at the same address as the other chains\n * (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()` ==\n * \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const avalancheFuji = {\n\t...viemAvalancheFuji,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { mainnet as viemMainnet, sepolia as viemSepolia } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Ethereum mainnet — priority 4 production chain (institutional use cases).\n *\n * Casper FFG finalises in epochs (~12.8 min). `defaultConfirmations` of `32`\n * (~6.4 min at ~12 s blocks) gives finalised-grade safety. **Do NOT use\n * Polygon's `4` here** — 4 blocks (~48 s) is nowhere near finalised, and would\n * re-open the settle-reorg gap (threat 2.8). The facilitator auto-sizes\n * `receiptTimeoutMs` from this depth (~10 min), so the default does not time\n * out. JPYC is live at the same address as the other chains.\n */\nexport const ethereum = {\n\t...viemMainnet,\n\tisTestnet: false,\n\tdefaultConfirmations: 32,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n\n/**\n * Sepolia — Ethereum testnet. JPYC is live at the same address as the other\n * chains (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()`\n * == \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const sepolia = {\n\t...viemSepolia,\n\tisTestnet: true,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n","import { kaia as viemKaia, kairos as viemKairos } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Kaia mainnet — priority 2 production chain.\n *\n * Kaia (Klaytn + Finschia) runs IBFT consensus with **immediate finality** — a\n * single confirmed block is final — so `defaultConfirmations` is `1` (do NOT\n * copy Polygon's `4`). JPYC is live at the same address as the other chains\n * (`src/tokens/jpyc.ts`).\n *\n * Note: ZeroDev does not support Kaia, so the **smart-account path** (session\n * keys, sponsored UserOps) is not yet available here — it is planned via\n * Pimlico (M5-3 Phase 2). The **x402 EOA-payer path** works today.\n */\nexport const kaia = {\n\t...viemKaia,\n\tisTestnet: false,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n\n/**\n * Kairos — Kaia testnet. JPYC is available via the Kaia faucet at the same\n * address as mainnet; suitable for the same Amoy→Polygon-style testnet→mainnet\n * verification pattern.\n */\nexport const kairos = {\n\t...viemKairos,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n","import { polygon as viemPolygon, polygonAmoy as viemPolygonAmoy } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Polygon mainnet — priority 1 production chain.\n *\n * Built on viem's `polygon` definition (official RPC URLs, block explorers,\n * and `POL` native currency) plus kawasekit metadata. Polygon PoS is\n * probabilistic; the default `4` confirmations ≈ ~8 s of soft finality.\n */\nexport const polygon = {\n\t...viemPolygon,\n\tisTestnet: false,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Polygon Amoy testnet — the primary kawasekit development target.\n *\n * Built on viem's `polygonAmoy` definition. JPYC is also live on Amoy at the\n * same address as mainnet; see `src/tokens/jpyc.ts`.\n */\nexport const polygonAmoy = {\n\t...viemPolygonAmoy,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { avalanche, avalancheFuji } from \"./avalanche\";\nimport { ethereum, sepolia } from \"./ethereum\";\nimport { kaia, kairos } from \"./kaia\";\nimport { polygon, polygonAmoy } from \"./polygon\";\nimport { type KawaseChain, zerodevRpcUrl } from \"./types\";\n\nexport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\ttype KawaseChain,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n\tzerodevRpcUrl,\n};\n\n/**\n * All chains kawasekit supports, in priority order (CLAUDE.md chain priority:\n * Polygon → Kaia → Avalanche → Ethereum, each with its testnet).\n *\n * Exposed as a `readonly` tuple — **not** a `Map` — so that bundlers can\n * tree-shake chains a consumer never references.\n *\n * JPYC liveness is a separate axis (`src/tokens/jpyc.ts`): a chain can be\n * supported here while JPYC is not yet live on it (Avalanche Fuji / Sepolia).\n *\n * @example\n * ```ts\n * import { supportedChains } from \"kawasekit\";\n *\n * for (const chain of supportedChains) {\n * \tconsole.log(chain.id, chain.name);\n * }\n * ```\n */\nexport const supportedChains = [\n\tpolygon,\n\tpolygonAmoy,\n\tkaia,\n\tkairos,\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tsepolia,\n] as const;\n\n/**\n * Union of every chain ID kawasekit supports\n * (`137 | 80002 | 8217 | 1001 | 43114 | 43113 | 1 | 11155111`).\n *\n * Derived from {@link supportedChains}, so adding a chain there extends this\n * type automatically.\n */\nexport type SupportedChainId = (typeof supportedChains)[number][\"id\"];\n\n/** A single member of {@link supportedChains}, with its literal `id`. */\ntype SupportedChain = (typeof supportedChains)[number];\n\n/**\n * Internal chain lookup, built once at module scope.\n *\n * This `Map` is an implementation detail and is intentionally **not**\n * exported: the public API exposes the {@link supportedChains} tuple instead,\n * so importing one chain does not pull in all of them.\n */\nconst chainsById: ReadonlyMap<number, SupportedChain> = new Map(\n\tsupportedChains.map((chain) => [chain.id, chain]),\n);\n\n/**\n * Error thrown when a chain ID kawasekit does not support is requested.\n *\n * @example\n * ```ts\n * import { ChainNotSupportedError, getChain } from \"kawasekit\";\n *\n * try {\n * \tgetChain(1);\n * } catch (error) {\n * \tif (error instanceof ChainNotSupportedError) {\n * \t\tconsole.error(error.message);\n * \t}\n * }\n * ```\n */\nexport class ChainNotSupportedError extends Error {\n\tconstructor(chainId: number) {\n\t\tconst supported = supportedChains.map((chain) => chain.id).join(\", \");\n\t\tsuper(\n\t\t\t`Chain ID ${chainId} is not supported by kawasekit. ` + `Supported chain IDs: ${supported}.`,\n\t\t);\n\t\tthis.name = \"ChainNotSupportedError\";\n\t}\n}\n\n/**\n * Type guard that narrows an arbitrary chain ID to a {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to test.\n * @returns `true` if kawasekit supports this chain ID.\n *\n * @example\n * ```ts\n * import { isSupportedChainId } from \"kawasekit\";\n *\n * const id = 80002;\n * if (isSupportedChainId(id)) {\n * \t// `id` is now narrowed to SupportedChainId\n * }\n * ```\n */\nexport function isSupportedChainId(chainId: number): chainId is SupportedChainId {\n\treturn chainsById.has(chainId);\n}\n\n/**\n * Looks up a supported chain by its numeric chain ID.\n *\n * The returned chain's `id` is narrowed to {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to look up.\n * @returns The matching {@link KawaseChain}.\n * @throws {ChainNotSupportedError} If `chainId` is not supported.\n *\n * @example\n * ```ts\n * import { getChain } from \"kawasekit\";\n *\n * const chain = getChain(80002); // Polygon Amoy\n * console.log(chain.name);\n * ```\n */\nexport function getChain(chainId: number): SupportedChain {\n\tconst chain = chainsById.get(chainId);\n\tif (chain === undefined) {\n\t\tthrow new ChainNotSupportedError(chainId);\n\t}\n\treturn chain;\n}\n","/**\n * JPYC stablecoin metadata, deployments, and ABI.\n *\n * JPYC is a Japanese yen-pegged stablecoin issued by JPYC Inc. under the\n * revised Payment Services Act as 電子決済手段 (electronic payment\n * instrument). The new (\"v2\") JPYC, launched 2025-10, lives at the same\n * address on every chain where it is deployed.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport type { SupportedChainId } from \"../chains\";\nimport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n} from \"../chains\";\n\n/** ERC-20 decimals for JPYC. Constant across every chain. */\nexport const JPYC_DECIMALS = 18;\n\n/**\n * EIP-712 domain hint for off-chain authorization signing (EIP-3009, EIP-2612).\n *\n * The real JPYC contract does not expose `version()` publicly — it lives in an\n * `internal VERSION` state variable set during proxy initialization. The\n * canonical value is `\"1\"`, matching the FiatToken lineage; the\n * {@link signTransferWithAuthorization} helper accepts an override if a future\n * deployment changes this.\n *\n * `name` is \"JPY Coin\" — the on-chain `name()` value on every live deployment.\n */\nexport const JPYC_EIP712_DOMAIN_HINT = {\n\tname: \"JPY Coin\",\n\tversion: \"1\",\n} as const;\n\n/**\n * Address shared by every live JPYC deployment.\n *\n * Verified on:\n * - Ethereum : https://etherscan.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * - Polygon : https://polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Polygon Amoy : https://amoy.polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Avalanche : https://snowtrace.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n *\n * Do NOT confuse with the legacy 前払式支払手段 JPYC at `0x431D5dFF...`.\n */\nexport const JPYC_V2_ADDRESS: Address = \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\";\n\n/** A JPYC deployment on a single chain. */\nexport interface JpycDeployment {\n\treadonly chainId: SupportedChainId;\n\treadonly address: Address;\n\t/** `true` if the token is live on this chain right now. */\n\treadonly isLive: boolean;\n}\n\n/**\n * JPYC deployments keyed by chain.\n *\n * JPYC v2 uses the **same address** (`JPYC_V2_ADDRESS`) on every chain where it\n * is live. `isLive` is the separate \"is JPYC actually deployed here yet?\" axis.\n * All eight supported chains are live at this address: the four mainnets\n * (Polygon, Kaia, Avalanche, Ethereum) + Amoy + Kairos + Avalanche Fuji +\n * Sepolia. Kaia/Kairos/Avalanche/Fuji/Sepolia were confirmed by a read-only\n * on-chain check (`name() == \"JPY Coin\"`, `symbol() == \"JPYC\"` at `0xE7C3…`,\n * 2026-05-31); Polygon/Amoy/Ethereum are established. `isLive: false` + the\n * {@link JpycNotAvailableError} path remain for any future chain added before\n * its JPYC deployment lands.\n */\nexport const jpycDeployments: { readonly [chainId in SupportedChainId]: JpycDeployment } = {\n\t[polygon.id]: { chainId: polygon.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[polygonAmoy.id]: { chainId: polygonAmoy.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kaia.id]: { chainId: kaia.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kairos.id]: { chainId: kairos.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalanche.id]: { chainId: avalanche.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[ethereum.id]: { chainId: ethereum.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalancheFuji.id]: { chainId: avalancheFuji.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[sepolia.id]: { chainId: sepolia.id, address: JPYC_V2_ADDRESS, isLive: true },\n};\n\n/**\n * Thrown when JPYC is not deployed on the requested chain.\n *\n * Today this is unreachable (every {@link SupportedChainId} has a live\n * deployment), but the error class is exported for future chains (Kaia) where\n * JPYC is still in development.\n */\nexport class JpycNotAvailableError extends Error {\n\tconstructor(chainId: number) {\n\t\tsuper(`JPYC is not yet deployed on chain ID ${chainId}.`);\n\t\tthis.name = \"JpycNotAvailableError\";\n\t}\n}\n\n/**\n * Returns the JPYC contract address for a kawasekit-supported chain.\n *\n * @param chainId - A {@link SupportedChainId}.\n * @returns The JPYC contract address on that chain.\n * @throws {JpycNotAvailableError} If JPYC is not live on the chain.\n *\n * @example\n * ```ts\n * import { getJpycAddress, polygonAmoy } from \"kawasekit\";\n *\n * const address = getJpycAddress(polygonAmoy.id);\n * ```\n */\nexport function getJpycAddress(chainId: SupportedChainId): Address {\n\tconst deployment = jpycDeployments[chainId];\n\tif (!deployment.isLive) {\n\t\tthrow new JpycNotAvailableError(chainId);\n\t}\n\treturn deployment.address;\n}\n\n/**\n * Minimal JPYC ABI: ERC-20 + EIP-3009 surface that kawasekit needs.\n *\n * Excludes permit / mint / blocklist / pause — kawasekit only reads balance,\n * sends `transfer()` via UserOp, and constructs / submits EIP-3009\n * authorizations. Bringing in the full FiatTokenV1 ABI would be wasted bytes.\n */\nexport const jpycAbi = [\n\t// ----- ERC-20 read -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"name\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"symbol\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"decimals\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint8\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"totalSupply\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"balanceOf\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [{ name: \"account\", type: \"address\" }],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"allowance\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\" },\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t// ----- ERC-20 write -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transfer\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferFrom\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"approve\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- EIP-3009 -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"receiveWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"cancelAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"authorizationState\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- Events kawasekit needs to decode -----\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Transfer\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\", indexed: true },\n\t\t\t{ name: \"to\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Approval\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\", indexed: true },\n\t\t\t{ name: \"spender\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationUsed\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationCanceled\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n] as const;\n","/**\n * Known-asset registry for {@link createX402PaymentSigner}'s\n * `asset: { kind: \"known\", id }` discriminated-union branch.\n *\n * kawasekit only ships pinned EIP-712 domain definitions for assets it has\n * verified empirically against the deployed contracts. Adding a new entry\n * here requires citing the source-file + line reference for the contract\n * that owns the `name` / `version` (so the next reviewer can spot-check the\n * claim, the same discipline `docs/THREAT_MODEL.md` §0 demands of any ✅\n * verdict that delegates to an out-of-scope component).\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS } from \"./jpyc\";\n\n/** Known asset identifiers. New entries must update this union AND the table. */\nexport type KnownAssetId = \"jpyc-v2\";\n\n/** Fully-pinned EIP-712 domain for a known asset. */\nexport interface KnownAssetDomain {\n\treadonly id: KnownAssetId;\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\n/**\n * Canonical table. Lookups go through {@link getKnownAssetDomain}, which\n * returns a frozen copy so callers cannot mutate the registry.\n *\n * `verifyingContract` is the multi-chain canonical address — JPYC v2 is the\n * same address on Ethereum / Polygon (mainnet + Amoy) / Avalanche. The\n * signer cross-checks `requirements.asset` against this value at sign time,\n * so a server advertising a different `asset` is rejected before any\n * signature is produced.\n *\n * JPYC v2 domain: `name = \"JPY Coin\"`, `version = \"1\"`. Source of truth is\n * the deployed contract's `eip712Domain()` view — verified empirically and\n * also cached in `src/tokens/jpyc.ts:JPYC_EIP712_DOMAIN_HINT`.\n */\nconst KNOWN_ASSETS: ReadonlyArray<KnownAssetDomain> = [\n\t{\n\t\tid: \"jpyc-v2\",\n\t\tname: JPYC_EIP712_DOMAIN_HINT.name,\n\t\tversion: JPYC_EIP712_DOMAIN_HINT.version,\n\t\tverifyingContract: getAddress(JPYC_V2_ADDRESS),\n\t},\n];\n\n/**\n * Look up a known asset's pinned EIP-712 domain by id.\n *\n * @returns The domain, or `undefined` if the id is not in the registry.\n *\n * @example\n * ```ts\n * import { getKnownAssetDomain } from \"kawasekit\";\n *\n * const jpyc = getKnownAssetDomain(\"jpyc-v2\");\n * if (jpyc === undefined) throw new Error(\"unreachable\");\n * console.log(jpyc.verifyingContract); // 0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * ```\n */\nexport function getKnownAssetDomain(id: KnownAssetId): KnownAssetDomain | undefined {\n\treturn KNOWN_ASSETS.find((entry) => entry.id === id);\n}\n\n/** List every known asset id (for diagnostics / error messages). */\nexport function listKnownAssetIds(): readonly KnownAssetId[] {\n\treturn KNOWN_ASSETS.map((entry) => entry.id);\n}\n","/**\n * EIP-712 asset-domain resolution for x402 / EIP-3009 signing.\n *\n * Construction-time pinning of the EIP-712 domain (`name` / `version` /\n * `verifyingContract`) a signer will use. The integrator declares an\n * {@link X402AssetParam} — either a kawasekit-maintained `known` asset or a\n * loud `unsafeOverride` — and {@link resolveAssetParam} resolves it to a pinned\n * {@link ResolvedAsset}. The signer then trusts only this pinned domain and\n * refuses to sign for a mismatched advertised asset (Threat 1.4: misadvertised\n * EIP-712 domain).\n *\n * Token-domain concern, reused by both the x402 signer (`src/x402/client.ts`)\n * and the M6 PolicyGatedSigner (`src/signer/`).\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress, isAddress } from \"viem\";\nimport { X402InvalidConfigError } from \"../x402/errors\";\nimport type { Eip3009Domain } from \"./eip3009\";\nimport {\n\tgetKnownAssetDomain,\n\ttype KnownAssetDomain,\n\ttype KnownAssetId,\n\tlistKnownAssetIds,\n} from \"./known-assets\";\n\n/** EIP-712 token domain `name` / `version` pair. */\nexport interface X402TokenDomain {\n\treadonly name: string;\n\treadonly version: string;\n}\n\n/**\n * Asset binding for {@link createX402PaymentSigner} and the M6 PolicyGatedSigner.\n * Required, discriminated.\n *\n * **Default-on whitelist**: integrators MUST declare which asset they intend\n * to sign for. The `known` branch references a kawasekit-maintained\n * whitelist (see `src/tokens/known-assets.ts`); the `unsafeOverride` branch\n * is the deliberate escape hatch for any other asset and is named loudly so\n * it survives a code review. Either way, the signer pins the EIP-712 domain\n * at construction time and refuses to sign if `paymentRequirements.asset`\n * disagrees with the pinned `verifyingContract`.\n *\n * Closes Threat 1.4 (misadvertised EIP-712 domain): the server's advertised\n * `extra.name` / `extra.version` and `asset` are all ignored for signing\n * purposes — the signer trusts only what the integrator declared here.\n */\nexport type X402AssetParam =\n\t| {\n\t\t\t/** Use a kawasekit-maintained pinned EIP-712 domain. */\n\t\t\treadonly kind: \"known\";\n\t\t\t/** The asset id to pin. See {@link KnownAssetId} for the registry. */\n\t\t\treadonly id: KnownAssetId;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Use a caller-supplied EIP-712 domain for an asset NOT on the\n\t\t\t * kawasekit whitelist. The name is deliberately loud — pick this\n\t\t\t * branch only when you have separately audited the contract and its\n\t\t\t * `eip712Domain()` output.\n\t\t\t */\n\t\t\treadonly kind: \"unsafeOverride\";\n\t\t\treadonly domain: {\n\t\t\t\treadonly name: string;\n\t\t\t\treadonly version: string;\n\t\t\t\treadonly verifyingContract: Address;\n\t\t\t};\n\t };\n\n/** Construction-time resolution of an {@link X402AssetParam} to a pinned domain. */\nexport interface ResolvedAsset {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\n/**\n * Resolve an {@link X402AssetParam} to a pinned {@link ResolvedAsset}.\n *\n * Throws {@link X402InvalidConfigError} for an unknown `known` id or a malformed\n * `unsafeOverride` domain. Pure / construction-time — no chain RPC.\n */\nexport function resolveAssetParam(asset: X402AssetParam): ResolvedAsset {\n\tif (asset.kind === \"known\") {\n\t\tconst entry: KnownAssetDomain | undefined = getKnownAssetDomain(asset.id);\n\t\tif (entry === undefined) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.id\",\n\t\t\t\t`unknown asset id ${JSON.stringify(asset.id)}. Supported: ${listKnownAssetIds()\n\t\t\t\t\t.map((id) => JSON.stringify(id))\n\t\t\t\t\t.join(\", \")}.`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: entry.name,\n\t\t\tversion: entry.version,\n\t\t\tverifyingContract: entry.verifyingContract,\n\t\t};\n\t}\n\tif (asset.kind === \"unsafeOverride\") {\n\t\tconst { domain } = asset;\n\t\tif (typeof domain.name !== \"string\" || domain.name === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.name\",\n\t\t\t\t\"`unsafeOverride.domain.name` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (typeof domain.version !== \"string\" || domain.version === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.version\",\n\t\t\t\t\"`unsafeOverride.domain.version` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (!isAddress(domain.verifyingContract, { strict: false })) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.verifyingContract\",\n\t\t\t\t`\\`unsafeOverride.domain.verifyingContract\\` must be a valid address, got ${JSON.stringify(domain.verifyingContract)}`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: domain.name,\n\t\t\tversion: domain.version,\n\t\t\tverifyingContract: getAddress(domain.verifyingContract),\n\t\t};\n\t}\n\t// Defensive: TS exhaustiveness guarantees this is unreachable at compile\n\t// time, but a JS consumer could smuggle through an unknown kind.\n\tconst exhaustive = asset as { kind: string };\n\tthrow new X402InvalidConfigError(\n\t\t\"asset.kind\",\n\t\t`unsupported kind ${JSON.stringify(exhaustive.kind)}. Expected \"known\" or \"unsafeOverride\".`,\n\t);\n}\n\n/**\n * Assemble the EIP-712 {@link Eip3009Domain} from a construction-time pinned\n * {@link ResolvedAsset} and the runtime `chainId`.\n *\n * The single place that maps `(pinned asset, chainId) -> domain`, so every\n * signing path (`src/x402/client.ts`, `src/signer/`) builds the domain\n * identically — the domain half of the EIP-712 single-source-of-truth the\n * `mpc-2p` backend relies on (RFC M6-1 §4.5, H1). `name` / `version` /\n * `verifyingContract` come from the pinned asset; only `chainId` is per-request.\n */\nexport function resolvedAssetToEip3009Domain(asset: ResolvedAsset, chainId: number): Eip3009Domain {\n\treturn {\n\t\tname: asset.name,\n\t\tversion: asset.version,\n\t\tchainId,\n\t\tverifyingContract: asset.verifyingContract,\n\t};\n}\n","/**\n * EIP-3009 typed-data builders and signing helpers.\n *\n * Token-agnostic: works for any EIP-3009-compliant token (JPYC, USDC, USDP,\n * Centre FiatToken family). Pure off-chain construction — no chain RPC, no\n * submission. Submission is the caller's job (M3 x402 flow, or arbitrary\n * gas-paying relayer).\n *\n * @packageDocumentation\n */\n\nimport {\n\ttype Account,\n\ttype Address,\n\tgetAddress,\n\ttype Hex,\n\tkeccak256,\n\tparseSignature,\n\tstringToHex,\n} from \"viem\";\n\n// ---------------------------------------------------------------------------\n// Domain & typed-data shapes\n// ---------------------------------------------------------------------------\n\n/**\n * EIP-712 domain for an EIP-3009-compliant token.\n *\n * `name` and `version` MUST match the values the token used when computing\n * its `DOMAIN_SEPARATOR`. For JPYC see {@link JPYC_EIP712_DOMAIN_HINT}.\n */\nexport interface Eip3009Domain {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly chainId: number;\n\treadonly verifyingContract: Address;\n}\n\n/** Message body for {@link signTransferWithAuthorization}. */\nexport interface TransferWithAuthorizationMessage {\n\treadonly from: Address;\n\treadonly to: Address;\n\treadonly value: bigint;\n\treadonly validAfter: bigint;\n\treadonly validBefore: bigint;\n\t/** 32-byte random nonce. Generate with {@link generateAuthorizationNonce}. */\n\treadonly nonce: Hex;\n}\n\n/** Message body for {@link signReceiveWithAuthorization}. */\nexport type ReceiveWithAuthorizationMessage = TransferWithAuthorizationMessage;\n\n/** Message body for {@link signCancelAuthorization}. */\nexport interface CancelAuthorizationMessage {\n\treadonly authorizer: Address;\n\treadonly nonce: Hex;\n}\n\n/**\n * A signed EIP-3009 authorization, ready to be passed to the token's\n * `*WithAuthorization` entrypoint as `(v, r, s)`.\n */\nexport interface SignedAuthorization<TMessage> {\n\treadonly signature: Hex;\n\treadonly v: number;\n\treadonly r: Hex;\n\treadonly s: Hex;\n\treadonly domain: Eip3009Domain;\n\treadonly message: TMessage;\n}\n\n// ---------------------------------------------------------------------------\n// EIP-712 type definitions (must match EIP-3009 byte-for-byte)\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical EIP-712 `TransferWithAuthorization` type definition.\n *\n * This is the **single source of truth** for the typed-data structure (field\n * names, types, and order) that EIP-3009 hashes and `ecrecover` verifies.\n * Exported so out-of-process / cross-language consumers — notably the `mpc-2p`\n * co-signer backend (RFC M6-1 §4.5, H1) — bind to this exact definition (or\n * codegen from it) instead of re-declaring it, and so the digest the policy\n * gates on is provably the digest the chain verifies (see the digest-conformance\n * corpus in `__fixtures__/eip3009-digest.vectors.json`).\n */\nexport const transferWithAuthorizationTypes = {\n\tTransferWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n/** Canonical EIP-712 `ReceiveWithAuthorization` types. See {@link transferWithAuthorizationTypes}. */\nexport const receiveWithAuthorizationTypes = {\n\tReceiveWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n/** Canonical EIP-712 `CancelAuthorization` types. See {@link transferWithAuthorizationTypes}. */\nexport const cancelAuthorizationTypes = {\n\tCancelAuthorization: [\n\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Generates a cryptographically random 32-byte EIP-3009 nonce.\n *\n * The nonce only needs to be unique per `(authorizer, contract)` — duplicates\n * across different tokens are harmless because the contract scopes them.\n *\n * @example\n * ```ts\n * import { generateAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = generateAuthorizationNonce();\n * ```\n */\nexport function generateAuthorizationNonce(): Hex {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")}` as Hex;\n}\n\n/** Domain tag separating the nonce preimage from any other keccak use in the SDK. */\nconst EIP3009_NONCE_DOMAIN_TAG = \"kawasekit/eip3009-nonce/1\";\n\n/**\n * Derives a **deterministic** 32-byte EIP-3009 nonce from a reasoning-step\n * idempotency key, scoped to `(from, verifyingContract, chainId)` so the same\n * key never collides across tokens or chains (M5-1, Half B).\n *\n * `nonce = keccak256(DOMAIN_TAG ‖ idempotencyKey ‖ from ‖ verifyingContract ‖\n * chainId)`. **No shared secret**: determinism across replicas / sub-agents\n * needs only a shared `conversationId` (the source of the key), not secret\n * distribution. A replayed key ⇒ identical nonce ⇒ the token contract's\n * `authorizationState` rejects the second settlement — the on-chain last line of\n * defence against re-signed same-intent duplicate payments. Use in place of\n * {@link generateAuthorizationNonce} only when a key is available.\n *\n * `chainId` is in the preimage, so the same JPYC address on Polygon / Avalanche\n * / Kaia / Ethereum yields distinct nonces (cross-chain replay safety).\n *\n * @example\n * ```ts\n * import { deriveAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = deriveAuthorizationNonce(\n * { idempotencyKey },\n * { from: account.address, verifyingContract, chainId },\n * );\n * ```\n */\nexport function deriveAuthorizationNonce(\n\tinput: { readonly idempotencyKey: string },\n\tscope: { readonly from: Address; readonly verifyingContract: Address; readonly chainId: number },\n): Hex {\n\tif (input.idempotencyKey === \"\") {\n\t\tthrow new Error(\"deriveAuthorizationNonce: idempotencyKey must be a non-empty string\");\n\t}\n\tconst preimage = JSON.stringify([\n\t\tEIP3009_NONCE_DOMAIN_TAG,\n\t\tinput.idempotencyKey,\n\t\tgetAddress(scope.from),\n\t\tgetAddress(scope.verifyingContract),\n\t\tscope.chainId,\n\t]);\n\treturn keccak256(stringToHex(preimage));\n}\n\n/**\n * Returns a `validBefore` UNIX timestamp `seconds` in the future.\n *\n * @param seconds - Lifetime of the authorization, in seconds.\n * @param nowSec - Optional override of \"now\" (defaults to {@link Date.now}).\n *\n * @example\n * ```ts\n * import { authorizationDeadlineFromNow } from \"kawasekit\";\n *\n * const validBefore = authorizationDeadlineFromNow(60 * 5); // 5 minutes\n * ```\n */\nexport function authorizationDeadlineFromNow(seconds: number, nowSec?: bigint): bigint {\n\tconst now = nowSec ?? BigInt(Math.floor(Date.now() / 1000));\n\treturn now + BigInt(seconds);\n}\n\nfunction requireSignTypedData(account: Account): NonNullable<Account[\"signTypedData\"]> {\n\tif (!account.signTypedData) {\n\t\tthrow new Error(\n\t\t\t`Account ${account.address} cannot sign typed data — pass a LocalAccount or a JsonRpcAccount bound to a WalletClient.`,\n\t\t);\n\t}\n\treturn account.signTypedData.bind(account);\n}\n\nfunction assertSignerMatches(account: Account, expectedFrom: Address, role: string): void {\n\tif (getAddress(account.address) !== getAddress(expectedFrom)) {\n\t\tthrow new Error(\n\t\t\t`EIP-3009 ${role} signature must come from \\`${role === \"cancel\" ? \"authorizer\" : \"from\"}\\`: account is ${account.address}, message says ${expectedFrom}.`,\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Signers\n// ---------------------------------------------------------------------------\n\n/**\n * Signs an EIP-3009 `TransferWithAuthorization` message.\n *\n * The signing account MUST equal `message.from` — EIP-3009 rejects signatures\n * from anyone else (the on-chain check is pure `ecrecover` against `from`).\n *\n * @example\n * ```ts\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * authorizationDeadlineFromNow,\n * generateAuthorizationNonce,\n * JPYC_EIP712_DOMAIN_HINT,\n * polygon,\n * signTransferWithAuthorization,\n * } from \"kawasekit\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const signed = await signTransferWithAuthorization(account, {\n * ...JPYC_EIP712_DOMAIN_HINT,\n * chainId: polygon.id,\n * verifyingContract: \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\",\n * }, {\n * from: account.address,\n * to: \"0xBeef...\",\n * value: 100n * 10n ** 18n,\n * validAfter: 0n,\n * validBefore: authorizationDeadlineFromNow(300),\n * nonce: generateAuthorizationNonce(),\n * });\n * // → submit (v, r, s) to token.transferWithAuthorization(...)\n * ```\n */\nexport async function signTransferWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: TransferWithAuthorizationMessage,\n): Promise<SignedAuthorization<TransferWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"transfer\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: transferWithAuthorizationTypes,\n\t\tprimaryType: \"TransferWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `ReceiveWithAuthorization` message.\n *\n * Differs from {@link signTransferWithAuthorization} in two ways:\n * 1. Uses the `ReceiveWithAuthorization` EIP-712 type.\n * 2. The contract additionally enforces `msg.sender == to` at submission\n * time, so only `to` (or a relayer impersonating `to` — impossible in\n * practice) can land the tx.\n */\nexport async function signReceiveWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: ReceiveWithAuthorizationMessage,\n): Promise<SignedAuthorization<ReceiveWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"receive\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: receiveWithAuthorizationTypes,\n\t\tprimaryType: \"ReceiveWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `CancelAuthorization` message.\n *\n * Cancelling consumes the nonce so a later `transferWithAuthorization` or\n * `receiveWithAuthorization` with the same nonce will revert.\n */\nexport async function signCancelAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: CancelAuthorizationMessage,\n): Promise<SignedAuthorization<CancelAuthorizationMessage>> {\n\tassertSignerMatches(account, message.authorizer, \"cancel\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: cancelAuthorizationTypes,\n\t\tprimaryType: \"CancelAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\nfunction splitAuthorization<TMessage>(\n\tsignature: Hex,\n\tdomain: Eip3009Domain,\n\tmessage: TMessage,\n): SignedAuthorization<TMessage> {\n\tconst parsed = parseSignature(signature);\n\t// viem's parseSignature returns yParity ∈ {0, 1} as well as v when present.\n\tconst v = parsed.v !== undefined ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;\n\treturn {\n\t\tsignature,\n\t\tv,\n\t\tr: parsed.r,\n\t\ts: parsed.s,\n\t\tdomain,\n\t\tmessage,\n\t};\n}\n","/**\n * The `local` PolicyGatedSigner adapter — `enforcement: \"advisory\"`.\n *\n * Wraps a viem {@link Account} + a {@link SpendingPolicy} + a pinned EIP-712\n * domain. `sign(intent)` evaluates the policy SDK-side and, on pass, produces a\n * real EIP-3009 authorization via {@link signTransferWithAuthorization}. It is\n * **advisory** because the wrapped key can still sign anything elsewhere — the\n * gate is only reached if the caller chooses to call *this* `sign()`. Use it for\n * dev, the A1 cross-language fallback, and any flow that is explicitly not\n * bounded/regulated; the type-gate (`requireNonBypassable`) keeps it out of\n * flows that require non-bypassable enforcement.\n *\n * @packageDocumentation\n */\n\nimport type { Account } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { SpendingPolicy, SpendState } from \"../policy/spending-policy\";\nimport { evaluateSpendingPolicy } from \"../policy/spending-policy\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { signTransferWithAuthorization } from \"../tokens/eip3009\";\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { PaymentIntent, PolicyGatedSigner, SignerDescription, SignResult } from \"./types\";\n\n/** Parameters for {@link createLocalPolicyGatedSigner}. */\nexport interface CreateLocalPolicyGatedSignerParams {\n\t/** EOA / LocalAccount that signs the EIP-3009 authorization. */\n\treadonly account: Account;\n\t/** The spending policy this signer enforces (SDK-side, advisory). */\n\treadonly policy: SpendingPolicy;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract`. */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Required literal acknowledgement that this signer is **advisory** (a\n\t * key-holder can bypass its policy). Omitting it is a compile error (TS) and\n\t * a construction-time throw (JS) — so constructing an advisory signer is a\n\t * conscious, greppable act. For bounded/regulated flows use a cryptographic\n\t * adapter instead.\n\t */\n\treadonly acknowledgeAdvisory: true;\n\t/**\n\t * Optional cumulative-spend view (read-only) the adapter evaluates\n\t * `cumulativeCap` against. `local` does not own an authoritative ledger; the\n\t * caller folds a successful spend back in (e.g. via `mergeSpendState`) before\n\t * the next call. Default: empty.\n\t */\n\treadonly spendState?: () => SpendState | Promise<SpendState>;\n}\n\n/**\n * Construct a `local` (advisory) PolicyGatedSigner.\n *\n * @example\n * ```ts\n * const signer = createLocalPolicyGatedSigner({\n * account,\n * policy: createSpendingPolicy({ session: { id, notAfter }, perToken: [{ token: JPYC, maxPerSign: 1_000n }], recipientAllowlist: \"any\" }),\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * acknowledgeAdvisory: true,\n * });\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createLocalPolicyGatedSigner(\n\tparams: CreateLocalPolicyGatedSignerParams,\n): PolicyGatedSigner<\"advisory\"> {\n\tif (params.acknowledgeAdvisory !== true) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"acknowledgeAdvisory\",\n\t\t\t\"a local signer is advisory (a key-holder can bypass its policy); pass `acknowledgeAdvisory: true` to construct one consciously, or use a cryptographic adapter for bounded/regulated flows\",\n\t\t);\n\t}\n\n\tconst { account, policy, spendState } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(account.address);\n\n\treturn {\n\t\tenforcement: \"advisory\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"from_mismatch\",\n\t\t\t\t\t\tdetail: `intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"token_not_allowed\",\n\t\t\t\t\t\tdetail: `intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst state: SpendState = (await spendState?.()) ?? { spentPerToken: [] };\n\t\t\tconst nowSeconds = BigInt(Math.floor(Date.now() / 1000));\n\t\t\tconst decision = evaluateSpendingPolicy(policy, intent, state, nowSeconds);\n\t\t\tif (!decision.ok) {\n\t\t\t\treturn { ok: false, rejection: decision.rejection };\n\t\t\t}\n\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\tresolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\t{\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { ok: true, signature: signed.signature, intent };\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"advisory\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: policy.session.id,\n\t\t\t\tnotAfter: policy.session.notAfter,\n\t\t\t\trevoked: policy.revoked,\n\t\t\t};\n\t\t},\n\t};\n}\n","/**\n * The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control\n * envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.\n *\n * This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):\n * a small, versioned envelope carries the decoded {@link PaymentIntent} (never a\n * digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque\n * DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The\n * shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**\n * (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,\n * `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame\n * the SDK builds round-trips through the backend's `serde_json`.\n *\n * `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it\n * reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected\n * authenticator's HMAC equals what the co-signer verifies (RFC §4.6:\n * `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).\n *\n * @packageDocumentation\n */\n\nimport type { Hex } from \"viem\";\nimport type { PaymentIntent } from \"./types\";\n\n/** The wire protocol version. A frame whose `wire_version` differs is rejected. */\nexport const WIRE_VERSION = 2 as const;\n\n/**\n * The inbound round-payload bound, in bytes — mirrors the backend's\n * `crypto-core/src/transport.rs` `MAX_FRAME_BYTES` (8 MiB) so the agent side\n * enforces the same pre-decode cap the backend does (RFC m6-3a §4.2/M3). The\n * adapter refuses an over-bound `round` payload **before** hex-decoding it into\n * the WASM boundary; the private transport should additionally cap raw\n * websocket messages (e.g. the `ws` client's `maxPayload`).\n */\nexport const MAX_FRAME_BYTES = 8 * 1024 * 1024;\n\n/**\n * The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`\n * addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any\n * library's native serde so a stdlib client reproduces it trivially; matches the\n * Rust `WireIntent` field names + encoding exactly.\n */\nexport interface WireIntent {\n\treadonly token: string;\n\treadonly chain_id: number;\n\treadonly from: string;\n\treadonly to: string;\n\treadonly value: string;\n\treadonly valid_after: string;\n\treadonly valid_before: string;\n\treadonly nonce: string;\n}\n\n/** Encode a decoded {@link PaymentIntent} for the wire. */\nexport function toWireIntent(intent: PaymentIntent): WireIntent {\n\treturn {\n\t\ttoken: intent.token.toLowerCase(),\n\t\tchain_id: intent.chainId,\n\t\tfrom: intent.from.toLowerCase(),\n\t\tto: intent.to.toLowerCase(),\n\t\tvalue: intent.value.toString(),\n\t\tvalid_after: intent.validAfter.toString(),\n\t\tvalid_before: intent.validBefore.toString(),\n\t\tnonce: intent.nonce.toLowerCase(),\n\t};\n}\n\n/**\n * The A3 request envelope the adapter generates per `sign()` and authenticates: a\n * per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element\n * (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).\n */\nexport interface CoSignRequestEnvelope {\n\treadonly ceremonyId: string;\n\treadonly ssid: string;\n\treadonly intent: PaymentIntent;\n\t/** Unix seconds; the backend checks it against a clock-skew window. */\n\treadonly freshnessTs: number;\n\t/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */\n\treadonly freshnessNonce: Hex;\n}\n\n/**\n * A versioned control frame: the only cross-language content of the wire. The\n * DKLs round bytes ride opaque inside `payload`; everything else is the small,\n * pinned envelope. Internally tagged by `kind` (matches the Rust serde).\n */\nexport type CoSignFrame = { readonly wire_version: typeof WIRE_VERSION } & (\n\t| {\n\t\t\treadonly kind: \"request\";\n\t\t\treadonly session_id: string;\n\t\t\treadonly ceremony_id: string;\n\t\t\treadonly ssid: string;\n\t\t\treadonly intent: WireIntent;\n\t\t\treadonly freshness_ts: number;\n\t\t\treadonly freshness_nonce: Hex;\n\t\t\t/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */\n\t\t\treadonly auth_tag: Hex;\n\t }\n\t| { readonly kind: \"round\"; readonly payload: Hex }\n\t| { readonly kind: \"result\"; readonly r: Hex; readonly s: Hex; readonly v: number }\n\t| { readonly kind: \"rejection\"; readonly reason: string; readonly detail: string }\n\t| { readonly kind: \"error\"; readonly message: string }\n);\n\n/**\n * The A3 canonical encoding of a request — a byte-exact mirror of the backend's\n * `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,\n * one `key=value\\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖\n * canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,\n * decimal integers, trailing newline). The injected authenticator HMACs these\n * bytes; because the encoding is shared, the tag equals the co-signer's.\n */\nexport function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array {\n\tconst i = env.intent;\n\tconst lines = [\n\t\t\"kawasekit-mpc-2p/cosign-request/v3\",\n\t\t\"wireVersion=2\",\n\t\t`ceremonyId=${env.ceremonyId}`,\n\t\t`ssid=${env.ssid}`,\n\t\t`token=${i.token.toLowerCase()}`,\n\t\t`chainId=${i.chainId}`,\n\t\t`from=${i.from.toLowerCase()}`,\n\t\t`to=${i.to.toLowerCase()}`,\n\t\t`value=${i.value}`,\n\t\t`validAfter=${i.validAfter}`,\n\t\t`validBefore=${i.validBefore}`,\n\t\t`nonce=${i.nonce.toLowerCase()}`,\n\t\t`freshnessTs=${env.freshnessTs}`,\n\t\t`freshnessNonce=${env.freshnessNonce.toLowerCase()}`,\n\t];\n\treturn new TextEncoder().encode(lines.map((l) => `${l}\\n`).join(\"\"));\n}\n","/**\n * The `mpc-2p` PolicyGatedSigner adapter — `enforcement: \"cryptographic\"`.\n *\n * A 2-of-2 MPC co-signer: the agent holds ONE DKLs share, the owner backend holds\n * the other + the authoritative policy gate. No valid signature exists without a\n * **policy-passing co-sign**, so — unlike `local` — a single key-holder cannot\n * bypass the policy. That is what earns the non-bypassable `\"cryptographic\"` label\n * and lets the M6-0 type-gate (`requireNonBypassable`) reject an advisory signer at\n * compile time in bounded flows.\n *\n * **Open-core / thin adapter.** This module is pure orchestration over injected\n * interfaces — it ships in the public SDK with **no crypto, no socket, no key**:\n *\n * - {@link Mpc2pCoSignAgent} — the WASM DKLs share (the private package's compiled\n * `crypto-core`); drives the agent's half of the ceremony round-by-round.\n * - {@link CoSignTransport} — the authenticated, encrypted (wss/mTLS) frame channel\n * to the owner backend (the private package's transport).\n * - {@link CoSignRequestAuthenticator} — the A3 HMAC (the pre-shared key never\n * enters this module).\n *\n * The adapter owns the protocol: it pins the EIP-712 domain, **re-derives the\n * digest from the intent (A4)** via the shared `transferWithAuthorizationTypes`\n * source-of-truth, computes the A3 canonical bytes, frames the versioned\n * {@link CoSignFrame} envelope, pumps the ceremony, and maps the terminal frame to\n * a {@link SignResult}. Crucially it has **no local-signing path**: any\n * transport/availability failure throws {@link CoSignUnavailableError}, never an\n * `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback\n * guarantee, RFC m6-3a constraint 3 / W8).\n *\n * **Wire hardening (RFC §4.7/§4.8, Track C):** a bounded **transient-only retry**\n * replays the byte-identical intent (nonce included — idempotency-by-nonce is the\n * safety net) under a fresh A3 envelope and accepts the backend's **roundless\n * idempotent-replay result** via an ecrecover/low-S self-check; the **ceremony\n * deadline always fires before `validBefore`** (minus a clock-skew budget, W11),\n * and inbound round payloads are **bounded** before the WASM boundary (M3). Tuning\n * via {@link Mpc2pWireOptions}.\n *\n * @packageDocumentation\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { getAddress, hashTypedData, recoverAddress, serializeSignature, toHex } from \"viem\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { transferWithAuthorizationTypes } from \"../tokens/eip3009\";\nimport { CoSignUnavailableError, PolicyGatedSignerConfigError } from \"./errors\";\nimport type { CoSignFrame, CoSignRequestEnvelope } from \"./mpc-2p-wire\";\nimport { canonicalRequestBytes, MAX_FRAME_BYTES, toWireIntent, WIRE_VERSION } from \"./mpc-2p-wire\";\nimport type {\n\tPaymentIntent,\n\tPolicyGatedSigner,\n\tPolicyRejection,\n\tSignerDescription,\n\tSignResult,\n} from \"./types\";\n\n/** The agent's half of the 2-of-2 ceremony (the injected WASM DKLs share). */\nexport interface Mpc2pCoSignAgent {\n\t/** The group 2-of-2 EOA this share controls — must equal the signer's `from`. */\n\tgroupEoa(): Address;\n\t/** Begin signing the 32-byte EIP-712 `digest`; returns the first outbound round (hex). */\n\tstart(digest: Hex): Hex;\n\t/** Feed one inbound round (hex); returns the next outbound round, or the final signature. */\n\tstep(incoming: Hex): Mpc2pStepOutcome;\n}\n\n/** The result of one {@link Mpc2pCoSignAgent.step}. */\nexport type Mpc2pStepOutcome =\n\t| { readonly outbound: Hex }\n\t| { readonly signature: { readonly r: Hex; readonly s: Hex; readonly v: number } };\n\n/** One authenticated, encrypted ceremony connection to the owner backend. */\nexport interface CoSignConnection {\n\t/** Send one control frame. */\n\tsend(frame: CoSignFrame): Promise<void>;\n\t/** Receive the next control frame (resolves per round). */\n\trecv(): Promise<CoSignFrame>;\n\t/** Release the connection (best-effort; errors here are ignored). */\n\tclose(): void | Promise<void>;\n}\n\n/** Opens a wss/mTLS {@link CoSignConnection} for a single co-sign ceremony. */\nexport interface CoSignTransport {\n\tconnect(): Promise<CoSignConnection>;\n}\n\n/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */\nexport interface CoSignRequestAuthenticator {\n\t/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */\n\ttag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;\n}\n\n/**\n * Wire liveness / retry tuning (RFC m6-3a §4.7 + §4.8). Every field is optional\n * with a safe default. The invariants these enforce:\n *\n * - **Retry (4b/H2):** only the **transient transport class** is retried (connect\n * failed / connection dropped), replaying the **byte-identical intent** — nonce\n * included, so the backend's idempotency-by-nonce is the safety net — under a\n * fresh A3 envelope (the freshness guard rejects a replayed envelope by design).\n * A delivered rejection, a ban/identifiable-abort, a protocol anomaly, or a\n * timeout is never retried.\n * - **Liveness (4c/W11/M1+M3):** the ceremony deadline always fires **before**\n * `intent.validBefore − clockSkewBudgetSecs` (a co-signature must never be born\n * expired), and a `sign()` whose remaining window is under\n * `minWindowSecs + clockSkewBudgetSecs` is refused up front.\n * - **Inbound bound (4c/M3):** a `round` payload over `maxFrameBytes` is refused\n * before it reaches the WASM boundary (mirrors the backend's bound).\n */\nexport interface Mpc2pWireOptions {\n\t/** Max ceremony attempts for transient transport failures (default 2 = one retry). */\n\treadonly maxAttempts?: number;\n\t/** Overall per-`sign()` budget in ms, across ALL attempts (default 30_000). */\n\treadonly ceremonyTimeoutMs?: number;\n\t/** Minimum remaining validity window required at `sign()` start, in seconds (default 30). */\n\treadonly minWindowSecs?: number;\n\t/** Max tolerated agent-host clock skew, in seconds (default 30). */\n\treadonly clockSkewBudgetSecs?: number;\n\t/** Inbound round-payload bound in bytes (default {@link MAX_FRAME_BYTES} = 8 MiB). */\n\treadonly maxFrameBytes?: number;\n}\n\n/** Parameters for {@link createMpc2pPolicyGatedSigner}. */\nexport interface Mpc2pSignerParams {\n\t/** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */\n\treadonly from: Address;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract` (A4). */\n\treadonly asset: X402AssetParam;\n\t/** The bound policy session, for `describe()` (the backend holds the authoritative policy). */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\t/** The injected WASM DKLs share (private package). */\n\treadonly agent: Mpc2pCoSignAgent;\n\t/** The injected wss/mTLS frame channel (private package). */\n\treadonly transport: CoSignTransport;\n\t/** The injected A3 authenticator (the pre-shared key never enters the SDK). */\n\treadonly authenticator: CoSignRequestAuthenticator;\n\t/** Wire liveness / retry tuning (optional; safe defaults — {@link Mpc2pWireOptions}). */\n\treadonly wire?: Mpc2pWireOptions;\n}\n\n/**\n * The backend `rejection` reasons that are genuine **policy denials** (the owner\n * decided \"no\" — audit-meaningful → `{ ok: false, rejection }`). Any other reason\n * on a rejection frame is treated as \"the owner did not cleanly decide\" and throws\n * {@link CoSignUnavailableError} (no-silent-fallback; never a misclassified denial).\n */\nconst POLICY_REASONS: ReadonlySet<PolicyRejection[\"reason\"]> = new Set([\n\t\"revoked\",\n\t\"expired\",\n\t\"token_not_allowed\",\n\t\"recipient_not_allowed\",\n\t\"amount_exceeds_per_sign\",\n\t\"amount_exceeds_cumulative\",\n\t\"intent_digest_mismatch\",\n\t\"unauthenticated\",\n\t\"from_mismatch\",\n\t\"nonce_reuse_conflict\",\n]);\n\nfunction rejection(reason: PolicyRejection[\"reason\"], detail: string): SignResult {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +\n * transport + authenticator.\n *\n * @example\n * ```ts\n * // The agent, transport and authenticator come from the private `kawasekit-mpc-2p`\n * // package (the WASM share, the wss/mTLS client, the HMAC key) — never bundled here.\n * const signer = createMpc2pPolicyGatedSigner({\n * from: groupEoa,\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * session: { id: \"sess-1\", notAfter: 2_000_000_000n },\n * agent, transport, authenticator,\n * });\n * requireNonBypassable(signer); // ✓ \"cryptographic\" — passes the type-gate\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createMpc2pPolicyGatedSigner(\n\tparams: Mpc2pSignerParams,\n): PolicyGatedSigner<\"cryptographic\"> {\n\tconst { agent, transport, authenticator, session } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(params.from);\n\tconst wire = params.wire ?? {};\n\tconst maxAttempts = Math.max(1, wire.maxAttempts ?? 2);\n\tconst ceremonyTimeoutMs = wire.ceremonyTimeoutMs ?? 30_000;\n\tconst minWindowSecs = wire.minWindowSecs ?? 30;\n\tconst clockSkewBudgetSecs = wire.clockSkewBudgetSecs ?? 30;\n\tconst maxFrameBytes = wire.maxFrameBytes ?? MAX_FRAME_BYTES;\n\n\t// The injected share MUST control the declared group EOA, or every signature\n\t// would recover to the wrong address.\n\tconst agentEoa = getAddress(agent.groupEoa());\n\tif (agentEoa !== from) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"from\",\n\t\t\t`the agent share controls ${agentEoa} but params.from is ${from}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tenforcement: \"cryptographic\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\t// Adapter-local pre-checks (cheap; no wire needed). Same shape as `local`.\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"from_mismatch\",\n\t\t\t\t\t`intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"token_not_allowed\",\n\t\t\t\t\t`intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// A4: re-derive the EIP-712 digest from the intent + the pinned domain (the\n\t\t\t// SDK's exported types are the cross-language source of truth). The agent and\n\t\t\t// the backend each sign THIS digest; the SoT keeps them byte-identical.\n\t\t\tconst digest = hashTypedData({\n\t\t\t\tdomain: resolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\ttypes: transferWithAuthorizationTypes,\n\t\t\t\tprimaryType: \"TransferWithAuthorization\",\n\t\t\t\tmessage: {\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// 4c (W11/M1+M3) — the ceremony-liveness minimum-window invariant: the rounds +\n\t\t\t// the bounded retry budget must all complete BEFORE validBefore, and validity is\n\t\t\t// judged against chain time, so the agent host's clock-skew budget is part of the\n\t\t\t// bar. A window already too small risks a born-expired signature (wasted\n\t\t\t// facilitator gas + retry/cap pressure); the owner has not decided anything, so\n\t\t\t// this throws (never a rejection).\n\t\t\tconst validBeforeSecs = Number(intent.validBefore);\n\t\t\tconst nowSecs = Math.floor(Date.now() / 1000);\n\t\t\tif (validBeforeSecs - nowSecs < minWindowSecs + clockSkewBudgetSecs) {\n\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t`intent.validBefore (${validBeforeSecs}) leaves under the minimum ceremony window (${minWindowSecs}s + ${clockSkewBudgetSecs}s clock-skew budget) — refusing a co-sign that risks being born expired (W11)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// One deadline for the whole sign() — every attempt included — capped so the\n\t\t\t// ceremony timeout always fires before validBefore (minus the clock-skew budget).\n\t\t\tconst deadlineMs = Math.min(\n\t\t\t\tDate.now() + ceremonyTimeoutMs,\n\t\t\t\t(validBeforeSecs - clockSkewBudgetSecs) * 1000,\n\t\t\t);\n\n\t\t\t// 4b (RFC §4.7/H2) — bounded transient-only retry. Every attempt re-presents the\n\t\t\t// *byte-identical* `intent` (nonce included — the backend's idempotency-by-nonce\n\t\t\t// + atomic SpendState are the safety net) under a FRESH A3 envelope: the\n\t\t\t// ceremonyId/ssid/freshness are per-attempt BY DESIGN (the backend's freshness\n\t\t\t// guard rejects a replayed envelope, while idempotency keys on the unchanged\n\t\t\t// EIP-3009 nonce). Only the transient transport class retries — never a\n\t\t\t// delivered rejection, never a ban/identifiable-abort, never a timeout.\n\t\t\tlet lastTransient: CoSignUnavailableError | undefined;\n\t\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n\t\t\t\tif (Date.now() >= deadlineMs) break;\n\t\t\t\t// A3 (v2): a fresh per-ceremony id + ssid + freshness (a timestamp + a\n\t\t\t\t// per-request nonce, distinct from the EIP-3009 nonce), authenticated over the\n\t\t\t\t// canonical bytes (the shared SoT; the HMAC key lives inside the injected\n\t\t\t\t// authenticator). Web Crypto is isomorphic (Node 19+ / browsers).\n\t\t\t\tconst env: CoSignRequestEnvelope = {\n\t\t\t\t\tceremonyId: globalThis.crypto.randomUUID(),\n\t\t\t\t\tssid: globalThis.crypto.randomUUID(),\n\t\t\t\t\tintent,\n\t\t\t\t\tfreshnessTs: Math.floor(Date.now() / 1000),\n\t\t\t\t\tfreshnessNonce: toHex(globalThis.crypto.getRandomValues(new Uint8Array(16))),\n\t\t\t\t};\n\t\t\t\tconst authTag = await authenticator.tag(canonicalRequestBytes(env));\n\t\t\t\ttry {\n\t\t\t\t\tconst conn = await openConnection(transport);\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await runCeremony({\n\t\t\t\t\t\t\tconn,\n\t\t\t\t\t\t\tagent,\n\t\t\t\t\t\t\tsessionId: session.id,\n\t\t\t\t\t\t\tenv,\n\t\t\t\t\t\t\tdigest,\n\t\t\t\t\t\t\tauthTag,\n\t\t\t\t\t\t\tfrom,\n\t\t\t\t\t\t\tdeadlineMs,\n\t\t\t\t\t\t\tmaxFrameBytes,\n\t\t\t\t\t\t});\n\t\t\t\t\t} finally {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait conn.close();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// best-effort cleanup; a close error must not mask the result/throw.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof CoSignUnavailableError && error.transient && attempt < maxAttempts) {\n\t\t\t\t\t\tlastTransient = error;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow (\n\t\t\t\tlastTransient ??\n\t\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\t\"co-sign ceremony budget exhausted before validBefore (W11) — no attempt could start\",\n\t\t\t\t)\n\t\t\t);\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"cryptographic\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: session.id,\n\t\t\t\tnotAfter: session.notAfter,\n\t\t\t\t// The backend owns authoritative revocation (a revoked session → a\n\t\t\t\t// rejection at sign time); this metadata field is best-effort.\n\t\t\t\trevoked: false,\n\t\t\t};\n\t\t},\n\t};\n}\n\nasync function openConnection(transport: CoSignTransport): Promise<CoSignConnection> {\n\ttry {\n\t\treturn await transport.connect();\n\t} catch (cause) {\n\t\t// Connect failure = the transient transport class (the one retried, §4.7).\n\t\tthrow new CoSignUnavailableError(\"co-signer connection failed\", { cause, transient: true });\n\t}\n}\n\n/** Everything one ceremony attempt needs (one connection, one A3 envelope). */\ninterface CeremonyContext {\n\treadonly conn: CoSignConnection;\n\treadonly agent: Mpc2pCoSignAgent;\n\treadonly sessionId: string;\n\treadonly env: CoSignRequestEnvelope;\n\treadonly digest: Hex;\n\treadonly authTag: Hex;\n\t/** The group EOA every result must recover to (the §4.4 self-check). */\n\treadonly from: Address;\n\t/** Absolute epoch-ms the ceremony must finish by (fires before validBefore — W11). */\n\treadonly deadlineMs: number;\n\t/** Inbound round-payload bound in bytes (mirrors the backend's MAX_FRAME_BYTES). */\n\treadonly maxFrameBytes: number;\n}\n\n/**\n * Drive one full ceremony attempt over `ctx.conn`: send the authenticated request +\n * the agent's first round, then pump rounds until a terminal frame. Returns a\n * {@link SignResult} (success or a policy denial) or throws\n * {@link CoSignUnavailableError}. There is no path that returns `{ ok: true }`\n * without a backend `result` frame that passes the ecrecover/low-S self-check.\n */\nasync function runCeremony(ctx: CeremonyContext): Promise<SignResult> {\n\tconst { conn, agent, env, digest, from } = ctx;\n\tconst send = async (frame: CoSignFrame): Promise<void> => {\n\t\ttry {\n\t\t\tawait withDeadline(conn.send(frame), ctx.deadlineMs);\n\t\t} catch (cause) {\n\t\t\tif (cause instanceof CoSignUnavailableError) throw cause; // the deadline (never retried)\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped while sending\", {\n\t\t\t\tcause,\n\t\t\t\ttransient: true,\n\t\t\t});\n\t\t}\n\t};\n\tconst recv = async (): Promise<CoSignFrame> => {\n\t\tlet frame: CoSignFrame;\n\t\ttry {\n\t\t\tframe = await withDeadline(conn.recv(), ctx.deadlineMs);\n\t\t} catch (cause) {\n\t\t\tif (cause instanceof CoSignUnavailableError) throw cause; // the deadline (never retried)\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped mid-ceremony\", {\n\t\t\t\tcause,\n\t\t\t\ttransient: true,\n\t\t\t});\n\t\t}\n\t\tif (frame.wire_version !== WIRE_VERSION) {\n\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t`co-signer spoke wire_version ${frame.wire_version}, expected ${WIRE_VERSION}`,\n\t\t\t);\n\t\t}\n\t\treturn frame;\n\t};\n\n\tawait send({\n\t\twire_version: WIRE_VERSION,\n\t\tkind: \"request\",\n\t\tsession_id: ctx.sessionId,\n\t\tceremony_id: env.ceremonyId,\n\t\tssid: env.ssid,\n\t\tintent: toWireIntent(env.intent),\n\t\tfreshness_ts: env.freshnessTs,\n\t\tfreshness_nonce: env.freshnessNonce,\n\t\tauth_tag: ctx.authTag,\n\t});\n\n\tlet first: Hex;\n\ttry {\n\t\tfirst = agent.start(digest);\n\t} catch (cause) {\n\t\t// A protocol-level failure, not a transport loss — restart-not-resume classifies\n\t\t// only the transient transport class as retry-safe (§4.7), so this never retries.\n\t\tthrow new CoSignUnavailableError(\"the agent failed to start the ceremony\", { cause });\n\t}\n\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: first });\n\n\tlet agentSig: { r: Hex; s: Hex; v: number } | null = null;\n\tfor (;;) {\n\t\tconst frame = await recv();\n\t\tswitch (frame.kind) {\n\t\t\tcase \"round\": {\n\t\t\t\t// 4c (M3) — the agent-side inbound bound, mirroring the backend's\n\t\t\t\t// MAX_FRAME_BYTES: an over-bound payload is refused BEFORE hex-decode and\n\t\t\t\t// before it crosses the WASM boundary.\n\t\t\t\tconst payloadBytes = (frame.payload.length - 2) / 2;\n\t\t\t\tif (payloadBytes > ctx.maxFrameBytes) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t\t`co-signer sent a ${payloadBytes}-byte round frame (bound ${ctx.maxFrameBytes}) — refused pre-decode`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet step: Mpc2pStepOutcome;\n\t\t\t\ttry {\n\t\t\t\t\tstep = agent.step(frame.payload);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\t// Protocol abort (possibly a cheating peer) — never retried (§4.7).\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the agent rejected a round frame\", { cause });\n\t\t\t\t}\n\t\t\t\tif (\"outbound\" in step) {\n\t\t\t\t\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: step.outbound });\n\t\t\t\t} else {\n\t\t\t\t\tagentSig = step.signature;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"result\": {\n\t\t\t\tconst signature = assembleSignature({ r: frame.r, s: frame.s, v: frame.v });\n\t\t\t\tif (agentSig === null) {\n\t\t\t\t\t// A ROUNDLESS result = the backend's idempotent replay (§4.7): a retry hit\n\t\t\t\t\t// a nonce whose ceremony already committed, and the CACHED signature came\n\t\t\t\t\t// back with zero rounds. There is no agent-derived signature to cross-check,\n\t\t\t\t\t// so the self-check is recovery: low-S + ecrecover(digest) == from (§4.4).\n\t\t\t\t\tawait verifyRecovers(digest, signature, frame.s, from, \"idempotent-replay\");\n\t\t\t\t\treturn { ok: true, signature, intent: env.intent };\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tframe.r.toLowerCase() !== agentSig.r.toLowerCase() ||\n\t\t\t\t\tframe.s.toLowerCase() !== agentSig.s.toLowerCase() ||\n\t\t\t\t\tframe.v !== agentSig.v\n\t\t\t\t) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the backend and agent derived different signatures\");\n\t\t\t\t}\n\t\t\t\t// The §4.4 ecrecover/low-S self-check: agent/backend agreement alone does not\n\t\t\t\t// prove the signature recovers to the group EOA over OUR digest — recovery does.\n\t\t\t\tawait verifyRecovers(digest, signature, frame.s, from, \"co-signed\");\n\t\t\t\treturn { ok: true, signature, intent: env.intent };\n\t\t\t}\n\t\t\tcase \"rejection\": {\n\t\t\t\t// A genuine policy denial → typed rejection. A non-policy \"rejection\"\n\t\t\t\t// (transient/internal/ban) is \"the owner did not decide\" → no-fallback throw,\n\t\t\t\t// and it is NOT the transient transport class (never retried — a ban or an\n\t\t\t\t// in-flight duplicate must surface, not silently re-spin).\n\t\t\t\tif (POLICY_REASONS.has(frame.reason as PolicyRejection[\"reason\"])) {\n\t\t\t\t\t// reason membership verified against POLICY_REASONS above.\n\t\t\t\t\treturn rejection(frame.reason as PolicyRejection[\"reason\"], frame.detail);\n\t\t\t\t}\n\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t`co-signer returned a non-policy rejection (${frame.reason}): ${frame.detail}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"error\": {\n\t\t\t\tthrow new CoSignUnavailableError(`co-signer error: ${frame.message}`);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t// Unknown frame kind — never a silent success.\n\t\t\t\tthrow new CoSignUnavailableError(\"co-signer sent an unexpected frame\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Race `promise` against the ceremony deadline (W11: the timeout must fire before\n * `validBefore`). A deadline strike throws a NON-transient\n * {@link CoSignUnavailableError} — the retry budget is spent, never re-spun.\n */\nfunction withDeadline<T>(promise: Promise<T>, deadlineMs: number): Promise<T> {\n\tconst remaining = deadlineMs - Date.now();\n\tif (remaining <= 0) {\n\t\treturn Promise.reject(\n\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\"co-sign ceremony timed out (the deadline fires before validBefore — W11)\",\n\t\t\t),\n\t\t);\n\t}\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\t\"co-sign ceremony timed out (the deadline fires before validBefore — W11)\",\n\t\t\t\t),\n\t\t\t);\n\t\t}, remaining);\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(cause) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(cause);\n\t\t\t},\n\t\t);\n\t});\n}\n\n/** secp256k1 n/2 — the EIP-2 low-S bound. */\nconst SECP256K1_HALF_N = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0n;\n\n/**\n * The RFC §4.4 result self-check: the signature is low-S (EIP-2) and recovers to\n * the group EOA over the adapter's OWN re-derived digest — the exact check the\n * token contract's `ecrecover` will repeat on-chain.\n */\nasync function verifyRecovers(\n\tdigest: Hex,\n\tsignature: Hex,\n\ts: Hex,\n\tfrom: Address,\n\twhat: string,\n): Promise<void> {\n\tif (BigInt(s) > SECP256K1_HALF_N) {\n\t\tthrow new CoSignUnavailableError(`the ${what} signature is not low-S (EIP-2)`);\n\t}\n\tlet recovered: Address;\n\ttry {\n\t\trecovered = await recoverAddress({ hash: digest, signature });\n\t} catch (cause) {\n\t\tthrow new CoSignUnavailableError(`the ${what} signature failed to recover`, { cause });\n\t}\n\tif (getAddress(recovered) !== from) {\n\t\tthrow new CoSignUnavailableError(\n\t\t\t`the ${what} signature recovers to ${getAddress(recovered)}, not the group EOA ${from}`,\n\t\t);\n\t}\n}\n\n/** Assemble a 65-byte EIP-3009 signature from the agent's `{ r, s, v }` (v = recovery_id + 27). */\nfunction assembleSignature(sig: { r: Hex; s: Hex; v: number }): Hex {\n\tconst yParity = sig.v - 27;\n\tif (yParity !== 0 && yParity !== 1) {\n\t\tthrow new CoSignUnavailableError(`malformed recovery id v=${sig.v} (expected 27 or 28)`);\n\t}\n\treturn serializeSignature({ r: sig.r, s: sig.s, yParity });\n}\n"]}
1
+ {"version":3,"sources":["../../src/signer/errors.ts","../../src/signer/gate.ts","../../src/policy/spending-policy.ts","../../src/x402/errors.ts","../../src/chains/avalanche.ts","../../src/chains/ethereum.ts","../../src/chains/kaia.ts","../../src/chains/polygon.ts","../../src/chains/index.ts","../../src/tokens/jpyc.ts","../../src/tokens/known-assets.ts","../../src/tokens/asset-domain.ts","../../src/tokens/eip3009.ts","../../src/signer/local.ts","../../src/signer/mpc-2p-wire.ts","../../src/signer/mpc-2p.ts"],"names":["getAddress","viemAvalanche","viemAvalancheFuji","viemMainnet","viemSepolia","viemKaia","viemKairos","viemPolygon","viemPolygonAmoy","isAddress","parseSignature","hashTypedData","toHex","recoverAddress","serializeSignature"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * PolicyGatedSigner error types.\n *\n * @packageDocumentation\n */\n\n/**\n * Thrown for a construction-time / configuration error in a PolicyGatedSigner\n * adapter — e.g. a `local` signer constructed without the required\n * `acknowledgeAdvisory: true`, or a non-bypassable signer asserted on an\n * advisory one (`assertNonBypassable`). Policy *denials* are NOT errors — they\n * are returned as a typed {@link PolicyRejection} in {@link SignResult}.\n *\n * @example\n * ```ts\n * import { createLocalPolicyGatedSigner, PolicyGatedSignerConfigError } from \"kawasekit/signer\";\n *\n * try {\n * // @ts-expect-error — acknowledgeAdvisory is required\n * createLocalPolicyGatedSigner({ account, policy, asset });\n * } catch (error) {\n * if (error instanceof PolicyGatedSignerConfigError) {\n * console.error(`${error.field}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class PolicyGatedSignerConfigError extends Error {\n\t/** The offending config field. */\n\treadonly field: string;\n\t/** Short machine-readable reason. */\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid PolicyGatedSigner config (${field}): ${reason}`, options);\n\t\tthis.name = \"PolicyGatedSignerConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown by the `mpc-2p` cryptographic adapter when the co-signer is\n * **unreachable or the ceremony could not complete** — endpoint down, TLS\n * failure, connection dropped mid-ceremony, timeout, a malformed/missing\n * terminal frame, or an internal protocol anomaly. It is a transient / internal\n * error on the throws channel (M6-0: throws are reserved for internal/config\n * errors), **distinct from a policy denial**.\n *\n * This is the **no-silent-fallback** guarantee (RFC m6-3a constraint 3 / W8):\n * the adapter has no local-signing path, so an unavailable wire NEVER yields an\n * `{ ok: true }` signature and NEVER a {@link PolicyRejection}. A `rejection`\n * means \"the owner decided no\" (audit-meaningful); a `CoSignUnavailableError`\n * means \"the owner did not decide\" — the caller may retry the *same* intent\n * (the backend's idempotency keeps a retry safe).\n *\n * @example\n * ```ts\n * try {\n * const result = await mpc2pSigner.sign(intent);\n * if (!result.ok) handleDenial(result.rejection); // owner said no\n * } catch (error) {\n * if (error instanceof CoSignUnavailableError) retryLater(); // wire was down\n * }\n * ```\n */\nexport class CoSignUnavailableError extends Error {\n\t/**\n\t * `true` when the failure is the **transient transport class** (connect failed /\n\t * connection dropped) — the only class the adapter's bounded retry replays\n\t * (RFC m6-3a §4.7: never a delivered rejection, never a ban/identifiable-abort,\n\t * never a protocol anomaly or timeout). Defaults to `false`.\n\t */\n\treadonly transient: boolean;\n\n\tconstructor(message: string, options?: { cause?: unknown; transient?: boolean }) {\n\t\tsuper(message, options?.cause === undefined ? undefined : { cause: options.cause });\n\t\tthis.name = \"CoSignUnavailableError\";\n\t\tthis.transient = options?.transient ?? false;\n\t}\n}\n","/**\n * The enforcement-level type-gate — the compile-time (and runtime) mechanism\n * that prevents an advisory signer from being substituted for an enforcing one.\n *\n * @packageDocumentation\n */\n\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { NonBypassableEnforcement, PolicyGatedSigner } from \"./types\";\n\n/**\n * Compile-time gate: accepts only a non-bypassable signer\n * (`cryptographic` | `hardware`). Passing an `advisory` (or `integrator`) signer\n * is a **compile error**, because `PolicyGatedSigner<\"advisory\">` is not\n * assignable to `PolicyGatedSigner<NonBypassableEnforcement>` (covariant `E`).\n *\n * Use it at the boundary of a bounded/regulated flow so wiring an advisory\n * signer into it fails the build, not silently at runtime.\n *\n * @example\n * ```ts\n * function payBounded(signer: PolicyGatedSigner<NonBypassableEnforcement>) { ... }\n *\n * requireNonBypassable(mpc2pSigner); // ✓ ok — cryptographic\n * // requireNonBypassable(localSigner); // ✗ compile error — advisory\n * ```\n */\nexport function requireNonBypassable<E extends NonBypassableEnforcement>(\n\tsigner: PolicyGatedSigner<E>,\n): PolicyGatedSigner<E> {\n\treturn signer;\n}\n\n/**\n * Runtime mirror of {@link requireNonBypassable}, for plain-JS call sites and as\n * defense-in-depth. Throws {@link PolicyGatedSignerConfigError} if the signer is\n * advisory/integrator (i.e. bypassable). On success, narrows the signer type to\n * {@link NonBypassableEnforcement}.\n */\nexport function assertNonBypassable(\n\tsigner: PolicyGatedSigner,\n): asserts signer is PolicyGatedSigner<NonBypassableEnforcement> {\n\tif (signer.enforcement === \"advisory\" || signer.enforcement === \"integrator\") {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"enforcement\",\n\t\t\t`expected a non-bypassable signer (cryptographic | hardware), got \"${signer.enforcement}\" — an ${signer.enforcement} signer's policy can be bypassed by a key-holder`,\n\t\t);\n\t}\n}\n","/**\n * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner\n * (M6). One declarative {@link SpendingPolicy} (session + expiry, per-token\n * `maxPerSign` + cumulative cap, recipient allowlist, `revoked`) and one pure,\n * deny-closed evaluator {@link evaluateSpendingPolicy}.\n *\n * The same specification is enforced SDK-side (the `local` adapter) and, for the\n * `mpc-2p` adapter, re-implemented backend-side in Rust (the `kawasekit-mpc-2p`\n * co-signer); a shared conformance corpus\n * (`__fixtures__/spending-policy.vectors.json`) keeps the two in lockstep.\n * The evaluator is **check-only** — it reads `SpendState` and never mutates it;\n * the cumulative-cap *commit* (folding a successful spend back in via\n * {@link mergeSpendState}) is the adapter's job, and atomic+authoritative\n * commit is a property of the `cryptographic` adapter only.\n *\n * This is the **x402-EOA** policy path. The smart-account / ZeroDev session-key\n * path is `createJpycDailyLimitPolicies` (`./daily-limit`) — a sibling, not a\n * replacement.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { PaymentIntent, PolicyRejection } from \"../signer/types\";\nimport { normalizeRecipientAllowlist } from \"./normalize-allowlist\";\n\n/** Per-token spend limits. A token absent from the policy's `perToken` is NOT allowed. */\nexport interface TokenLimit {\n\treadonly token: Address;\n\t/** Max value per single signature, token base units. Generalizes `maxAmountPerSign` (threat 1.14). */\n\treadonly maxPerSign: bigint;\n\t/** Optional total across the session. `undefined` = uncapped. MUST be `>= maxPerSign`. */\n\treadonly cumulativeCap?: bigint;\n}\n\n/**\n * Policy-as-data evaluated for every {@link PaymentIntent}. Deny-closed\n * throughout: a token not listed in `perToken` is rejected, and\n * `recipientAllowlist` is **required** — `\"any\"` (unrestricted) is a conscious,\n * greppable choice, never a silent default.\n */\nexport interface SpendingPolicy {\n\treadonly version: \"1\";\n\t/** Session id + expiry (unix seconds). An authorization may not outlive the session. */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/**\n\t * Recipient restriction (**required** — no silent allow-open default):\n\t * `\"any\"` = unrestricted, `[]` = deny-all, `[...]` = allowlist. Making\n\t * `\"any\"` explicit keeps the policy deny-closed like `perToken`.\n\t *\n\t * The on-chain {@link createJpycDailyLimitPolicies} takes the same\n\t * `Address[] | \"any\"` shape, with two on-chain-forced differences: it is\n\t * optional (omitted = `\"any\"`), and `[]` throws there (an on-chain allowlist\n\t * cannot encode deny-all).\n\t */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\treadonly revoked: boolean;\n}\n\n/**\n * Cross-call cumulative spend, per token. Injected into the evaluator (never a\n * module global). For the `local` adapter this is a single-process, caller-managed\n * **read-only view**; the authoritative ledger lives in the `cryptographic`\n * adapter's backend.\n */\nexport interface SpendState {\n\treadonly spentPerToken: readonly { readonly token: Address; readonly spent: bigint }[];\n}\n\n/** The outcome of {@link evaluateSpendingPolicy}. */\nexport type PolicyDecision =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly rejection: PolicyRejection };\n\n/** Thrown by {@link createSpendingPolicy} on a malformed policy. */\nexport class SpendingPolicyConfigError extends Error {\n\treadonly field: string;\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid SpendingPolicy (${field}): ${reason}`, options);\n\t\tthis.name = \"SpendingPolicyConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\nfunction deny(reason: PolicyRejection[\"reason\"], detail: string): PolicyDecision {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Evaluate a {@link SpendingPolicy} against a decoded {@link PaymentIntent}.\n *\n * Pure, deterministic, no I/O. Deny-closed; the first failing check wins. All\n * amount comparisons are `bigint`; all address equality uses `getAddress()` on\n * both sides. **Reads `state`, never mutates it** — see {@link mergeSpendState}.\n * `detail` strings never contain the nonce or any signature.\n *\n * @example\n * ```ts\n * const decision = evaluateSpendingPolicy(policy, intent, state, BigInt(Math.floor(Date.now() / 1000)));\n * if (!decision.ok) console.warn(decision.rejection.reason);\n * ```\n */\nexport function evaluateSpendingPolicy(\n\tpolicy: SpendingPolicy,\n\tintent: PaymentIntent,\n\tstate: SpendState,\n\tnowSeconds: bigint,\n): PolicyDecision {\n\tif (policy.revoked) {\n\t\treturn deny(\"revoked\", \"the spending policy has been revoked\");\n\t}\n\tif (nowSeconds > policy.session.notAfter) {\n\t\treturn deny(\"expired\", `session expired at ${policy.session.notAfter} (now ${nowSeconds})`);\n\t}\n\tif (intent.validBefore > policy.session.notAfter) {\n\t\treturn deny(\n\t\t\t\"expired\",\n\t\t\t`authorization validBefore ${intent.validBefore} outlives the session (notAfter ${policy.session.notAfter})`,\n\t\t);\n\t}\n\n\tconst intentToken = getAddress(intent.token);\n\tconst limit = policy.perToken.find((l) => getAddress(l.token) === intentToken);\n\tif (limit === undefined) {\n\t\treturn deny(\"token_not_allowed\", `token ${intentToken} is not in the policy`);\n\t}\n\n\tif (policy.recipientAllowlist !== \"any\") {\n\t\tconst to = getAddress(intent.to);\n\t\tconst allowed = policy.recipientAllowlist.some((a) => getAddress(a) === to);\n\t\tif (!allowed) {\n\t\t\treturn deny(\"recipient_not_allowed\", `recipient ${to} is not on the allowlist`);\n\t\t}\n\t}\n\n\tif (intent.value > limit.maxPerSign) {\n\t\treturn deny(\n\t\t\t\"amount_exceeds_per_sign\",\n\t\t\t`value ${intent.value} exceeds maxPerSign ${limit.maxPerSign}`,\n\t\t);\n\t}\n\n\tif (limit.cumulativeCap !== undefined) {\n\t\tconst spent = state.spentPerToken.find((s) => getAddress(s.token) === intentToken)?.spent ?? 0n;\n\t\tif (spent + intent.value > limit.cumulativeCap) {\n\t\t\treturn deny(\n\t\t\t\t\"amount_exceeds_cumulative\",\n\t\t\t\t`spent ${spent} + value ${intent.value} exceeds cumulativeCap ${limit.cumulativeCap}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n\n/** Parameters for {@link createSpendingPolicy}. */\nexport interface CreateSpendingPolicyParams {\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/** Required: `\"any\"` (unrestricted), `[]` (deny-all), or an allowlist. No silent default. */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\t/** Defaults to `false`. */\n\treadonly revoked?: boolean;\n}\n\n/**\n * Validate + normalize a {@link SpendingPolicy}. Checksums all addresses\n * (`getAddress`), de-dupes the recipient allowlist (shared\n * {@link normalizeRecipientAllowlist}; `[]` stays deny-all), rejects an empty\n * `perToken` (deny-closed), a non-positive `maxPerSign`/`cumulativeCap`, a\n * `cumulativeCap < maxPerSign`, and duplicate tokens. Throws\n * {@link SpendingPolicyConfigError} on violation.\n *\n * @example\n * ```ts\n * const policy = createSpendingPolicy({\n * session: { id: conversationId, notAfter: BigInt(deadline) },\n * perToken: [{ token: JPYC, maxPerSign: 1_000n, cumulativeCap: 10_000n }],\n * recipientAllowlist: [merchant],\n * });\n * ```\n */\nexport function createSpendingPolicy(params: CreateSpendingPolicyParams): SpendingPolicy {\n\tif (typeof params.session.id !== \"string\" || params.session.id === \"\") {\n\t\tthrow new SpendingPolicyConfigError(\"session.id\", \"must be a non-empty string\");\n\t}\n\tif (params.session.notAfter <= 0n) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"session.notAfter\",\n\t\t\t`must be a positive unix-seconds bigint, got ${params.session.notAfter}`,\n\t\t);\n\t}\n\tif (params.perToken.length === 0) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"perToken\",\n\t\t\t\"must list at least one token (the policy is deny-closed)\",\n\t\t);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst perToken: readonly TokenLimit[] = params.perToken.map((l) => {\n\t\tconst token = getAddress(l.token);\n\t\tif (seen.has(token)) {\n\t\t\tthrow new SpendingPolicyConfigError(\"perToken\", `duplicate token ${token}`);\n\t\t}\n\t\tseen.add(token);\n\t\tif (l.maxPerSign <= 0n) {\n\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\"perToken.maxPerSign\",\n\t\t\t\t`must be positive, got ${l.maxPerSign} for ${token}`,\n\t\t\t);\n\t\t}\n\t\tif (l.cumulativeCap !== undefined) {\n\t\t\tif (l.cumulativeCap <= 0n) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`must be positive, got ${l.cumulativeCap} for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (l.cumulativeCap < l.maxPerSign) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`cumulativeCap (${l.cumulativeCap}) must be >= maxPerSign (${l.maxPerSign}) for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { token, maxPerSign: l.maxPerSign, cumulativeCap: l.cumulativeCap };\n\t\t}\n\t\treturn { token, maxPerSign: l.maxPerSign };\n\t});\n\n\t// Checksum-normalize + de-dupe the allowlist (shared with the on-chain\n\t// daily-limit path). `[]` stays `[]` — deny-all is a valid off-chain policy.\n\tconst recipientAllowlist =\n\t\tparams.recipientAllowlist === \"any\"\n\t\t\t? \"any\"\n\t\t\t: normalizeRecipientAllowlist(params.recipientAllowlist);\n\n\treturn {\n\t\tversion: \"1\",\n\t\tsession: { id: params.session.id, notAfter: params.session.notAfter },\n\t\tperToken,\n\t\trecipientAllowlist,\n\t\trevoked: params.revoked ?? false,\n\t};\n}\n\n/**\n * Fold a successful spend back into a {@link SpendState} (pure; returns a new\n * state). The caller of the `local` adapter uses this to keep `cumulativeCap`\n * meaningful across calls — `local` does not own an authoritative ledger.\n */\nexport function mergeSpendState(\n\tstate: SpendState,\n\tspend: { readonly token: Address; readonly value: bigint },\n): SpendState {\n\tconst token = getAddress(spend.token);\n\tconst exists = state.spentPerToken.some((s) => getAddress(s.token) === token);\n\tconst spentPerToken = exists\n\t\t? state.spentPerToken.map((s) =>\n\t\t\t\tgetAddress(s.token) === token ? { token, spent: s.spent + spend.value } : s,\n\t\t\t)\n\t\t: [...state.spentPerToken, { token, spent: spend.value }];\n\treturn { spentPerToken };\n}\n","/**\n * Typed errors thrown by the `kawasekit/x402` modules.\n *\n * Centralised so that consumers can `instanceof`-discriminate without importing\n * deep paths. Additional error classes are added here as the corresponding\n * modules come online (server, facilitator, …).\n *\n * @packageDocumentation\n */\n\nimport type { PolicyRejection } from \"../signer/types\";\n\n/**\n * Thrown when an x402 wire-format payload is malformed: invalid base64, invalid\n * JSON, or a value that cannot represent the expected schema.\n *\n * Carries the offending header / context name so callers can produce actionable\n * log lines without re-parsing the message string.\n *\n * @example\n * ```ts\n * import { decodePaymentSignatureHeader, X402InvalidPayloadError } from \"kawasekit\";\n *\n * try {\n * decodePaymentSignatureHeader(headerValue);\n * } catch (error) {\n * if (error instanceof X402InvalidPayloadError) {\n * console.warn(`reject ${error.context}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402InvalidPayloadError extends Error {\n\t/** Logical name of the payload that failed (e.g. `\"PAYMENT-SIGNATURE\"`). */\n\treadonly context: string;\n\t/** Short machine-readable reason code. */\n\treadonly reason: string;\n\n\tconstructor(context: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid ${context} payload: ${reason}`, options);\n\t\tthis.name = \"X402InvalidPayloadError\";\n\t\tthis.context = context;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown when an x402 SDK construction-time configuration is invalid: an\n * unknown `asset.kind`, a known asset id that kawasekit does not ship a\n * domain for, missing required fields on an `unsafeOverride`, etc.\n *\n * Distinct from {@link X402InvalidPayloadError} (which describes wire-format\n * problems): config errors are integrator bugs, not adversarial inputs.\n *\n * @example\n * ```ts\n * import { createX402PaymentSigner, X402InvalidConfigError } from \"kawasekit\";\n *\n * try {\n * createX402PaymentSigner({\n * network: \"testnet\",\n * account,\n * // @ts-expect-error — kind: \"foo\" is not a known kind\n * asset: { kind: \"foo\" },\n * });\n * } catch (error) {\n * if (error instanceof X402InvalidConfigError) {\n * console.error(`${error.field}: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402InvalidConfigError extends Error {\n\t/** Logical name of the config field that failed (e.g. `\"asset\"`). */\n\treadonly field: string;\n\t/** Short machine-readable reason code. */\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid ${field} config: ${reason}`, options);\n\t\tthis.name = \"X402InvalidConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\n/**\n * Thrown by {@link createX402PaymentSigner} (the `signer` variant) when the bound\n * `PolicyGatedSigner` refuses to sign — i.e. its `sign()` returned\n * `{ ok: false }`. Carries the typed {@link PolicyRejection} so callers can\n * branch on `reason`. This is the policy-driven analog of the `account`\n * variant's `maxAmountPerSign` throw ({@link X402InvalidPayloadError}): the\n * `X402PaymentSigner.sign()` surface returns a payload or throws, unchanged.\n *\n * @example\n * ```ts\n * import { X402PolicyRejectedError } from \"kawasekit\";\n *\n * try {\n * await signer.sign({ paymentRequirements });\n * } catch (error) {\n * if (error instanceof X402PolicyRejectedError) {\n * console.warn(`policy refused: ${error.reason}`);\n * }\n * }\n * ```\n */\nexport class X402PolicyRejectedError extends Error {\n\t/** The policy rejection reason (e.g. `\"amount_exceeds_per_sign\"`). */\n\treadonly reason: PolicyRejection[\"reason\"];\n\t/** The full typed rejection (its `detail` never contains the nonce or signature). */\n\treadonly rejection: PolicyRejection;\n\n\tconstructor(rejection: PolicyRejection, options?: { cause?: unknown }) {\n\t\tsuper(`x402 payment rejected by policy: ${rejection.reason} (${rejection.detail})`, options);\n\t\tthis.name = \"X402PolicyRejectedError\";\n\t\tthis.reason = rejection.reason;\n\t\tthis.rejection = rejection;\n\t}\n}\n","import { avalanche as viemAvalanche, avalancheFuji as viemAvalancheFuji } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Avalanche C-Chain — priority 3 production chain.\n *\n * Snowman BFT gives sub-`2 s` **deterministic finality**, so\n * `defaultConfirmations` of `2` is ample — deep confirmations add latency for\n * no extra safety. JPYC is live at the same address as the other chains.\n *\n * The x402 EOA-payer path works today; the smart-account path via ZeroDev is\n * not yet verified on Avalanche.\n */\nexport const avalanche = {\n\t...viemAvalanche,\n\tisTestnet: false,\n\tdefaultConfirmations: 2,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Avalanche Fuji testnet. JPYC is live at the same address as the other chains\n * (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()` ==\n * \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const avalancheFuji = {\n\t...viemAvalancheFuji,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { mainnet as viemMainnet, sepolia as viemSepolia } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Ethereum mainnet — priority 4 production chain (institutional use cases).\n *\n * Casper FFG finalises in epochs (~12.8 min). `defaultConfirmations` of `32`\n * (~6.4 min at ~12 s blocks) gives finalised-grade safety. **Do NOT use\n * Polygon's `4` here** — 4 blocks (~48 s) is nowhere near finalised, and would\n * re-open the settle-reorg gap (threat 2.8). The facilitator auto-sizes\n * `receiptTimeoutMs` from this depth (~10 min), so the default does not time\n * out. JPYC is live at the same address as the other chains.\n */\nexport const ethereum = {\n\t...viemMainnet,\n\tisTestnet: false,\n\tdefaultConfirmations: 32,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n\n/**\n * Sepolia — Ethereum testnet. JPYC is live at the same address as the other\n * chains (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()`\n * == \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const sepolia = {\n\t...viemSepolia,\n\tisTestnet: true,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n","import { kaia as viemKaia, kairos as viemKairos } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Kaia mainnet — priority 2 production chain.\n *\n * Kaia (Klaytn + Finschia) runs IBFT consensus with **immediate finality** — a\n * single confirmed block is final — so `defaultConfirmations` is `1` (do NOT\n * copy Polygon's `4`). JPYC is live at the same address as the other chains\n * (`src/tokens/jpyc.ts`).\n *\n * Note: ZeroDev does not support Kaia, so the **smart-account path** (session\n * keys, sponsored UserOps) is not yet available here — it is planned via\n * Pimlico (M5-3 Phase 2). The **x402 EOA-payer path** works today.\n */\nexport const kaia = {\n\t...viemKaia,\n\tisTestnet: false,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n\n/**\n * Kairos — Kaia testnet. JPYC is available via the Kaia faucet at the same\n * address as mainnet; suitable for the same Amoy→Polygon-style testnet→mainnet\n * verification pattern.\n */\nexport const kairos = {\n\t...viemKairos,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n","import { polygon as viemPolygon, polygonAmoy as viemPolygonAmoy } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Polygon mainnet — priority 1 production chain.\n *\n * Built on viem's `polygon` definition (official RPC URLs, block explorers,\n * and `POL` native currency) plus kawasekit metadata. Polygon PoS is\n * probabilistic; the default `4` confirmations ≈ ~8 s of soft finality.\n */\nexport const polygon = {\n\t...viemPolygon,\n\tisTestnet: false,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Polygon Amoy testnet — the primary kawasekit development target.\n *\n * Built on viem's `polygonAmoy` definition. JPYC is also live on Amoy at the\n * same address as mainnet; see `src/tokens/jpyc.ts`.\n */\nexport const polygonAmoy = {\n\t...viemPolygonAmoy,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { avalanche, avalancheFuji } from \"./avalanche\";\nimport { ethereum, sepolia } from \"./ethereum\";\nimport { kaia, kairos } from \"./kaia\";\nimport { polygon, polygonAmoy } from \"./polygon\";\nimport { type KawaseChain, zerodevRpcUrl } from \"./types\";\n\nexport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\ttype KawaseChain,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n\tzerodevRpcUrl,\n};\n\n/**\n * All chains kawasekit supports, in priority order (CLAUDE.md chain priority:\n * Polygon → Kaia → Avalanche → Ethereum, each with its testnet).\n *\n * Exposed as a `readonly` tuple — **not** a `Map` — so that bundlers can\n * tree-shake chains a consumer never references.\n *\n * JPYC liveness is a separate axis (`src/tokens/jpyc.ts`): a chain can be\n * supported here while JPYC is not yet live on it (Avalanche Fuji / Sepolia).\n *\n * @example\n * ```ts\n * import { supportedChains } from \"kawasekit\";\n *\n * for (const chain of supportedChains) {\n * \tconsole.log(chain.id, chain.name);\n * }\n * ```\n */\nexport const supportedChains = [\n\tpolygon,\n\tpolygonAmoy,\n\tkaia,\n\tkairos,\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tsepolia,\n] as const;\n\n/**\n * Union of every chain ID kawasekit supports\n * (`137 | 80002 | 8217 | 1001 | 43114 | 43113 | 1 | 11155111`).\n *\n * Derived from {@link supportedChains}, so adding a chain there extends this\n * type automatically.\n */\nexport type SupportedChainId = (typeof supportedChains)[number][\"id\"];\n\n/** A single member of {@link supportedChains}, with its literal `id`. */\ntype SupportedChain = (typeof supportedChains)[number];\n\n/**\n * Internal chain lookup, built once at module scope.\n *\n * This `Map` is an implementation detail and is intentionally **not**\n * exported: the public API exposes the {@link supportedChains} tuple instead,\n * so importing one chain does not pull in all of them.\n */\nconst chainsById: ReadonlyMap<number, SupportedChain> = new Map(\n\tsupportedChains.map((chain) => [chain.id, chain]),\n);\n\n/**\n * Error thrown when a chain ID kawasekit does not support is requested.\n *\n * @example\n * ```ts\n * import { ChainNotSupportedError, getChain } from \"kawasekit\";\n *\n * try {\n * \tgetChain(1);\n * } catch (error) {\n * \tif (error instanceof ChainNotSupportedError) {\n * \t\tconsole.error(error.message);\n * \t}\n * }\n * ```\n */\nexport class ChainNotSupportedError extends Error {\n\tconstructor(chainId: number) {\n\t\tconst supported = supportedChains.map((chain) => chain.id).join(\", \");\n\t\tsuper(\n\t\t\t`Chain ID ${chainId} is not supported by kawasekit. ` + `Supported chain IDs: ${supported}.`,\n\t\t);\n\t\tthis.name = \"ChainNotSupportedError\";\n\t}\n}\n\n/**\n * Type guard that narrows an arbitrary chain ID to a {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to test.\n * @returns `true` if kawasekit supports this chain ID.\n *\n * @example\n * ```ts\n * import { isSupportedChainId } from \"kawasekit\";\n *\n * const id = 80002;\n * if (isSupportedChainId(id)) {\n * \t// `id` is now narrowed to SupportedChainId\n * }\n * ```\n */\nexport function isSupportedChainId(chainId: number): chainId is SupportedChainId {\n\treturn chainsById.has(chainId);\n}\n\n/**\n * Looks up a supported chain by its numeric chain ID.\n *\n * The returned chain's `id` is narrowed to {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to look up.\n * @returns The matching {@link KawaseChain}.\n * @throws {ChainNotSupportedError} If `chainId` is not supported.\n *\n * @example\n * ```ts\n * import { getChain } from \"kawasekit\";\n *\n * const chain = getChain(80002); // Polygon Amoy\n * console.log(chain.name);\n * ```\n */\nexport function getChain(chainId: number): SupportedChain {\n\tconst chain = chainsById.get(chainId);\n\tif (chain === undefined) {\n\t\tthrow new ChainNotSupportedError(chainId);\n\t}\n\treturn chain;\n}\n","/**\n * JPYC stablecoin metadata, deployments, and ABI.\n *\n * JPYC is a Japanese yen-pegged stablecoin issued by JPYC Inc. under the\n * revised Payment Services Act as 電子決済手段 (electronic payment\n * instrument). The new (\"v2\") JPYC, launched 2025-10, lives at the same\n * address on every chain where it is deployed.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport type { SupportedChainId } from \"../chains\";\nimport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n} from \"../chains\";\n\n/** ERC-20 decimals for JPYC. Constant across every chain. */\nexport const JPYC_DECIMALS = 18;\n\n/**\n * EIP-712 domain hint for off-chain authorization signing (EIP-3009, EIP-2612).\n *\n * The real JPYC contract does not expose `version()` publicly — it lives in an\n * `internal VERSION` state variable set during proxy initialization. The\n * canonical value is `\"1\"`, matching the FiatToken lineage; the\n * {@link signTransferWithAuthorization} helper accepts an override if a future\n * deployment changes this.\n *\n * `name` is \"JPY Coin\" — the on-chain `name()` value on every live deployment.\n */\nexport const JPYC_EIP712_DOMAIN_HINT = {\n\tname: \"JPY Coin\",\n\tversion: \"1\",\n} as const;\n\n/**\n * Address shared by every live JPYC deployment.\n *\n * Verified on:\n * - Ethereum : https://etherscan.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * - Polygon : https://polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Polygon Amoy : https://amoy.polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Avalanche : https://snowtrace.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n *\n * Do NOT confuse with the legacy 前払式支払手段 JPYC at `0x431D5dFF...`.\n */\nexport const JPYC_V2_ADDRESS: Address = \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\";\n\n/** A JPYC deployment on a single chain. */\nexport interface JpycDeployment {\n\treadonly chainId: SupportedChainId;\n\treadonly address: Address;\n\t/** `true` if the token is live on this chain right now. */\n\treadonly isLive: boolean;\n}\n\n/**\n * JPYC deployments keyed by chain.\n *\n * JPYC v2 uses the **same address** (`JPYC_V2_ADDRESS`) on every chain where it\n * is live. `isLive` is the separate \"is JPYC actually deployed here yet?\" axis.\n * All eight supported chains are live at this address: the four mainnets\n * (Polygon, Kaia, Avalanche, Ethereum) + Amoy + Kairos + Avalanche Fuji +\n * Sepolia. Kaia/Kairos/Avalanche/Fuji/Sepolia were confirmed by a read-only\n * on-chain check (`name() == \"JPY Coin\"`, `symbol() == \"JPYC\"` at `0xE7C3…`,\n * 2026-05-31); Polygon/Amoy/Ethereum are established. `isLive: false` + the\n * {@link JpycNotAvailableError} path remain for any future chain added before\n * its JPYC deployment lands.\n */\nexport const jpycDeployments: { readonly [chainId in SupportedChainId]: JpycDeployment } = {\n\t[polygon.id]: { chainId: polygon.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[polygonAmoy.id]: { chainId: polygonAmoy.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kaia.id]: { chainId: kaia.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kairos.id]: { chainId: kairos.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalanche.id]: { chainId: avalanche.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[ethereum.id]: { chainId: ethereum.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalancheFuji.id]: { chainId: avalancheFuji.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[sepolia.id]: { chainId: sepolia.id, address: JPYC_V2_ADDRESS, isLive: true },\n};\n\n/**\n * Thrown when JPYC is not deployed on the requested chain.\n *\n * Today this is unreachable (every {@link SupportedChainId} has a live\n * deployment), but the error class is exported for future chains (Kaia) where\n * JPYC is still in development.\n */\nexport class JpycNotAvailableError extends Error {\n\tconstructor(chainId: number) {\n\t\tsuper(`JPYC is not yet deployed on chain ID ${chainId}.`);\n\t\tthis.name = \"JpycNotAvailableError\";\n\t}\n}\n\n/**\n * Returns the JPYC contract address for a kawasekit-supported chain.\n *\n * @param chainId - A {@link SupportedChainId}.\n * @returns The JPYC contract address on that chain.\n * @throws {JpycNotAvailableError} If JPYC is not live on the chain.\n *\n * @example\n * ```ts\n * import { getJpycAddress, polygonAmoy } from \"kawasekit\";\n *\n * const address = getJpycAddress(polygonAmoy.id);\n * ```\n */\nexport function getJpycAddress(chainId: SupportedChainId): Address {\n\tconst deployment = jpycDeployments[chainId];\n\tif (!deployment.isLive) {\n\t\tthrow new JpycNotAvailableError(chainId);\n\t}\n\treturn deployment.address;\n}\n\n/**\n * Minimal JPYC ABI: ERC-20 + EIP-3009 surface that kawasekit needs.\n *\n * Excludes permit / mint / blocklist / pause — kawasekit only reads balance,\n * sends `transfer()` via UserOp, and constructs / submits EIP-3009\n * authorizations. Bringing in the full FiatTokenV1 ABI would be wasted bytes.\n */\nexport const jpycAbi = [\n\t// ----- ERC-20 read -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"name\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"symbol\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"decimals\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint8\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"totalSupply\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"balanceOf\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [{ name: \"account\", type: \"address\" }],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"allowance\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\" },\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t// ----- ERC-20 write -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transfer\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferFrom\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"approve\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- EIP-3009 -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"receiveWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"cancelAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"authorizationState\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- Events kawasekit needs to decode -----\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Transfer\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\", indexed: true },\n\t\t\t{ name: \"to\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Approval\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\", indexed: true },\n\t\t\t{ name: \"spender\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationUsed\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationCanceled\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n] as const;\n","/**\n * Known-asset registry for {@link createX402PaymentSigner}'s\n * `asset: { kind: \"known\", id }` discriminated-union branch.\n *\n * kawasekit only ships pinned EIP-712 domain definitions for assets it has\n * verified empirically against the deployed contracts. Adding a new entry\n * here requires citing the source-file + line reference for the contract\n * that owns the `name` / `version` (so the next reviewer can spot-check the\n * claim, the same discipline `docs/THREAT_MODEL.md` §0 demands of any ✅\n * verdict that delegates to an out-of-scope component).\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS } from \"./jpyc\";\n\n/** Known asset identifiers. New entries must update this union AND the table. */\nexport type KnownAssetId = \"jpyc-v2\";\n\n/** Fully-pinned EIP-712 domain for a known asset. */\nexport interface KnownAssetDomain {\n\treadonly id: KnownAssetId;\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\n/**\n * Canonical table. Lookups go through {@link getKnownAssetDomain}, which\n * returns a frozen copy so callers cannot mutate the registry.\n *\n * `verifyingContract` is the multi-chain canonical address — JPYC v2 is the\n * same address on Ethereum / Polygon (mainnet + Amoy) / Avalanche. The\n * signer cross-checks `requirements.asset` against this value at sign time,\n * so a server advertising a different `asset` is rejected before any\n * signature is produced.\n *\n * JPYC v2 domain: `name = \"JPY Coin\"`, `version = \"1\"`. Source of truth is\n * the deployed contract's `eip712Domain()` view — verified empirically and\n * also cached in `src/tokens/jpyc.ts:JPYC_EIP712_DOMAIN_HINT`.\n */\nconst KNOWN_ASSETS: ReadonlyArray<KnownAssetDomain> = [\n\t{\n\t\tid: \"jpyc-v2\",\n\t\tname: JPYC_EIP712_DOMAIN_HINT.name,\n\t\tversion: JPYC_EIP712_DOMAIN_HINT.version,\n\t\tverifyingContract: getAddress(JPYC_V2_ADDRESS),\n\t},\n];\n\n/**\n * Look up a known asset's pinned EIP-712 domain by id.\n *\n * @returns The domain, or `undefined` if the id is not in the registry.\n *\n * @example\n * ```ts\n * import { getKnownAssetDomain } from \"kawasekit\";\n *\n * const jpyc = getKnownAssetDomain(\"jpyc-v2\");\n * if (jpyc === undefined) throw new Error(\"unreachable\");\n * console.log(jpyc.verifyingContract); // 0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * ```\n */\nexport function getKnownAssetDomain(id: KnownAssetId): KnownAssetDomain | undefined {\n\treturn KNOWN_ASSETS.find((entry) => entry.id === id);\n}\n\n/** List every known asset id (for diagnostics / error messages). */\nexport function listKnownAssetIds(): readonly KnownAssetId[] {\n\treturn KNOWN_ASSETS.map((entry) => entry.id);\n}\n","/**\n * EIP-712 asset-domain resolution for x402 / EIP-3009 signing.\n *\n * Construction-time pinning of the EIP-712 domain (`name` / `version` /\n * `verifyingContract`) a signer will use. The integrator declares an\n * {@link X402AssetParam} — either a kawasekit-maintained `known` asset or a\n * loud `unsafeOverride` — and {@link resolveAssetParam} resolves it to a pinned\n * {@link ResolvedAsset}. The signer then trusts only this pinned domain and\n * refuses to sign for a mismatched advertised asset (Threat 1.4: misadvertised\n * EIP-712 domain).\n *\n * Token-domain concern, reused by both the x402 signer (`src/x402/client.ts`)\n * and the M6 PolicyGatedSigner (`src/signer/`).\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress, isAddress } from \"viem\";\nimport { X402InvalidConfigError } from \"../x402/errors\";\nimport type { Eip3009Domain } from \"./eip3009\";\nimport {\n\tgetKnownAssetDomain,\n\ttype KnownAssetDomain,\n\ttype KnownAssetId,\n\tlistKnownAssetIds,\n} from \"./known-assets\";\n\n/** EIP-712 token domain `name` / `version` pair. */\nexport interface X402TokenDomain {\n\treadonly name: string;\n\treadonly version: string;\n}\n\n/**\n * Asset binding for {@link createX402PaymentSigner} and the M6 PolicyGatedSigner.\n * Required, discriminated.\n *\n * **Default-on whitelist**: integrators MUST declare which asset they intend\n * to sign for. The `known` branch references a kawasekit-maintained\n * whitelist (see `src/tokens/known-assets.ts`); the `unsafeOverride` branch\n * is the deliberate escape hatch for any other asset and is named loudly so\n * it survives a code review. Either way, the signer pins the EIP-712 domain\n * at construction time and refuses to sign if `paymentRequirements.asset`\n * disagrees with the pinned `verifyingContract`.\n *\n * Closes Threat 1.4 (misadvertised EIP-712 domain): the server's advertised\n * `extra.name` / `extra.version` and `asset` are all ignored for signing\n * purposes — the signer trusts only what the integrator declared here.\n */\nexport type X402AssetParam =\n\t| {\n\t\t\t/** Use a kawasekit-maintained pinned EIP-712 domain. */\n\t\t\treadonly kind: \"known\";\n\t\t\t/** The asset id to pin. See {@link KnownAssetId} for the registry. */\n\t\t\treadonly id: KnownAssetId;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Use a caller-supplied EIP-712 domain for an asset NOT on the\n\t\t\t * kawasekit whitelist. The name is deliberately loud — pick this\n\t\t\t * branch only when you have separately audited the contract and its\n\t\t\t * `eip712Domain()` output.\n\t\t\t */\n\t\t\treadonly kind: \"unsafeOverride\";\n\t\t\treadonly domain: {\n\t\t\t\treadonly name: string;\n\t\t\t\treadonly version: string;\n\t\t\t\treadonly verifyingContract: Address;\n\t\t\t};\n\t };\n\n/** Construction-time resolution of an {@link X402AssetParam} to a pinned domain. */\nexport interface ResolvedAsset {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\n/**\n * Resolve an {@link X402AssetParam} to a pinned {@link ResolvedAsset}.\n *\n * Throws {@link X402InvalidConfigError} for an unknown `known` id or a malformed\n * `unsafeOverride` domain. Pure / construction-time — no chain RPC.\n */\nexport function resolveAssetParam(asset: X402AssetParam): ResolvedAsset {\n\tif (asset.kind === \"known\") {\n\t\tconst entry: KnownAssetDomain | undefined = getKnownAssetDomain(asset.id);\n\t\tif (entry === undefined) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.id\",\n\t\t\t\t`unknown asset id ${JSON.stringify(asset.id)}. Supported: ${listKnownAssetIds()\n\t\t\t\t\t.map((id) => JSON.stringify(id))\n\t\t\t\t\t.join(\", \")}.`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: entry.name,\n\t\t\tversion: entry.version,\n\t\t\tverifyingContract: entry.verifyingContract,\n\t\t};\n\t}\n\tif (asset.kind === \"unsafeOverride\") {\n\t\tconst { domain } = asset;\n\t\tif (typeof domain.name !== \"string\" || domain.name === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.name\",\n\t\t\t\t\"`unsafeOverride.domain.name` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (typeof domain.version !== \"string\" || domain.version === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.version\",\n\t\t\t\t\"`unsafeOverride.domain.version` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (!isAddress(domain.verifyingContract, { strict: false })) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.verifyingContract\",\n\t\t\t\t`\\`unsafeOverride.domain.verifyingContract\\` must be a valid address, got ${JSON.stringify(domain.verifyingContract)}`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: domain.name,\n\t\t\tversion: domain.version,\n\t\t\tverifyingContract: getAddress(domain.verifyingContract),\n\t\t};\n\t}\n\t// Defensive: TS exhaustiveness guarantees this is unreachable at compile\n\t// time, but a JS consumer could smuggle through an unknown kind.\n\tconst exhaustive = asset as { kind: string };\n\tthrow new X402InvalidConfigError(\n\t\t\"asset.kind\",\n\t\t`unsupported kind ${JSON.stringify(exhaustive.kind)}. Expected \"known\" or \"unsafeOverride\".`,\n\t);\n}\n\n/**\n * Assemble the EIP-712 {@link Eip3009Domain} from a construction-time pinned\n * {@link ResolvedAsset} and the runtime `chainId`.\n *\n * The single place that maps `(pinned asset, chainId) -> domain`, so every\n * signing path (`src/x402/client.ts`, `src/signer/`) builds the domain\n * identically — the domain half of the EIP-712 single-source-of-truth the\n * `mpc-2p` backend relies on (RFC M6-1 §4.5, H1). `name` / `version` /\n * `verifyingContract` come from the pinned asset; only `chainId` is per-request.\n */\nexport function resolvedAssetToEip3009Domain(asset: ResolvedAsset, chainId: number): Eip3009Domain {\n\treturn {\n\t\tname: asset.name,\n\t\tversion: asset.version,\n\t\tchainId,\n\t\tverifyingContract: asset.verifyingContract,\n\t};\n}\n","/**\n * EIP-3009 typed-data builders and signing helpers.\n *\n * Token-agnostic: works for any EIP-3009-compliant token (JPYC, USDC, USDP,\n * Centre FiatToken family). Pure off-chain construction — no chain RPC, no\n * submission. Submission is the caller's job (M3 x402 flow, or arbitrary\n * gas-paying relayer).\n *\n * @packageDocumentation\n */\n\nimport {\n\ttype Account,\n\ttype Address,\n\tgetAddress,\n\ttype Hex,\n\tkeccak256,\n\tparseSignature,\n\tstringToHex,\n} from \"viem\";\n\n// ---------------------------------------------------------------------------\n// Domain & typed-data shapes\n// ---------------------------------------------------------------------------\n\n/**\n * EIP-712 domain for an EIP-3009-compliant token.\n *\n * `name` and `version` MUST match the values the token used when computing\n * its `DOMAIN_SEPARATOR`. For JPYC see {@link JPYC_EIP712_DOMAIN_HINT}.\n */\nexport interface Eip3009Domain {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly chainId: number;\n\treadonly verifyingContract: Address;\n}\n\n/** Message body for {@link signTransferWithAuthorization}. */\nexport interface TransferWithAuthorizationMessage {\n\treadonly from: Address;\n\treadonly to: Address;\n\treadonly value: bigint;\n\treadonly validAfter: bigint;\n\treadonly validBefore: bigint;\n\t/** 32-byte random nonce. Generate with {@link generateAuthorizationNonce}. */\n\treadonly nonce: Hex;\n}\n\n/** Message body for {@link signReceiveWithAuthorization}. */\nexport type ReceiveWithAuthorizationMessage = TransferWithAuthorizationMessage;\n\n/** Message body for {@link signCancelAuthorization}. */\nexport interface CancelAuthorizationMessage {\n\treadonly authorizer: Address;\n\treadonly nonce: Hex;\n}\n\n/**\n * A signed EIP-3009 authorization, ready to be passed to the token's\n * `*WithAuthorization` entrypoint as `(v, r, s)`.\n */\nexport interface SignedAuthorization<TMessage> {\n\treadonly signature: Hex;\n\treadonly v: number;\n\treadonly r: Hex;\n\treadonly s: Hex;\n\treadonly domain: Eip3009Domain;\n\treadonly message: TMessage;\n}\n\n// ---------------------------------------------------------------------------\n// EIP-712 type definitions (must match EIP-3009 byte-for-byte)\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical EIP-712 `TransferWithAuthorization` type definition.\n *\n * This is the **single source of truth** for the typed-data structure (field\n * names, types, and order) that EIP-3009 hashes and `ecrecover` verifies.\n * Exported so out-of-process / cross-language consumers — notably the `mpc-2p`\n * co-signer backend (RFC M6-1 §4.5, H1) — bind to this exact definition (or\n * codegen from it) instead of re-declaring it, and so the digest the policy\n * gates on is provably the digest the chain verifies (see the digest-conformance\n * corpus in `__fixtures__/eip3009-digest.vectors.json`).\n */\nexport const transferWithAuthorizationTypes = {\n\tTransferWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n/** Canonical EIP-712 `ReceiveWithAuthorization` types. See {@link transferWithAuthorizationTypes}. */\nexport const receiveWithAuthorizationTypes = {\n\tReceiveWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n/** Canonical EIP-712 `CancelAuthorization` types. See {@link transferWithAuthorizationTypes}. */\nexport const cancelAuthorizationTypes = {\n\tCancelAuthorization: [\n\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Generates a cryptographically random 32-byte EIP-3009 nonce.\n *\n * The nonce only needs to be unique per `(authorizer, contract)` — duplicates\n * across different tokens are harmless because the contract scopes them.\n *\n * @example\n * ```ts\n * import { generateAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = generateAuthorizationNonce();\n * ```\n */\nexport function generateAuthorizationNonce(): Hex {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")}` as Hex;\n}\n\n/** Domain tag separating the nonce preimage from any other keccak use in the SDK. */\nconst EIP3009_NONCE_DOMAIN_TAG = \"kawasekit/eip3009-nonce/1\";\n\n/**\n * Derives a **deterministic** 32-byte EIP-3009 nonce from a reasoning-step\n * idempotency key, scoped to `(from, verifyingContract, chainId)` so the same\n * key never collides across tokens or chains (M5-1, Half B).\n *\n * `nonce = keccak256(DOMAIN_TAG ‖ idempotencyKey ‖ from ‖ verifyingContract ‖\n * chainId)`. **No shared secret**: determinism across replicas / sub-agents\n * needs only a shared `conversationId` (the source of the key), not secret\n * distribution. A replayed key ⇒ identical nonce ⇒ the token contract's\n * `authorizationState` rejects the second settlement — the on-chain last line of\n * defence against re-signed same-intent duplicate payments. Use in place of\n * {@link generateAuthorizationNonce} only when a key is available.\n *\n * `chainId` is in the preimage, so the same JPYC address on Polygon / Avalanche\n * / Kaia / Ethereum yields distinct nonces (cross-chain replay safety).\n *\n * @example\n * ```ts\n * import { deriveAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = deriveAuthorizationNonce(\n * { idempotencyKey },\n * { from: account.address, verifyingContract, chainId },\n * );\n * ```\n */\nexport function deriveAuthorizationNonce(\n\tinput: { readonly idempotencyKey: string },\n\tscope: { readonly from: Address; readonly verifyingContract: Address; readonly chainId: number },\n): Hex {\n\tif (input.idempotencyKey === \"\") {\n\t\tthrow new Error(\"deriveAuthorizationNonce: idempotencyKey must be a non-empty string\");\n\t}\n\tconst preimage = JSON.stringify([\n\t\tEIP3009_NONCE_DOMAIN_TAG,\n\t\tinput.idempotencyKey,\n\t\tgetAddress(scope.from),\n\t\tgetAddress(scope.verifyingContract),\n\t\tscope.chainId,\n\t]);\n\treturn keccak256(stringToHex(preimage));\n}\n\n/**\n * Returns a `validBefore` UNIX timestamp `seconds` in the future.\n *\n * @param seconds - Lifetime of the authorization, in seconds.\n * @param nowSec - Optional override of \"now\" (defaults to {@link Date.now}).\n *\n * @example\n * ```ts\n * import { authorizationDeadlineFromNow } from \"kawasekit\";\n *\n * const validBefore = authorizationDeadlineFromNow(60 * 5); // 5 minutes\n * ```\n */\nexport function authorizationDeadlineFromNow(seconds: number, nowSec?: bigint): bigint {\n\tconst now = nowSec ?? BigInt(Math.floor(Date.now() / 1000));\n\treturn now + BigInt(seconds);\n}\n\nfunction requireSignTypedData(account: Account): NonNullable<Account[\"signTypedData\"]> {\n\tif (!account.signTypedData) {\n\t\tthrow new Error(\n\t\t\t`Account ${account.address} cannot sign typed data — pass a LocalAccount or a JsonRpcAccount bound to a WalletClient.`,\n\t\t);\n\t}\n\treturn account.signTypedData.bind(account);\n}\n\nfunction assertSignerMatches(account: Account, expectedFrom: Address, role: string): void {\n\tif (getAddress(account.address) !== getAddress(expectedFrom)) {\n\t\tthrow new Error(\n\t\t\t`EIP-3009 ${role} signature must come from \\`${role === \"cancel\" ? \"authorizer\" : \"from\"}\\`: account is ${account.address}, message says ${expectedFrom}.`,\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Signers\n// ---------------------------------------------------------------------------\n\n/**\n * Signs an EIP-3009 `TransferWithAuthorization` message.\n *\n * The signing account MUST equal `message.from` — EIP-3009 rejects signatures\n * from anyone else (the on-chain check is pure `ecrecover` against `from`).\n *\n * @example\n * ```ts\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * authorizationDeadlineFromNow,\n * generateAuthorizationNonce,\n * JPYC_EIP712_DOMAIN_HINT,\n * polygon,\n * signTransferWithAuthorization,\n * } from \"kawasekit\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const signed = await signTransferWithAuthorization(account, {\n * ...JPYC_EIP712_DOMAIN_HINT,\n * chainId: polygon.id,\n * verifyingContract: \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\",\n * }, {\n * from: account.address,\n * to: \"0xBeef...\",\n * value: 100n * 10n ** 18n,\n * validAfter: 0n,\n * validBefore: authorizationDeadlineFromNow(300),\n * nonce: generateAuthorizationNonce(),\n * });\n * // → submit (v, r, s) to token.transferWithAuthorization(...)\n * ```\n */\nexport async function signTransferWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: TransferWithAuthorizationMessage,\n): Promise<SignedAuthorization<TransferWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"transfer\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: transferWithAuthorizationTypes,\n\t\tprimaryType: \"TransferWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `ReceiveWithAuthorization` message.\n *\n * Differs from {@link signTransferWithAuthorization} in two ways:\n * 1. Uses the `ReceiveWithAuthorization` EIP-712 type.\n * 2. The contract additionally enforces `msg.sender == to` at submission\n * time, so only `to` (or a relayer impersonating `to` — impossible in\n * practice) can land the tx.\n */\nexport async function signReceiveWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: ReceiveWithAuthorizationMessage,\n): Promise<SignedAuthorization<ReceiveWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"receive\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: receiveWithAuthorizationTypes,\n\t\tprimaryType: \"ReceiveWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `CancelAuthorization` message.\n *\n * Cancelling consumes the nonce so a later `transferWithAuthorization` or\n * `receiveWithAuthorization` with the same nonce will revert.\n */\nexport async function signCancelAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: CancelAuthorizationMessage,\n): Promise<SignedAuthorization<CancelAuthorizationMessage>> {\n\tassertSignerMatches(account, message.authorizer, \"cancel\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: cancelAuthorizationTypes,\n\t\tprimaryType: \"CancelAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\nfunction splitAuthorization<TMessage>(\n\tsignature: Hex,\n\tdomain: Eip3009Domain,\n\tmessage: TMessage,\n): SignedAuthorization<TMessage> {\n\tconst parsed = parseSignature(signature);\n\t// viem's parseSignature returns yParity ∈ {0, 1} as well as v when present.\n\tconst v = parsed.v !== undefined ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;\n\treturn {\n\t\tsignature,\n\t\tv,\n\t\tr: parsed.r,\n\t\ts: parsed.s,\n\t\tdomain,\n\t\tmessage,\n\t};\n}\n","/**\n * The `local` PolicyGatedSigner adapter — `enforcement: \"advisory\"`.\n *\n * Wraps a viem {@link Account} + a {@link SpendingPolicy} + a pinned EIP-712\n * domain. `sign(intent)` evaluates the policy SDK-side and, on pass, produces a\n * real EIP-3009 authorization via {@link signTransferWithAuthorization}. It is\n * **advisory** because the wrapped key can still sign anything elsewhere — the\n * gate is only reached if the caller chooses to call *this* `sign()`. Use it for\n * dev, the A1 cross-language fallback, and any flow that is explicitly not\n * bounded/regulated; the type-gate (`requireNonBypassable`) keeps it out of\n * flows that require non-bypassable enforcement.\n *\n * @packageDocumentation\n */\n\nimport type { Account } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { SpendingPolicy, SpendState } from \"../policy/spending-policy\";\nimport { evaluateSpendingPolicy } from \"../policy/spending-policy\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { signTransferWithAuthorization } from \"../tokens/eip3009\";\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { PaymentIntent, PolicyGatedSigner, SignerDescription, SignResult } from \"./types\";\n\n/** Parameters for {@link createLocalPolicyGatedSigner}. */\nexport interface CreateLocalPolicyGatedSignerParams {\n\t/** EOA / LocalAccount that signs the EIP-3009 authorization. */\n\treadonly account: Account;\n\t/** The spending policy this signer enforces (SDK-side, advisory). */\n\treadonly policy: SpendingPolicy;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract`. */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Required literal acknowledgement that this signer is **advisory** (a\n\t * key-holder can bypass its policy). Omitting it is a compile error (TS) and\n\t * a construction-time throw (JS) — so constructing an advisory signer is a\n\t * conscious, greppable act. For bounded/regulated flows use a cryptographic\n\t * adapter instead.\n\t */\n\treadonly acknowledgeAdvisory: true;\n\t/**\n\t * Optional cumulative-spend view (read-only) the adapter evaluates\n\t * `cumulativeCap` against. `local` does not own an authoritative ledger; the\n\t * caller folds a successful spend back in (e.g. via `mergeSpendState`) before\n\t * the next call. Default: empty.\n\t */\n\treadonly spendState?: () => SpendState | Promise<SpendState>;\n}\n\n/**\n * Construct a `local` (advisory) PolicyGatedSigner.\n *\n * @example\n * ```ts\n * const signer = createLocalPolicyGatedSigner({\n * account,\n * policy: createSpendingPolicy({ session: { id, notAfter }, perToken: [{ token: JPYC, maxPerSign: 1_000n }], recipientAllowlist: \"any\" }),\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * acknowledgeAdvisory: true,\n * });\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createLocalPolicyGatedSigner(\n\tparams: CreateLocalPolicyGatedSignerParams,\n): PolicyGatedSigner<\"advisory\"> {\n\tif (params.acknowledgeAdvisory !== true) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"acknowledgeAdvisory\",\n\t\t\t\"a local signer is advisory (a key-holder can bypass its policy); pass `acknowledgeAdvisory: true` to construct one consciously, or use a cryptographic adapter for bounded/regulated flows\",\n\t\t);\n\t}\n\n\tconst { account, policy, spendState } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(account.address);\n\n\treturn {\n\t\tenforcement: \"advisory\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"from_mismatch\",\n\t\t\t\t\t\tdetail: `intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"token_not_allowed\",\n\t\t\t\t\t\tdetail: `intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst state: SpendState = (await spendState?.()) ?? { spentPerToken: [] };\n\t\t\tconst nowSeconds = BigInt(Math.floor(Date.now() / 1000));\n\t\t\tconst decision = evaluateSpendingPolicy(policy, intent, state, nowSeconds);\n\t\t\tif (!decision.ok) {\n\t\t\t\treturn { ok: false, rejection: decision.rejection };\n\t\t\t}\n\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\tresolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\t{\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { ok: true, signature: signed.signature, intent };\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"advisory\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: policy.session.id,\n\t\t\t\tnotAfter: policy.session.notAfter,\n\t\t\t\trevoked: policy.revoked,\n\t\t\t};\n\t\t},\n\t};\n}\n","/**\n * The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control\n * envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.\n *\n * This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):\n * a small, versioned envelope carries the decoded {@link PaymentIntent} (never a\n * digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque\n * DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The\n * shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**\n * (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,\n * `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame\n * the SDK builds round-trips through the backend's `serde_json`.\n *\n * `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it\n * reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected\n * authenticator's HMAC equals what the co-signer verifies (RFC §4.6:\n * `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).\n *\n * @packageDocumentation\n */\n\nimport type { Hex } from \"viem\";\nimport type { PaymentIntent } from \"./types\";\n\n/** The wire protocol version. A frame whose `wire_version` differs is rejected. */\nexport const WIRE_VERSION = 2 as const;\n\n/**\n * The inbound round-payload bound, in bytes — mirrors the backend's\n * `crypto-core/src/transport.rs` `MAX_FRAME_BYTES` (8 MiB) so the agent side\n * enforces the same pre-decode cap the backend does (RFC m6-3a §4.2/M3). The\n * adapter refuses an over-bound `round` payload **before** hex-decoding it into\n * the WASM boundary; the private transport should additionally cap raw\n * websocket messages (e.g. the `ws` client's `maxPayload`).\n */\nexport const MAX_FRAME_BYTES = 8 * 1024 * 1024;\n\n/**\n * The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`\n * addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any\n * library's native serde so a stdlib client reproduces it trivially; matches the\n * Rust `WireIntent` field names + encoding exactly.\n */\nexport interface WireIntent {\n\treadonly token: string;\n\treadonly chain_id: number;\n\treadonly from: string;\n\treadonly to: string;\n\treadonly value: string;\n\treadonly valid_after: string;\n\treadonly valid_before: string;\n\treadonly nonce: string;\n}\n\n/** Encode a decoded {@link PaymentIntent} for the wire. */\nexport function toWireIntent(intent: PaymentIntent): WireIntent {\n\treturn {\n\t\ttoken: intent.token.toLowerCase(),\n\t\tchain_id: intent.chainId,\n\t\tfrom: intent.from.toLowerCase(),\n\t\tto: intent.to.toLowerCase(),\n\t\tvalue: intent.value.toString(),\n\t\tvalid_after: intent.validAfter.toString(),\n\t\tvalid_before: intent.validBefore.toString(),\n\t\tnonce: intent.nonce.toLowerCase(),\n\t};\n}\n\n/**\n * The A3 request envelope the adapter generates per `sign()` and authenticates: a\n * per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element\n * (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).\n */\nexport interface CoSignRequestEnvelope {\n\treadonly ceremonyId: string;\n\treadonly ssid: string;\n\treadonly intent: PaymentIntent;\n\t/** Unix seconds; the backend checks it against a clock-skew window. */\n\treadonly freshnessTs: number;\n\t/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */\n\treadonly freshnessNonce: Hex;\n}\n\n/**\n * A versioned control frame: the only cross-language content of the wire. The\n * DKLs round bytes ride opaque inside `payload`; everything else is the small,\n * pinned envelope. Internally tagged by `kind` (matches the Rust serde).\n */\nexport type CoSignFrame = { readonly wire_version: typeof WIRE_VERSION } & (\n\t| {\n\t\t\treadonly kind: \"request\";\n\t\t\treadonly session_id: string;\n\t\t\treadonly ceremony_id: string;\n\t\t\treadonly ssid: string;\n\t\t\treadonly intent: WireIntent;\n\t\t\treadonly freshness_ts: number;\n\t\t\treadonly freshness_nonce: Hex;\n\t\t\t/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */\n\t\t\treadonly auth_tag: Hex;\n\t }\n\t| { readonly kind: \"round\"; readonly payload: Hex }\n\t| { readonly kind: \"result\"; readonly r: Hex; readonly s: Hex; readonly v: number }\n\t| { readonly kind: \"rejection\"; readonly reason: string; readonly detail: string }\n\t| { readonly kind: \"error\"; readonly message: string }\n);\n\n/**\n * The A3 canonical encoding of a request — a byte-exact mirror of the backend's\n * `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,\n * one `key=value\\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖\n * canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,\n * decimal integers, trailing newline). The injected authenticator HMACs these\n * bytes; because the encoding is shared, the tag equals the co-signer's.\n */\nexport function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array {\n\tconst i = env.intent;\n\tconst lines = [\n\t\t\"kawasekit-mpc-2p/cosign-request/v3\",\n\t\t\"wireVersion=2\",\n\t\t`ceremonyId=${env.ceremonyId}`,\n\t\t`ssid=${env.ssid}`,\n\t\t`token=${i.token.toLowerCase()}`,\n\t\t`chainId=${i.chainId}`,\n\t\t`from=${i.from.toLowerCase()}`,\n\t\t`to=${i.to.toLowerCase()}`,\n\t\t`value=${i.value}`,\n\t\t`validAfter=${i.validAfter}`,\n\t\t`validBefore=${i.validBefore}`,\n\t\t`nonce=${i.nonce.toLowerCase()}`,\n\t\t`freshnessTs=${env.freshnessTs}`,\n\t\t`freshnessNonce=${env.freshnessNonce.toLowerCase()}`,\n\t];\n\treturn new TextEncoder().encode(lines.map((l) => `${l}\\n`).join(\"\"));\n}\n","/**\n * The `mpc-2p` PolicyGatedSigner adapter — `enforcement: \"cryptographic\"`.\n *\n * A 2-of-2 MPC co-signer: the agent holds ONE DKLs share, the owner backend holds\n * the other + the authoritative policy gate. No valid signature exists without a\n * **policy-passing co-sign**, so — unlike `local` — a single key-holder cannot\n * bypass the policy. That is what earns the non-bypassable `\"cryptographic\"` label\n * and lets the M6-0 type-gate (`requireNonBypassable`) reject an advisory signer at\n * compile time in bounded flows.\n *\n * **Open-core / thin adapter.** This module is pure orchestration over injected\n * interfaces — it ships in the public SDK with **no crypto, no socket, no key**:\n *\n * - {@link Mpc2pCoSignAgent} — the WASM DKLs share (the private package's compiled\n * `crypto-core`); drives the agent's half of the ceremony round-by-round.\n * - {@link CoSignTransport} — the authenticated, encrypted (wss/mTLS) frame channel\n * to the owner backend (the private package's transport).\n * - {@link CoSignRequestAuthenticator} — the A3 HMAC (the pre-shared key never\n * enters this module).\n *\n * The adapter owns the protocol: it pins the EIP-712 domain, **re-derives the\n * digest from the intent (A4)** via the shared `transferWithAuthorizationTypes`\n * source-of-truth, computes the A3 canonical bytes, frames the versioned\n * {@link CoSignFrame} envelope, pumps the ceremony, and maps the terminal frame to\n * a {@link SignResult}. Crucially it has **no local-signing path**: any\n * transport/availability failure throws {@link CoSignUnavailableError}, never an\n * `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback\n * guarantee, RFC m6-3a constraint 3 / W8).\n *\n * **Wire hardening (RFC §4.7/§4.8, Track C):** a bounded **transient-only retry**\n * replays the byte-identical intent (nonce included — idempotency-by-nonce is the\n * safety net) under a fresh A3 envelope and accepts the backend's **roundless\n * idempotent-replay result** via an ecrecover/low-S self-check; the **ceremony\n * deadline always fires before `validBefore`** (minus a clock-skew budget, W11),\n * and inbound round payloads are **bounded** before the WASM boundary (M3). Tuning\n * via {@link Mpc2pWireOptions}.\n *\n * @packageDocumentation\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { getAddress, hashTypedData, recoverAddress, serializeSignature, toHex } from \"viem\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { transferWithAuthorizationTypes } from \"../tokens/eip3009\";\nimport { CoSignUnavailableError, PolicyGatedSignerConfigError } from \"./errors\";\nimport type { CoSignFrame, CoSignRequestEnvelope } from \"./mpc-2p-wire\";\nimport { canonicalRequestBytes, MAX_FRAME_BYTES, toWireIntent, WIRE_VERSION } from \"./mpc-2p-wire\";\nimport type {\n\tPaymentIntent,\n\tPolicyGatedSigner,\n\tPolicyRejection,\n\tSignerDescription,\n\tSignResult,\n} from \"./types\";\n\n/** The agent's half of the 2-of-2 ceremony (the injected WASM DKLs share). */\nexport interface Mpc2pCoSignAgent {\n\t/** The group 2-of-2 EOA this share controls — must equal the signer's `from`. */\n\tgroupEoa(): Address;\n\t/** Begin signing the 32-byte EIP-712 `digest`; returns the first outbound round (hex). */\n\tstart(digest: Hex): Hex;\n\t/** Feed one inbound round (hex); returns the next outbound round, or the final signature. */\n\tstep(incoming: Hex): Mpc2pStepOutcome;\n}\n\n/** The result of one {@link Mpc2pCoSignAgent.step}. */\nexport type Mpc2pStepOutcome =\n\t| { readonly outbound: Hex }\n\t| { readonly signature: { readonly r: Hex; readonly s: Hex; readonly v: number } };\n\n/** One authenticated, encrypted ceremony connection to the owner backend. */\nexport interface CoSignConnection {\n\t/** Send one control frame. */\n\tsend(frame: CoSignFrame): Promise<void>;\n\t/** Receive the next control frame (resolves per round). */\n\trecv(): Promise<CoSignFrame>;\n\t/** Release the connection (best-effort; errors here are ignored). */\n\tclose(): void | Promise<void>;\n}\n\n/** Opens a wss/mTLS {@link CoSignConnection} for a single co-sign ceremony. */\nexport interface CoSignTransport {\n\tconnect(): Promise<CoSignConnection>;\n}\n\n/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */\nexport interface CoSignRequestAuthenticator {\n\t/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */\n\ttag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;\n}\n\n/**\n * Wire liveness / retry tuning (RFC m6-3a §4.7 + §4.8). Every field is optional\n * with a safe default. The invariants these enforce:\n *\n * - **Retry (4b/H2):** only the **transient transport class** is retried (connect\n * failed / connection dropped), replaying the **byte-identical intent** — nonce\n * included, so the backend's idempotency-by-nonce is the safety net — under a\n * fresh A3 envelope (the freshness guard rejects a replayed envelope by design).\n * A delivered rejection, a ban/identifiable-abort, a protocol anomaly, or a\n * timeout is never retried.\n * - **Liveness (4c/W11/M1+M3):** the ceremony deadline always fires **before**\n * `intent.validBefore − clockSkewBudgetSecs` (a co-signature must never be born\n * expired), and a `sign()` whose remaining window is under\n * `minWindowSecs + clockSkewBudgetSecs` is refused up front.\n * - **Inbound bound (4c/M3):** a `round` payload over `maxFrameBytes` is refused\n * before it reaches the WASM boundary (mirrors the backend's bound).\n */\nexport interface Mpc2pWireOptions {\n\t/** Max ceremony attempts for transient transport failures (default 2 = one retry). */\n\treadonly maxAttempts?: number;\n\t/** Overall per-`sign()` budget in ms, across ALL attempts (default 30_000). */\n\treadonly ceremonyTimeoutMs?: number;\n\t/** Minimum remaining validity window required at `sign()` start, in seconds (default 30). */\n\treadonly minWindowSecs?: number;\n\t/** Max tolerated agent-host clock skew, in seconds (default 30). */\n\treadonly clockSkewBudgetSecs?: number;\n\t/** Inbound round-payload bound in bytes (default {@link MAX_FRAME_BYTES} = 8 MiB). */\n\treadonly maxFrameBytes?: number;\n}\n\n/** Parameters for {@link createMpc2pPolicyGatedSigner}. */\nexport interface Mpc2pSignerParams {\n\t/** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */\n\treadonly from: Address;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract` (A4). */\n\treadonly asset: X402AssetParam;\n\t/** The bound policy session, for `describe()` (the backend holds the authoritative policy). */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\t/** The injected WASM DKLs share (private package). */\n\treadonly agent: Mpc2pCoSignAgent;\n\t/** The injected wss/mTLS frame channel (private package). */\n\treadonly transport: CoSignTransport;\n\t/** The injected A3 authenticator (the pre-shared key never enters the SDK). */\n\treadonly authenticator: CoSignRequestAuthenticator;\n\t/** Wire liveness / retry tuning (optional; safe defaults — {@link Mpc2pWireOptions}). */\n\treadonly wire?: Mpc2pWireOptions;\n}\n\n/**\n * The backend `rejection` reasons that are genuine **policy denials** (the owner\n * decided \"no\" — audit-meaningful → `{ ok: false, rejection }`). Any other reason\n * on a rejection frame is treated as \"the owner did not cleanly decide\" and throws\n * {@link CoSignUnavailableError} (no-silent-fallback; never a misclassified denial).\n */\nconst POLICY_REASONS: ReadonlySet<PolicyRejection[\"reason\"]> = new Set([\n\t\"revoked\",\n\t\"expired\",\n\t\"token_not_allowed\",\n\t\"recipient_not_allowed\",\n\t\"amount_exceeds_per_sign\",\n\t\"amount_exceeds_cumulative\",\n\t\"intent_digest_mismatch\",\n\t\"unauthenticated\",\n\t\"from_mismatch\",\n\t\"nonce_reuse_conflict\",\n]);\n\nfunction rejection(reason: PolicyRejection[\"reason\"], detail: string): SignResult {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +\n * transport + authenticator.\n *\n * @example\n * ```ts\n * // The agent, transport and authenticator come from the private `kawasekit-mpc-2p`\n * // package (the WASM share, the wss/mTLS client, the HMAC key) — never bundled here.\n * const signer = createMpc2pPolicyGatedSigner({\n * from: groupEoa,\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * session: { id: \"sess-1\", notAfter: 2_000_000_000n },\n * agent, transport, authenticator,\n * });\n * requireNonBypassable(signer); // ✓ \"cryptographic\" — passes the type-gate\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createMpc2pPolicyGatedSigner(\n\tparams: Mpc2pSignerParams,\n): PolicyGatedSigner<\"cryptographic\"> {\n\tconst { agent, transport, authenticator, session } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(params.from);\n\tconst wire = params.wire ?? {};\n\tconst maxAttempts = Math.max(1, wire.maxAttempts ?? 2);\n\tconst ceremonyTimeoutMs = wire.ceremonyTimeoutMs ?? 30_000;\n\tconst minWindowSecs = wire.minWindowSecs ?? 30;\n\tconst clockSkewBudgetSecs = wire.clockSkewBudgetSecs ?? 30;\n\tconst maxFrameBytes = wire.maxFrameBytes ?? MAX_FRAME_BYTES;\n\n\t// The injected share MUST control the declared group EOA, or every signature\n\t// would recover to the wrong address.\n\tconst agentEoa = getAddress(agent.groupEoa());\n\tif (agentEoa !== from) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"from\",\n\t\t\t`the agent share controls ${agentEoa} but params.from is ${from}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tenforcement: \"cryptographic\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\t// Adapter-local pre-checks (cheap; no wire needed). Same shape as `local`.\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"from_mismatch\",\n\t\t\t\t\t`intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"token_not_allowed\",\n\t\t\t\t\t`intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// A4: re-derive the EIP-712 digest from the intent + the pinned domain (the\n\t\t\t// SDK's exported types are the cross-language source of truth). The agent and\n\t\t\t// the backend each sign THIS digest; the SoT keeps them byte-identical.\n\t\t\tconst digest = hashTypedData({\n\t\t\t\tdomain: resolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\ttypes: transferWithAuthorizationTypes,\n\t\t\t\tprimaryType: \"TransferWithAuthorization\",\n\t\t\t\tmessage: {\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// 4c (W11/M1+M3) — the ceremony-liveness minimum-window invariant: the rounds +\n\t\t\t// the bounded retry budget must all complete BEFORE validBefore, and validity is\n\t\t\t// judged against chain time, so the agent host's clock-skew budget is part of the\n\t\t\t// bar. A window already too small risks a born-expired signature (wasted\n\t\t\t// facilitator gas + retry/cap pressure); the owner has not decided anything, so\n\t\t\t// this throws (never a rejection).\n\t\t\tconst validBeforeSecs = Number(intent.validBefore);\n\t\t\tconst nowSecs = Math.floor(Date.now() / 1000);\n\t\t\tif (validBeforeSecs - nowSecs < minWindowSecs + clockSkewBudgetSecs) {\n\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t`intent.validBefore (${validBeforeSecs}) leaves under the minimum ceremony window (${minWindowSecs}s + ${clockSkewBudgetSecs}s clock-skew budget) — refusing a co-sign that risks being born expired (W11)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// One deadline for the whole sign() — every attempt included — capped so the\n\t\t\t// ceremony timeout always fires before validBefore (minus the clock-skew budget).\n\t\t\tconst deadlineMs = Math.min(\n\t\t\t\tDate.now() + ceremonyTimeoutMs,\n\t\t\t\t(validBeforeSecs - clockSkewBudgetSecs) * 1000,\n\t\t\t);\n\n\t\t\t// 4b (RFC §4.7/H2) — bounded transient-only retry. Every attempt re-presents the\n\t\t\t// *byte-identical* `intent` (nonce included — the backend's idempotency-by-nonce\n\t\t\t// + atomic SpendState are the safety net) under a FRESH A3 envelope: the\n\t\t\t// ceremonyId/ssid/freshness are per-attempt BY DESIGN (the backend's freshness\n\t\t\t// guard rejects a replayed envelope, while idempotency keys on the unchanged\n\t\t\t// EIP-3009 nonce). Only the transient transport class retries — never a\n\t\t\t// delivered rejection, never a ban/identifiable-abort, never a timeout.\n\t\t\tlet lastTransient: CoSignUnavailableError | undefined;\n\t\t\tfor (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n\t\t\t\tif (Date.now() >= deadlineMs) break;\n\t\t\t\t// A3 (v2): a fresh per-ceremony id + ssid + freshness (a timestamp + a\n\t\t\t\t// per-request nonce, distinct from the EIP-3009 nonce), authenticated over the\n\t\t\t\t// canonical bytes (the shared SoT; the HMAC key lives inside the injected\n\t\t\t\t// authenticator). Web Crypto is isomorphic (Node 19+ / browsers).\n\t\t\t\tconst env: CoSignRequestEnvelope = {\n\t\t\t\t\tceremonyId: globalThis.crypto.randomUUID(),\n\t\t\t\t\tssid: globalThis.crypto.randomUUID(),\n\t\t\t\t\tintent,\n\t\t\t\t\tfreshnessTs: Math.floor(Date.now() / 1000),\n\t\t\t\t\tfreshnessNonce: toHex(globalThis.crypto.getRandomValues(new Uint8Array(16))),\n\t\t\t\t};\n\t\t\t\tconst authTag = await authenticator.tag(canonicalRequestBytes(env));\n\t\t\t\ttry {\n\t\t\t\t\tconst conn = await openConnection(transport);\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await runCeremony({\n\t\t\t\t\t\t\tconn,\n\t\t\t\t\t\t\tagent,\n\t\t\t\t\t\t\tsessionId: session.id,\n\t\t\t\t\t\t\tenv,\n\t\t\t\t\t\t\tdigest,\n\t\t\t\t\t\t\tauthTag,\n\t\t\t\t\t\t\tfrom,\n\t\t\t\t\t\t\tdeadlineMs,\n\t\t\t\t\t\t\tmaxFrameBytes,\n\t\t\t\t\t\t});\n\t\t\t\t\t} finally {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait conn.close();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// best-effort cleanup; a close error must not mask the result/throw.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof CoSignUnavailableError && error.transient && attempt < maxAttempts) {\n\t\t\t\t\t\tlastTransient = error;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow (\n\t\t\t\tlastTransient ??\n\t\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\t\"co-sign ceremony budget exhausted before validBefore (W11) — no attempt could start\",\n\t\t\t\t)\n\t\t\t);\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"cryptographic\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: session.id,\n\t\t\t\tnotAfter: session.notAfter,\n\t\t\t\t// The backend owns authoritative revocation (a revoked session → a\n\t\t\t\t// rejection at sign time); this metadata field is best-effort.\n\t\t\t\trevoked: false,\n\t\t\t};\n\t\t},\n\t};\n}\n\nasync function openConnection(transport: CoSignTransport): Promise<CoSignConnection> {\n\ttry {\n\t\treturn await transport.connect();\n\t} catch (cause) {\n\t\t// Connect failure = the transient transport class (the one retried, §4.7).\n\t\tthrow new CoSignUnavailableError(\"co-signer connection failed\", { cause, transient: true });\n\t}\n}\n\n/** Everything one ceremony attempt needs (one connection, one A3 envelope). */\ninterface CeremonyContext {\n\treadonly conn: CoSignConnection;\n\treadonly agent: Mpc2pCoSignAgent;\n\treadonly sessionId: string;\n\treadonly env: CoSignRequestEnvelope;\n\treadonly digest: Hex;\n\treadonly authTag: Hex;\n\t/** The group EOA every result must recover to (the §4.4 self-check). */\n\treadonly from: Address;\n\t/** Absolute epoch-ms the ceremony must finish by (fires before validBefore — W11). */\n\treadonly deadlineMs: number;\n\t/** Inbound round-payload bound in bytes (mirrors the backend's MAX_FRAME_BYTES). */\n\treadonly maxFrameBytes: number;\n}\n\n/**\n * Drive one full ceremony attempt over `ctx.conn`: send the authenticated request +\n * the agent's first round, then pump rounds until a terminal frame. Returns a\n * {@link SignResult} (success or a policy denial) or throws\n * {@link CoSignUnavailableError}. There is no path that returns `{ ok: true }`\n * without a backend `result` frame that passes the ecrecover/low-S self-check.\n */\nasync function runCeremony(ctx: CeremonyContext): Promise<SignResult> {\n\tconst { conn, agent, env, digest, from } = ctx;\n\tconst send = async (frame: CoSignFrame): Promise<void> => {\n\t\ttry {\n\t\t\tawait withDeadline(conn.send(frame), ctx.deadlineMs);\n\t\t} catch (cause) {\n\t\t\tif (cause instanceof CoSignUnavailableError) throw cause; // the deadline (never retried)\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped while sending\", {\n\t\t\t\tcause,\n\t\t\t\ttransient: true,\n\t\t\t});\n\t\t}\n\t};\n\tconst recv = async (): Promise<CoSignFrame> => {\n\t\tlet frame: CoSignFrame;\n\t\ttry {\n\t\t\tframe = await withDeadline(conn.recv(), ctx.deadlineMs);\n\t\t} catch (cause) {\n\t\t\tif (cause instanceof CoSignUnavailableError) throw cause; // the deadline (never retried)\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped mid-ceremony\", {\n\t\t\t\tcause,\n\t\t\t\ttransient: true,\n\t\t\t});\n\t\t}\n\t\tif (frame.wire_version !== WIRE_VERSION) {\n\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t`co-signer spoke wire_version ${frame.wire_version}, expected ${WIRE_VERSION}`,\n\t\t\t);\n\t\t}\n\t\treturn frame;\n\t};\n\n\tawait send({\n\t\twire_version: WIRE_VERSION,\n\t\tkind: \"request\",\n\t\tsession_id: ctx.sessionId,\n\t\tceremony_id: env.ceremonyId,\n\t\tssid: env.ssid,\n\t\tintent: toWireIntent(env.intent),\n\t\tfreshness_ts: env.freshnessTs,\n\t\tfreshness_nonce: env.freshnessNonce,\n\t\tauth_tag: ctx.authTag,\n\t});\n\n\tlet first: Hex;\n\ttry {\n\t\tfirst = agent.start(digest);\n\t} catch (cause) {\n\t\t// A protocol-level failure, not a transport loss — restart-not-resume classifies\n\t\t// only the transient transport class as retry-safe (§4.7), so this never retries.\n\t\tthrow new CoSignUnavailableError(\"the agent failed to start the ceremony\", { cause });\n\t}\n\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: first });\n\n\tlet agentSig: { r: Hex; s: Hex; v: number } | null = null;\n\tfor (;;) {\n\t\tconst frame = await recv();\n\t\tswitch (frame.kind) {\n\t\t\tcase \"round\": {\n\t\t\t\t// 4c (M3) — the agent-side inbound bound, mirroring the backend's\n\t\t\t\t// MAX_FRAME_BYTES: an over-bound payload is refused BEFORE hex-decode and\n\t\t\t\t// before it crosses the WASM boundary.\n\t\t\t\tconst payloadBytes = (frame.payload.length - 2) / 2;\n\t\t\t\tif (payloadBytes > ctx.maxFrameBytes) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t\t`co-signer sent a ${payloadBytes}-byte round frame (bound ${ctx.maxFrameBytes}) — refused pre-decode`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet step: Mpc2pStepOutcome;\n\t\t\t\ttry {\n\t\t\t\t\tstep = agent.step(frame.payload);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\t// Protocol abort (possibly a cheating peer) — never retried (§4.7).\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the agent rejected a round frame\", { cause });\n\t\t\t\t}\n\t\t\t\tif (\"outbound\" in step) {\n\t\t\t\t\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: step.outbound });\n\t\t\t\t} else {\n\t\t\t\t\tagentSig = step.signature;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"result\": {\n\t\t\t\tconst signature = assembleSignature({ r: frame.r, s: frame.s, v: frame.v });\n\t\t\t\tif (agentSig === null) {\n\t\t\t\t\t// A ROUNDLESS result = the backend's idempotent replay (§4.7): a retry hit\n\t\t\t\t\t// a nonce whose ceremony already committed, and the CACHED signature came\n\t\t\t\t\t// back with zero rounds. There is no agent-derived signature to cross-check,\n\t\t\t\t\t// so the self-check is recovery: low-S + ecrecover(digest) == from (§4.4).\n\t\t\t\t\tawait verifyRecovers(digest, signature, frame.s, from, \"idempotent-replay\");\n\t\t\t\t\treturn { ok: true, signature, intent: env.intent };\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tframe.r.toLowerCase() !== agentSig.r.toLowerCase() ||\n\t\t\t\t\tframe.s.toLowerCase() !== agentSig.s.toLowerCase() ||\n\t\t\t\t\tframe.v !== agentSig.v\n\t\t\t\t) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the backend and agent derived different signatures\");\n\t\t\t\t}\n\t\t\t\t// The §4.4 ecrecover/low-S self-check: agent/backend agreement alone does not\n\t\t\t\t// prove the signature recovers to the group EOA over OUR digest — recovery does.\n\t\t\t\tawait verifyRecovers(digest, signature, frame.s, from, \"co-signed\");\n\t\t\t\treturn { ok: true, signature, intent: env.intent };\n\t\t\t}\n\t\t\tcase \"rejection\": {\n\t\t\t\t// A genuine policy denial → typed rejection. A non-policy \"rejection\"\n\t\t\t\t// (transient/internal/ban) is \"the owner did not decide\" → no-fallback throw,\n\t\t\t\t// and it is NOT the transient transport class (never retried — a ban or an\n\t\t\t\t// in-flight duplicate must surface, not silently re-spin).\n\t\t\t\tif (POLICY_REASONS.has(frame.reason as PolicyRejection[\"reason\"])) {\n\t\t\t\t\t// reason membership verified against POLICY_REASONS above.\n\t\t\t\t\treturn rejection(frame.reason as PolicyRejection[\"reason\"], frame.detail);\n\t\t\t\t}\n\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t`co-signer returned a non-policy rejection (${frame.reason}): ${frame.detail}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"error\": {\n\t\t\t\tthrow new CoSignUnavailableError(`co-signer error: ${frame.message}`);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t// Unknown frame kind — never a silent success.\n\t\t\t\tthrow new CoSignUnavailableError(\"co-signer sent an unexpected frame\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Race `promise` against the ceremony deadline (W11: the timeout must fire before\n * `validBefore`). A deadline strike throws a NON-transient\n * {@link CoSignUnavailableError} — the retry budget is spent, never re-spun.\n */\nfunction withDeadline<T>(promise: Promise<T>, deadlineMs: number): Promise<T> {\n\tconst remaining = deadlineMs - Date.now();\n\tif (remaining <= 0) {\n\t\treturn Promise.reject(\n\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\"co-sign ceremony timed out (the deadline fires before validBefore — W11)\",\n\t\t\t),\n\t\t);\n\t}\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew CoSignUnavailableError(\n\t\t\t\t\t\"co-sign ceremony timed out (the deadline fires before validBefore — W11)\",\n\t\t\t\t),\n\t\t\t);\n\t\t}, remaining);\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(cause) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(cause);\n\t\t\t},\n\t\t);\n\t});\n}\n\n/** secp256k1 n/2 — the EIP-2 low-S bound. */\nconst SECP256K1_HALF_N = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0n;\n\n/**\n * The RFC §4.4 result self-check: the signature is low-S (EIP-2) and recovers to\n * the group EOA over the adapter's OWN re-derived digest — the exact check the\n * token contract's `ecrecover` will repeat on-chain.\n */\nasync function verifyRecovers(\n\tdigest: Hex,\n\tsignature: Hex,\n\ts: Hex,\n\tfrom: Address,\n\twhat: string,\n): Promise<void> {\n\tif (BigInt(s) > SECP256K1_HALF_N) {\n\t\tthrow new CoSignUnavailableError(`the ${what} signature is not low-S (EIP-2)`);\n\t}\n\tlet recovered: Address;\n\ttry {\n\t\trecovered = await recoverAddress({ hash: digest, signature });\n\t} catch (cause) {\n\t\tthrow new CoSignUnavailableError(`the ${what} signature failed to recover`, { cause });\n\t}\n\tif (getAddress(recovered) !== from) {\n\t\tthrow new CoSignUnavailableError(\n\t\t\t`the ${what} signature recovers to ${getAddress(recovered)}, not the group EOA ${from}`,\n\t\t);\n\t}\n}\n\n/** Assemble a 65-byte EIP-3009 signature from the agent's `{ r, s, v }` (v = recovery_id + 27). */\nfunction assembleSignature(sig: { r: Hex; s: Hex; v: number }): Hex {\n\tconst yParity = sig.v - 27;\n\tif (yParity !== 0 && yParity !== 1) {\n\t\tthrow new CoSignUnavailableError(`malformed recovery id v=${sig.v} (expected 27 or 28)`);\n\t}\n\treturn serializeSignature({ r: sig.r, s: sig.s, yParity });\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { a as PolicyGatedSigner, N as NonBypassableEnforcement, P as PaymentIntent } from '../types-BLJU67HZ.cjs';
2
2
  export { E as EnforcementLevel, b as PolicyRejection, S as SignResult, c as SignerDescription } from '../types-BLJU67HZ.cjs';
3
3
  import { Account, Hex, Address } from 'viem';
4
- import { a as SpendingPolicy, S as SpendState } from '../spending-policy-CGIaBpg-.cjs';
4
+ import { a as SpendingPolicy, S as SpendState } from '../spending-policy-CwXcTFD_.cjs';
5
5
  import { X as X402AssetParam } from '../asset-domain-4Ioxqn28.cjs';
6
6
 
7
7
  /**