{"version":3,"sources":["../../src/exact/client/scheme.ts"],"sourcesContent":["import { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from \"@aeon-ai-pay/core/types\";\nimport { encodeFunctionData, getAddress, Hex } from \"viem\";\nimport {\n  aeonAuthorizationPrimaryType,\n  aeonAuthorizationTypes,\n  authorizationTypes, ERC20_ABI,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2 } from \"../../types\";\nimport { createNonce } from \"../../utils\";\nimport { ReadContractClient, verifyTransferWithAuthorizationSupport } from \"../../contractUtils\";\nimport * as console from \"node:console\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n *\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n  readonly scheme = \"exact\";\n\n  /**\n   * Creates a new ExactEvmClient instance.\n   *\n   * @param signer - The EVM signer for client operations\n   */\n  constructor(\n    private readonly signer: ClientEvmSigner,\n    /**\n     * Optional viem client used for on-chain capability checks (e.g. readContract).\n     * If not provided, the client will assume ERC-3009 support and proceed with EIP-712 signing.\n     */\n    private readonly readClient?: ReadContractClient,\n  ) {}\n\n  /**\n   * Creates a payment payload for the Exact scheme.\n   *\n   * @param x402Version - The x402 protocol version\n   * @param paymentRequirements - The payment requirements\n   * @returns Promise resolving to a payment payload\n   */\n  async createPaymentPayload(\n    x402Version: number,\n    paymentRequirements: PaymentRequirements,\n  ): Promise<Pick<PaymentPayload, \"x402Version\" | \"payload\">> {\n    const nonce = createNonce();\n    const now = Math.floor(Date.now() / 1000);\n\n    const authorization: ExactEvmPayloadV2[\"authorization\"] = {\n      from: this.signer.address,\n      to: getAddress(paymentRequirements.payTo),\n      value: paymentRequirements.amount,\n      validAfter: (now - 600).toString(), // 10 minutes before\n      validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n      nonce,\n    };\n\n    // 验证代币合约是否有TransferWithAuthorization函数\n    const supportsTransferWithAuthorization = await verifyTransferWithAuthorizationSupport(\n      this.signer,\n      paymentRequirements.asset,\n    );\n    console.log(\"[DEBUG] tokenAddress:\", paymentRequirements.asset);\n    console.log(\"[DEBUG] supportsTransferWithAuthorization:\", supportsTransferWithAuthorization);\n    let authorizationResult;\n    if (supportsTransferWithAuthorization) {\n      authorizationResult = await this.signAuthorization(authorization, paymentRequirements);\n    } else {\n      authorizationResult = await this.signAuthorizationNoSuperEip3009(\n        authorization,\n        paymentRequirements,\n      );\n    }\n    // Sign the authorization\n    const signature = authorizationResult;\n    // const signature = await this.signAuthorization(authorization, paymentRequirements);\n\n    const payload: ExactEvmPayloadV2 = {\n      authorization,\n      signature,\n    };\n\n    return {\n      x402Version,\n      payload,\n    };\n  }\n\n  /**\n   * Sign the EIP-3009 authorization using EIP-712\n   *\n   * @param authorization - The authorization to sign\n   * @param requirements - The payment requirements\n   * @returns Promise resolving to the signature\n   */\n  private async signAuthorization(\n    authorization: ExactEvmPayloadV2[\"authorization\"],\n    requirements: PaymentRequirements,\n  ): Promise<`0x${string}`> {\n    const chainId = parseInt(requirements.network.split(\":\")[1]);\n\n    if (!requirements.extra?.name || !requirements.extra?.version) {\n      throw new Error(\n        `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n      );\n    }\n\n    const { name, version } = requirements.extra;\n\n    const domain = {\n      name,\n      version,\n      chainId,\n      verifyingContract: getAddress(requirements.asset),\n    };\n\n    const message = {\n      from: getAddress(authorization.from),\n      to: getAddress(authorization.to),\n      value: BigInt(authorization.value),\n      validAfter: BigInt(authorization.validAfter),\n      validBefore: BigInt(authorization.validBefore),\n      nonce: authorization.nonce,\n    };\n\n    return await this.signer.signTypedData({\n      domain,\n      types: authorizationTypes,\n      primaryType: \"TransferWithAuthorization\",\n      message,\n    });\n  }\n\n  /**\n   * Sign the EIP-3009 authorization using EIP-712\n   *\n   * @param authorization - The authorization to sign\n   * @param requirements - The payment requirements\n   * @returns Promise resolving to the signature\n   */\n  private async signAuthorizationNoSuperEip3009(\n    authorization: ExactEvmPayloadV2[\"authorization\"],\n    requirements: PaymentRequirements,\n  ): Promise<`0x${string}`> {\n    const chainId = parseInt(requirements.network.split(\":\")[1]);\n\n    if (!requirements.extra?.name || !requirements.extra?.version) {\n      throw new Error(\n        `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n      );\n    }\n\n    const from = getAddress(authorization.from);\n    const facilitatorAddress = getAddress(\"0x555e3311a9893c9B17444C1Ff0d88192a57Ef13e\");\n\n    // Read current allowance and auto-approve if needed\n    const currentAllowance = (await this.signer.readContract({\n      address: getAddress(requirements.asset) as Hex,\n      abi: ERC20_ABI,\n      functionName: \"allowance\",\n      args: [from, facilitatorAddress],\n    })) as bigint;\n\n    const requiredAmount = BigInt(authorization.value);\n    // 一次性授权无限额度，后续支付无需再 approve（省 BNB gas）\n    const MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\n    if (currentAllowance < requiredAmount) {\n      const approveData = encodeFunctionData({\n        abi: ERC20_ABI,\n        functionName: \"approve\",\n        args: [facilitatorAddress, MAX_UINT256],\n      });\n      const  tx=await this.signer.sendTransaction({\n        to: getAddress(requirements.asset),\n        data: approveData,\n      });\n\n      console.log(\" Wait for approval transaction to be confirmed (unlimited allowance)\")\n      // Wait for approval transaction to be confirmed\n      const approvalReceipt = await this.signer.waitForTransactionReceipt({\n        hash: tx,\n      });\n\n      if (approvalReceipt.status !== \"success\") {\n        throw new Error(\"Token approval transaction failed\");\n      }\n      console.log(\"approve tx:\", tx);\n    }\n\n    const domain = {\n      name: \"Facilitator\",\n      version: \"1\",\n      chainId,\n      verifyingContract: getAddress(\"0x555e3311a9893c9B17444C1Ff0d88192a57Ef13e\"),\n    };\n    const message = {\n      token: getAddress(requirements.asset),\n      from,\n      to: getAddress(authorization.to),\n      value: BigInt(authorization.value),\n      validAfter: BigInt(authorization.validAfter),\n      validBefore: BigInt(authorization.validBefore),\n      nonce: authorization.nonce,\n      needApprove: true,\n    };\n\n    const data = {\n      domain,\n      types: aeonAuthorizationTypes,\n      primaryType: aeonAuthorizationPrimaryType,\n      message,\n    };\n    console.log(\"signTypedData: \", data);\n    const sign = await this.signer.signTypedData(data);\n    console.log(\"sign: \", sign);\n    return sign;\n  }\n}\n"],"mappings":"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","names":[]}