import { x402Actions } from './chunk-ZSSNU3UF.js';
import { toHex } from 'viem';

var EIP3009_TYPES = {
  TransferWithAuthorization: [
    { name: "from", type: "address" },
    { name: "to", type: "address" },
    { name: "value", type: "uint256" },
    { name: "validAfter", type: "uint256" },
    { name: "validBefore", type: "uint256" },
    { name: "nonce", type: "bytes32" }
  ],
  // Distinct typehash from TransferWithAuthorization — prevents replay across variants.
  // msg.sender must equal `to` on-chain (CallerMustBeRecipient error if violated).
  ReceiveWithAuthorization: [
    { name: "from", type: "address" },
    { name: "to", type: "address" },
    { name: "value", type: "uint256" },
    { name: "validAfter", type: "uint256" },
    { name: "validBefore", type: "uint256" },
    { name: "nonce", type: "bytes32" }
  ],
  CancelAuthorization: [
    { name: "authorizer", type: "address" },
    { name: "nonce", type: "bytes32" }
  ]
};
function getEIP3009Domain(tokenName, tokenVersion, chainId, verifyingContract) {
  return {
    name: tokenName,
    version: tokenVersion,
    chainId,
    verifyingContract
  };
}
function generateNonce() {
  const bytes = new Uint8Array(32);
  globalThis.crypto.getRandomValues(bytes);
  return toHex(bytes);
}
var GTOKEN_EIP712_DOMAIN = { name: "GToken", version: "1" };
async function signTransferWithAuthorization(walletClient, params) {
  const domain = getEIP3009Domain(params.tokenName, params.tokenVersion, params.chainId, params.verifyingContract);
  const account = walletClient.account;
  if (!account) {
    throw new Error("WalletClient must have an account");
  }
  return walletClient.signTypedData({
    account,
    domain,
    types: EIP3009_TYPES,
    primaryType: "TransferWithAuthorization",
    message: {
      from: params.from,
      to: params.to,
      value: params.value,
      validAfter: params.validAfter,
      validBefore: params.validBefore,
      nonce: params.nonce
    }
  });
}
async function signGTokenTransferWithAuthorization(walletClient, params) {
  const account = walletClient.account;
  if (!account) {
    throw new Error("WalletClient must have an account");
  }
  if (account.address.toLowerCase() !== params.from.toLowerCase()) {
    throw new Error(`Signer ${account.address} does not match from ${params.from}`);
  }
  if (params.validBefore <= params.validAfter) {
    throw new Error("validBefore must be greater than validAfter");
  }
  if (params.validBefore - params.validAfter > 300n) {
    throw new Error(`Authorization window ${params.validBefore - params.validAfter}s exceeds MAX_AUTH_VALIDITY (300s)`);
  }
  return signTransferWithAuthorization(walletClient, params);
}
async function signReceiveWithAuthorization(walletClient, params) {
  const account = walletClient.account;
  if (!account) {
    throw new Error("WalletClient must have an account");
  }
  if (account.address.toLowerCase() !== params.from.toLowerCase()) {
    throw new Error(`Signer ${account.address} does not match from ${params.from}`);
  }
  if (params.validBefore <= params.validAfter) {
    throw new Error("validBefore must be greater than validAfter");
  }
  if (params.validBefore - params.validAfter > 300n) {
    throw new Error(`Authorization window ${params.validBefore - params.validAfter}s exceeds MAX_AUTH_VALIDITY (300s)`);
  }
  return walletClient.signTypedData({
    account,
    domain: getEIP3009Domain(params.tokenName, params.tokenVersion, params.chainId, params.verifyingContract),
    types: EIP3009_TYPES,
    primaryType: "ReceiveWithAuthorization",
    message: {
      from: params.from,
      to: params.to,
      value: params.value,
      validAfter: params.validAfter,
      validBefore: params.validBefore,
      nonce: params.nonce
    }
  });
}
async function signCancelAuthorization(walletClient, params) {
  const account = walletClient.account;
  if (!account) {
    throw new Error("WalletClient must have an account");
  }
  if (account.address.toLowerCase() !== params.authorizer.toLowerCase()) {
    throw new Error(`Signer ${account.address} does not match authorizer ${params.authorizer}`);
  }
  return walletClient.signTypedData({
    account,
    domain: getEIP3009Domain(params.tokenName, params.tokenVersion, params.chainId, params.verifyingContract),
    types: EIP3009_TYPES,
    primaryType: "CancelAuthorization",
    message: {
      authorizer: params.authorizer,
      nonce: params.nonce
    }
  });
}

// ../x402/dist/payment-header.js
var HEADER_PAYMENT_REQUIRED = "PAYMENT-REQUIRED";
var HEADER_PAYMENT_SIGNATURE = "PAYMENT-SIGNATURE";
var HEADER_PAYMENT_RESPONSE = "PAYMENT-RESPONSE";
var HEADER_V1_PAYMENT = "X-PAYMENT";
var HEADER_V1_PAYMENT_RESPONSE = "X-PAYMENT-RESPONSE";
function toBase64(data) {
  const json = JSON.stringify(data);
  if (typeof Buffer !== "undefined") {
    return Buffer.from(json).toString("base64");
  }
  return btoa(json);
}
function fromBase64(encoded) {
  let json;
  if (typeof Buffer !== "undefined") {
    json = Buffer.from(encoded, "base64").toString("utf-8");
  } else {
    json = atob(encoded);
  }
  return JSON.parse(json);
}
function encodePaymentRequired(req) {
  return toBase64(req);
}
function decodePaymentRequired(encoded) {
  return fromBase64(encoded);
}
function encodePaymentPayload(payload) {
  return toBase64(payload);
}
function decodePaymentPayload(encoded) {
  return fromBase64(encoded);
}
function encodeSettleResponse(resp) {
  return toBase64(resp);
}
function decodeSettleResponse(encoded) {
  return fromBase64(encoded);
}
function extractPaymentRequired(response) {
  const v2 = response.headers.get(HEADER_PAYMENT_REQUIRED);
  if (v2)
    return decodePaymentRequired(v2);
  const v1 = response.headers.get("X-PAYMENT-REQUIRED");
  if (v1)
    return decodePaymentRequired(v1);
  return null;
}
function extractSettleResponse(response) {
  const v2 = response.headers.get(HEADER_PAYMENT_RESPONSE);
  if (v2)
    return decodeSettleResponse(v2);
  const v1 = response.headers.get(HEADER_V1_PAYMENT_RESPONSE);
  if (v1)
    return decodeSettleResponse(v1);
  return null;
}

// ../x402/dist/facilitator.js
var FacilitatorClient = class {
  url;
  createAuthHeaders;
  constructor(config) {
    this.url = config.url.replace(/\/$/, "");
    this.createAuthHeaders = config.createAuthHeaders;
  }
  async getHeaders(endpoint) {
    const base = { "Content-Type": "application/json" };
    if (!this.createAuthHeaders)
      return base;
    const auth = await this.createAuthHeaders();
    return { ...base, ...auth[endpoint] };
  }
  /**
   * POST /verify — validate payment signature off-chain (~100ms).
   */
  async verify(paymentPayload, paymentRequirements) {
    const resp = await fetch(`${this.url}/verify`, {
      method: "POST",
      headers: await this.getHeaders("verify"),
      body: JSON.stringify({
        x402Version: 2,
        paymentPayload,
        paymentRequirements
      })
    });
    if (!resp.ok) {
      throw new Error(`Facilitator /verify failed: ${resp.status} ${await resp.text()}`);
    }
    return resp.json();
  }
  /**
   * POST /settle — execute on-chain settlement (~2s on Base).
   */
  async settle(paymentPayload, paymentRequirements) {
    const resp = await fetch(`${this.url}/settle`, {
      method: "POST",
      headers: await this.getHeaders("settle"),
      body: JSON.stringify({
        x402Version: 2,
        paymentPayload,
        paymentRequirements
      })
    });
    if (!resp.ok) {
      throw new Error(`Facilitator /settle failed: ${resp.status} ${await resp.text()}`);
    }
    return resp.json();
  }
  /**
   * GET /supported — query facilitator capabilities.
   */
  async supported() {
    const resp = await fetch(`${this.url}/supported`, {
      method: "GET",
      headers: await this.getHeaders("supported")
    });
    if (!resp.ok) {
      throw new Error(`Facilitator /supported failed: ${resp.status} ${await resp.text()}`);
    }
    return resp.json();
  }
};

// ../x402/dist/X402Client.js
function toNetworkId(chainId) {
  return `eip155:${chainId}`;
}
var X402Client = class {
  actions;
  config;
  facilitatorClient;
  constructor(config) {
    if (!config.walletClient.account) {
      throw new Error("WalletClient must have an account configured");
    }
    this.config = config;
    this.actions = x402Actions(config.superPaymasterAddress)(config.walletClient);
    if (config.facilitator) {
      this.facilitatorClient = new FacilitatorClient(config.facilitator);
    }
  }
  /**
   * Create a signed payment payload (EIP-3009 TransferWithAuthorization).
   * Returns a base64-encoded PaymentPayload ready for PAYMENT-SIGNATURE header.
   */
  async createPayment(params) {
    const nonce = params.nonce || generateNonce();
    const now = BigInt(Math.floor(Date.now() / 1e3));
    const validAfter = params.validAfter ?? now - 600n;
    const validBefore = params.validBefore ?? now + 3600n;
    const tokenName = this.config.tokenName || "USDC";
    const tokenVersion = this.config.tokenVersion || "2";
    const signature = await signTransferWithAuthorization(this.config.walletClient, {
      from: params.from,
      to: params.to,
      value: params.amount,
      validAfter,
      validBefore,
      nonce,
      tokenName,
      tokenVersion,
      chainId: this.config.chainId,
      verifyingContract: params.asset
    });
    const payload = {
      x402Version: 2,
      accepted: {
        scheme: "exact",
        network: toNetworkId(this.config.chainId),
        asset: params.asset,
        amount: params.amount.toString(),
        payTo: params.to,
        maxTimeoutSeconds: 3600,
        extra: { name: tokenName, version: tokenVersion }
      },
      payload: {
        signature,
        authorization: {
          from: params.from,
          to: params.to,
          value: params.amount.toString(),
          validAfter: validAfter.toString(),
          validBefore: validBefore.toString(),
          nonce
        }
      }
    };
    return {
      payload,
      encoded: encodePaymentPayload(payload),
      nonce
    };
  }
  /**
   * Settle payment on-chain via SuperPaymaster (self-facilitated).
   * Uses EIP-3009 transferWithAuthorization path.
   */
  async settleOnChain(params) {
    return this.actions.settleX402Payment({
      ...params,
      account: this.config.walletClient.account
    });
  }
  /**
   * Settle payment on-chain via direct transfer (for xPNTs and pre-approved tokens).
   */
  async settleDirectOnChain(params) {
    return this.actions.settleX402PaymentDirect({
      ...params,
      account: this.config.walletClient.account
    });
  }
  /**
   * Get facilitator fee quote from on-chain contract.
   */
  async getQuote() {
    const feeBPS = await this.actions.facilitatorFeeBPS();
    return { feeBPS };
  }
  /**
   * Check if a nonce has been used.
   */
  async checkNonce(nonce) {
    return this.actions.x402SettlementNonces({ nonce });
  }
  /**
   * Settle via external facilitator (Coinbase, self-hosted, etc.).
   * Requires facilitator config in constructor.
   */
  async settleViaFacilitator(payload, requirements) {
    if (!this.facilitatorClient) {
      throw new Error("No facilitator configured. Pass facilitator config to X402Client constructor.");
    }
    return this.facilitatorClient.settle(payload, requirements);
  }
  /**
   * x402-aware fetch wrapper.
   * Automatically handles 402 → sign → retry flow per x402 v2 spec.
   *
   * Pattern from: @x402/fetch wrapFetchWithPayment
   *
   * Flow:
   * 1. Make initial request
   * 2. If 402, extract PaymentRequired from PAYMENT-REQUIRED header
   * 3. Select best payment option (applies policy: max amount check)
   * 4. Sign EIP-3009 authorization
   * 5. Retry with PAYMENT-SIGNATURE header
   */
  async x402Fetch(url, init) {
    const firstResponse = await fetch(url, init);
    if (firstResponse.status !== 402) {
      return firstResponse;
    }
    const paymentRequired = extractPaymentRequired(firstResponse);
    if (!paymentRequired || !paymentRequired.accepts?.length) {
      throw new Error("402 response missing PAYMENT-REQUIRED header or empty accepts");
    }
    const myNetwork = toNetworkId(this.config.chainId);
    let selected = paymentRequired.accepts.find((a) => a.network === myNetwork && a.scheme === "exact");
    if (!selected) {
      selected = paymentRequired.accepts.find((a) => a.network.startsWith("eip155:"));
    }
    if (!selected) {
      throw new Error(`No compatible payment option for network ${myNetwork}`);
    }
    if (this.config.maxAmountPerRequest && BigInt(selected.amount) > this.config.maxAmountPerRequest) {
      throw new Error(`Payment amount ${selected.amount} exceeds max ${this.config.maxAmountPerRequest}`);
    }
    const account = this.config.walletClient.account;
    if (!account) {
      throw new Error("WalletClient must have an account for automatic payment");
    }
    const { encoded } = await this.createPayment({
      from: account.address,
      to: selected.payTo,
      asset: selected.asset,
      amount: BigInt(selected.amount)
    });
    const retryHeaders = new Headers(init?.headers);
    retryHeaders.set(HEADER_PAYMENT_SIGNATURE, encoded);
    return fetch(url, { ...init, headers: retryHeaders });
  }
};

export { EIP3009_TYPES, FacilitatorClient, GTOKEN_EIP712_DOMAIN, HEADER_PAYMENT_REQUIRED, HEADER_PAYMENT_RESPONSE, HEADER_PAYMENT_SIGNATURE, HEADER_V1_PAYMENT, HEADER_V1_PAYMENT_RESPONSE, X402Client, decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractPaymentRequired, extractSettleResponse, generateNonce, getEIP3009Domain, signCancelAuthorization, signGTokenTransferWithAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization };
//# sourceMappingURL=chunk-XFI3AK32.js.map
//# sourceMappingURL=chunk-XFI3AK32.js.map