{"version":3,"sources":["../../src/shared/erc7702.ts","../../src/auth-capture/types.ts"],"sourcesContent":["/**\n * Detection utilities for the ERC-7702 delegation designation (`0xef0100 + 20-byte address`).\n *\n * NOTE: These helpers are diagnostic only. The signature-verification path does\n * not branch on 7702 detection — it routes by `code.length` (matching on-chain\n * SignatureChecker) and the delegate decides via `isValidSignature`. See\n * {@link ./verifySignature.ts} for the verification primitive.\n *\n * Use these helpers for telemetry, logging, or surfacing wallet types in UIs.\n */\n\nconst ERC7702_PREFIX = \"0xef0100\";\nconst ERC7702_BYTECODE_LENGTH = 48; // \"0x\" + 6 hex chars (prefix) + 40 hex chars (address)\n\n/**\n * Returns `true` if `bytecode` is a valid ERC-7702 delegation designation.\n *\n * The check is case-insensitive — `eth_getCode` casing is not normalized at the\n * JSON-RPC layer, so callers using ethers, custom signers, or post-processed\n * hex can pass uppercase variants.\n *\n * @param bytecode - Raw hex bytecode returned by `eth_getCode`.\n * @returns `true` if the bytecode is an ERC-7702 delegation designation.\n */\nexport function isERC7702Delegation(bytecode: `0x${string}` | undefined | null): boolean {\n  if (!bytecode || bytecode === \"0x\") return false;\n  if (bytecode.length !== ERC7702_BYTECODE_LENGTH) return false;\n  return bytecode.toLowerCase().startsWith(ERC7702_PREFIX);\n}\n\n/**\n * Extracts the 20-byte delegate address from a 7702 delegation designation.\n * Returns the address in **lowercase** hex with a `0x` prefix.\n * The Go equivalent ({@link GetERC7702DelegateAddress}) returns a checksummed EIP-55 address.\n * The Python equivalent returns lowercase hex. Normalise with `getAddress()` when comparing\n * cross-SDK outputs or storing in a case-sensitive index.\n * Returns `null` for non-7702 bytecode.\n *\n * @param bytecode - Raw hex bytecode returned by `eth_getCode`.\n * @returns The lowercase `0x`-prefixed delegate address, or `null` if `bytecode` is not a 7702 designation.\n */\nexport function getERC7702DelegateAddress(\n  bytecode: `0x${string}` | undefined | null,\n): `0x${string}` | null {\n  if (!isERC7702Delegation(bytecode)) return null;\n  return (\"0x\" + bytecode!.slice(8).toLowerCase()) as `0x${string}`;\n}\n","/**\n * auth-capture wire-format types.\n *\n * Spec-level field names (captureAuthorizer, captureDeadline, refundDeadline,\n * feeRecipient) live here at the extra/wire layer. The on-chain PaymentInfo\n * struct keeps the canonical Solidity field names (operator, authorizationExpiry,\n * refundExpiry, feeReceiver) so the EIP-712 typehash stays byte-identical with\n * the AuthCaptureEscrow contract.\n *\n * Salt is NOT in extra. It is generated client-side per signing call and rides\n * on the payload alongside the signature.\n */\n\nimport type { AssetTransferMethod } from \"../types\";\n\n// AuthCaptureExtra — fields in PaymentRequirements.extra.\n//\n// Fee-policy fields (minFeeBps, maxFeeBps, feeRecipient) are all required.\n// No implicit defaults: a merchant who wants no minimum fee writes\n// `minFeeBps: 0` explicitly. This forces fee policy to be a conscious choice\n// on the wire and avoids \"did they mean 0 or did they forget?\" ambiguity.\nexport interface AuthCaptureExtra {\n  // Required\n  // The only address allowed to call authorize/capture/void/refund/charge on\n  // AuthCaptureEscrow (each of those is gated by onlySender(paymentInfo.operator))\n  // — i.e., it must be msg.sender of the \"Authorize\" call. In x402's\n  // facilitator-submits flow that means either the facilitator's EOA, or any\n  // smart contract that ultimately calls escrow (arbiter with dispute logic,\n  // multisig, etc.). Independent of assetTransferMethod — applies to both\n  // EIP-3009 and Permit2.\n  captureAuthorizer: `0x${string}`; // formerly `operator` in commerce-payments\n  captureDeadline: number; // absolute Unix seconds; capture must occur before this\n  refundDeadline: number; // absolute Unix seconds; refunds allowed until this\n  feeRecipient: `0x${string}`; // address that receives the fee portion (renamed from feeReceiver)\n  minFeeBps: number; // floor on the captureAuthorizer's fee; 0 = no minimum\n  maxFeeBps: number; // cap on the captureAuthorizer's fee\n  name: string; // EIP-712 token-domain name (e.g., \"USDC\")\n  version: string; // EIP-712 token-domain version (e.g., \"2\")\n  // Optional\n  autoCapture?: boolean; // default: false. true → facilitator calls charge(), false → authorize()\n  assetTransferMethod?: AssetTransferMethod; // default: 'eip3009'\n}\n\n/**\n * Type guard for AuthCaptureExtra. Checks the structural shape an auth-capture\n * scheme requires inside `PaymentRequirements.extra`: every spec-mandated\n * required field present with the right primitive type.\n *\n * @param value - Candidate object from `requirements.extra`.\n * @returns True if `value` has every required AuthCaptureExtra field.\n */\nexport function isAuthCaptureExtra(value: unknown): value is AuthCaptureExtra {\n  if (typeof value !== \"object\" || value === null) return false;\n  const v = value as Record<string, unknown>;\n  return (\n    typeof v.captureAuthorizer === \"string\" &&\n    typeof v.captureDeadline === \"number\" &&\n    typeof v.refundDeadline === \"number\" &&\n    typeof v.feeRecipient === \"string\" &&\n    typeof v.minFeeBps === \"number\" &&\n    typeof v.maxFeeBps === \"number\" &&\n    typeof v.name === \"string\" &&\n    typeof v.version === \"string\"\n  );\n}\n\n// EIP-3009 payload — ReceiveWithAuthorization to the canonical EIP-3009 token collector.\nexport interface Eip3009Payload {\n  authorization: {\n    from: `0x${string}`;\n    to: `0x${string}`; // EIP3009_TOKEN_COLLECTOR_ADDRESS\n    value: string;\n    validAfter: string;\n    validBefore: string; // = preApprovalExpiry\n    nonce: `0x${string}`; // = payer-agnostic PaymentInfo hash\n  };\n  signature: `0x${string}`;\n  salt: `0x${string}`; // bytes32, fresh per request, used to reconstruct PaymentInfo\n}\n\n/**\n * Type guard for an EIP-3009-shaped auth-capture payload. Checks for an\n * `authorization` object plus the required `signature` and `salt` fields;\n * field-level validation happens later in `verify()`.\n *\n * @param value - Candidate payment payload from the wire.\n * @returns True if `value` has the EIP-3009 envelope shape.\n */\nexport function isEip3009Payload(value: unknown): value is Eip3009Payload {\n  if (typeof value !== \"object\" || value === null) return false;\n  const v = value as Record<string, unknown>;\n  return (\n    \"authorization\" in v &&\n    typeof v.authorization === \"object\" &&\n    v.authorization !== null &&\n    typeof v.signature === \"string\" &&\n    typeof v.salt === \"string\"\n  );\n}\n\n// Permit2 payload — PermitTransferFrom to the canonical Permit2 token collector.\nexport interface Permit2Payload {\n  permit2Authorization: {\n    from: `0x${string}`;\n    permitted: {\n      token: `0x${string}`;\n      amount: string;\n    };\n    spender: `0x${string}`; // PERMIT2_TOKEN_COLLECTOR_ADDRESS\n    nonce: string; // uint256 string, = uint256(payer-agnostic PaymentInfo hash)\n    deadline: string; // = preApprovalExpiry\n  };\n  signature: `0x${string}`;\n  salt: `0x${string}`; // bytes32, fresh per request, used to reconstruct PaymentInfo\n}\n\n/**\n * Type guard for a Permit2-shaped auth-capture payload. Checks for the\n * `permit2Authorization` envelope (with `from`, `spender`, `nonce`,\n * `deadline`, `permitted`) plus the required `signature` and `salt` fields.\n *\n * @param value - Candidate payment payload from the wire.\n * @returns True if `value` has the Permit2 envelope shape.\n */\nexport function isPermit2Payload(value: unknown): value is Permit2Payload {\n  if (typeof value !== \"object\" || value === null) return false;\n  const v = value as Record<string, unknown>;\n  if (typeof v.signature !== \"string\" || typeof v.salt !== \"string\") return false;\n  if (typeof v.permit2Authorization !== \"object\" || v.permit2Authorization === null) return false;\n  const a = v.permit2Authorization as Record<string, unknown>;\n  return (\n    typeof a.from === \"string\" &&\n    typeof a.spender === \"string\" &&\n    typeof a.nonce === \"string\" &&\n    typeof a.deadline === \"string\" &&\n    typeof a.permitted === \"object\" &&\n    a.permitted !== null\n  );\n}\n\n// Discriminated union of all auth-capture payload shapes.\nexport type AuthCapturePayload = Eip3009Payload | Permit2Payload;\n\n/**\n * Type guard for any auth-capture payload. Returns true if `value` matches\n * either the EIP-3009 envelope or the Permit2 envelope.\n *\n * @param value - Candidate payment payload from the wire.\n * @returns True if `value` is a valid auth-capture envelope of either shape.\n */\nexport function isAuthCapturePayload(value: unknown): value is AuthCapturePayload {\n  return isEip3009Payload(value) || isPermit2Payload(value);\n}\n\n/**\n * On-chain PaymentInfo struct (canonical Solidity names — DO NOT RENAME).\n * Reconstructed by the facilitator from extra + payload.salt + payer + receiver/asset/amount.\n */\nexport interface PaymentInfoStruct {\n  operator: `0x${string}`; // = extra.captureAuthorizer\n  payer: `0x${string}`;\n  receiver: `0x${string}`; // = requirements.payTo\n  token: `0x${string}`; // = requirements.asset\n  maxAmount: string; // = requirements.amount\n  preApprovalExpiry: number;\n  authorizationExpiry: number; // = extra.captureDeadline\n  refundExpiry: number; // = extra.refundDeadline\n  minFeeBps: number;\n  maxFeeBps: number;\n  feeReceiver: `0x${string}`; // = extra.feeRecipient\n  salt: `0x${string}`; // = payload.salt\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,IAAM,iBAAiB;AACvB,IAAM,0BAA0B;AAYzB,SAAS,oBAAoB,UAAqD;AACvF,MAAI,CAAC,YAAY,aAAa,KAAM,QAAO;AAC3C,MAAI,SAAS,WAAW,wBAAyB,QAAO;AACxD,SAAO,SAAS,YAAY,EAAE,WAAW,cAAc;AACzD;AAaO,SAAS,0BACd,UACsB;AACtB,MAAI,CAAC,oBAAoB,QAAQ,EAAG,QAAO;AAC3C,SAAQ,OAAO,SAAU,MAAM,CAAC,EAAE,YAAY;AAChD;;;ACKO,SAAS,mBAAmB,OAA2C;AAC5E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,SACE,OAAO,EAAE,sBAAsB,YAC/B,OAAO,EAAE,oBAAoB,YAC7B,OAAO,EAAE,mBAAmB,YAC5B,OAAO,EAAE,iBAAiB,YAC1B,OAAO,EAAE,cAAc,YACvB,OAAO,EAAE,cAAc,YACvB,OAAO,EAAE,SAAS,YAClB,OAAO,EAAE,YAAY;AAEzB;AAwBO,SAAS,iBAAiB,OAAyC;AACxE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,SACE,mBAAmB,KACnB,OAAO,EAAE,kBAAkB,YAC3B,EAAE,kBAAkB,QACpB,OAAO,EAAE,cAAc,YACvB,OAAO,EAAE,SAAS;AAEtB;AA0BO,SAASA,kBAAiB,OAAyC;AACxE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,cAAc,YAAY,OAAO,EAAE,SAAS,SAAU,QAAO;AAC1E,MAAI,OAAO,EAAE,yBAAyB,YAAY,EAAE,yBAAyB,KAAM,QAAO;AAC1F,QAAM,IAAI,EAAE;AACZ,SACE,OAAO,EAAE,SAAS,YAClB,OAAO,EAAE,YAAY,YACrB,OAAO,EAAE,UAAU,YACnB,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,cAAc,YACvB,EAAE,cAAc;AAEpB;AAYO,SAAS,qBAAqB,OAA6C;AAChF,SAAO,iBAAiB,KAAK,KAAKA,kBAAiB,KAAK;AAC1D;","names":["isPermit2Payload"]}