import { SuperPaymasterABI } from './chunk-ZSSNU3UF.js';
import { concat, pad, toHex, keccak256, encodeAbiParameters, toBytes, parseAbiParameters, parseAbi, encodeFunctionData } from 'viem';

var DEFAULT_VERIFICATION_GAS = 160000n;
var DEFAULT_POSTOP_GAS = 10000n;
function getSuperPaymasterMiddleware(config) {
  return {
    sponsorUserOperation: async (args) => {
      const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS;
      const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS;
      const maxRate = config.maxRate ?? 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn;
      const paymasterAndData = concat([
        config.paymasterAddress,
        pad(toHex(verGas), { size: 16 }),
        pad(toHex(postGas), { size: 16 }),
        config.operator,
        pad(toHex(maxRate), { size: 32 })
      ]);
      return {
        paymasterAndData,
        verificationGasLimit: verGas,
        preVerificationGas: args.userOperation.preVerificationGas
      };
    }
  };
}
async function checkEligibility(client, paymaster, user, operator) {
  try {
    const operatorData = await client.readContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "operators",
      args: [operator]
    });
    const token = operatorData[0];
    const isConfigured = operatorData[2];
    const isPaused = operatorData[3];
    if (!isConfigured || isPaused) {
      return { eligible: false };
    }
    const credit = await client.readContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "getAvailableCredit",
      args: [user, token]
    });
    return {
      eligible: credit > 0n,
      credit,
      token
    };
  } catch (e) {
    console.warn("Eligibility check failed:", e);
    return { eligible: false };
  }
}
var SuperPaymasterAdminClient = class {
  client;
  paymasterAddress;
  constructor(client, paymasterAddress) {
    this.client = client;
    this.paymasterAddress = paymasterAddress;
  }
  async getOperator(operator) {
    return this.client.readContract({
      address: this.paymasterAddress,
      abi: SuperPaymasterABI,
      functionName: "operators",
      args: [operator]
    });
  }
  static async configureOperator(wallet, paymaster, token, treasury) {
    return wallet.writeContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "configureOperator",
      args: [token, treasury],
      chain: wallet.chain
    });
  }
  static async setOperatorPaused(wallet, paymaster, operator, paused) {
    return wallet.writeContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "setOperatorPaused",
      args: [operator, paused],
      chain: wallet.chain
    });
  }
  static async updateReputation(wallet, paymaster, operator, score) {
    return wallet.writeContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "updateReputation",
      args: [operator, score],
      chain: wallet.chain
    });
  }
  static async setAPNTsToken(wallet, paymaster, token) {
    return wallet.writeContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "setAPNTsToken",
      args: [token],
      chain: wallet.chain
    });
  }
  static async setXPNTsFactory(wallet, paymaster, factory) {
    return wallet.writeContract({
      address: paymaster,
      abi: SuperPaymasterABI,
      functionName: "setXPNTsFactory",
      args: [factory],
      chain: wallet.chain
    });
  }
};
var DEFAULT_VERIFICATION_GAS_V4 = 1500000n;
var DEFAULT_POSTOP_GAS_V4 = 300000n;
function getPaymasterV4Middleware(config) {
  return {
    sponsorUserOperation: async (args) => {
      const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS_V4;
      const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS_V4;
      const paymasterAndData = concat([
        config.paymasterAddress,
        pad(toHex(verGas), { size: 16 }),
        pad(toHex(postGas), { size: 16 }),
        config.gasToken
      ]);
      return {
        paymasterAndData,
        verificationGasLimit: verGas,
        preVerificationGas: args.userOperation.preVerificationGas
      };
    }
  };
}
function buildPaymasterData(paymasterAddress, token, options) {
  const validityWindow = options?.validityWindow ?? 3600;
  const verGas = options?.verificationGasLimit ?? 200000n;
  const postGas = options?.postOpGasLimit ?? 100000n;
  const now = Math.floor(Date.now() / 1e3);
  const validUntil = now + validityWindow;
  const validAfter = now - 100;
  return concat([
    paymasterAddress,
    pad(toHex(verGas), { size: 16 }),
    pad(toHex(postGas), { size: 16 }),
    token,
    pad(toHex(validUntil), { size: 6 }),
    pad(toHex(validAfter), { size: 6 })
  ]);
}
function buildSuperPaymasterData(paymasterAddress, operator, options) {
  const verGas = options?.verificationGasLimit ?? 80000n;
  const postGas = options?.postOpGasLimit ?? 100000n;
  const maxRate = options?.maxRate ?? (1n << 256n) - 1n;
  return concat([
    paymasterAddress,
    pad(toHex(verGas), { size: 16 }),
    pad(toHex(postGas), { size: 16 }),
    operator,
    pad(toHex(maxRate), { size: 32 })
    // Optional rate commitment (rug pull protection)
  ]);
}
function formatUserOpV07(userOp) {
  const result = {
    sender: userOp.sender,
    nonce: toHex(userOp.nonce),
    callData: userOp.callData,
    preVerificationGas: toHex(userOp.preVerificationGas),
    signature: userOp.signature
  };
  if (userOp.initCode && userOp.initCode !== "0x" && userOp.initCode.length > 2) {
    result.initCode = userOp.initCode;
    if (userOp.initCode.length > 42) {
      result.factory = userOp.initCode.slice(0, 42);
      result.factoryData = "0x" + userOp.initCode.slice(42);
    } else {
      result.factory = "0x0000000000000000000000000000000000000000";
      result.factoryData = "0x";
    }
  }
  if (userOp.accountGasLimits && userOp.accountGasLimits !== "0x") {
    const packed = userOp.accountGasLimits.replace("0x", "").padStart(64, "0");
    result.verificationGasLimit = "0x" + BigInt("0x" + packed.slice(0, 32)).toString(16);
    result.callGasLimit = "0x" + BigInt("0x" + packed.slice(32, 64)).toString(16);
  }
  if (userOp.gasFees && userOp.gasFees !== "0x") {
    const packed = userOp.gasFees.replace("0x", "").padStart(64, "0");
    result.maxPriorityFeePerGas = "0x" + BigInt("0x" + packed.slice(0, 32)).toString(16);
    result.maxFeePerGas = "0x" + BigInt("0x" + packed.slice(32, 64)).toString(16);
  }
  if (userOp.paymasterAndData && userOp.paymasterAndData !== "0x") {
    const packed = userOp.paymasterAndData.replace("0x", "");
    if (packed.length >= 104) {
      result.paymaster = "0x" + packed.slice(0, 40);
      result.paymasterVerificationGasLimit = "0x" + BigInt("0x" + packed.slice(40, 72)).toString(16);
      result.paymasterPostOpGasLimit = "0x" + BigInt("0x" + packed.slice(72, 104)).toString(16);
      result.paymasterData = "0x" + packed.slice(104);
    }
  }
  return result;
}
function getUserOpHashV07(userOp, entryPoint, chainId) {
  const hashedUserOp = keccak256(encodeAbiParameters(["address", "uint256", "bytes32", "bytes32", "bytes32", "uint256", "bytes32", "bytes32"].map((t) => ({ type: t })), [
    userOp.sender,
    userOp.nonce,
    keccak256(toBytes(userOp.initCode)),
    keccak256(toBytes(userOp.callData)),
    userOp.accountGasLimits,
    toHex(userOp.preVerificationGas),
    userOp.gasFees,
    keccak256(toBytes(userOp.paymasterAndData))
  ]));
  return keccak256(encodeAbiParameters(["bytes32", "address", "uint256"].map((t) => ({ type: t })), [hashedUserOp, entryPoint, chainId]));
}
function tuneGasLimit(estimate, nominalActual, targetEfficiency = 0.45) {
  if (estimate === 0n)
    return 0n;
  const ceiling = nominalActual * 100n / BigInt(Math.floor(targetEfficiency * 100));
  return estimate < ceiling ? estimate : ceiling;
}

// ../paymaster/dist/V4/BundlerCompat.js
var BundlerType;
(function(BundlerType2) {
  BundlerType2["ALCHEMY"] = "alchemy";
  BundlerType2["PIMLICO"] = "pimlico";
  BundlerType2["STACKUP"] = "stackup";
  BundlerType2["CANDIDE"] = "candide";
  BundlerType2["UNKNOWN"] = "unknown";
})(BundlerType || (BundlerType = {}));
function detectBundlerType(bundlerUrl) {
  const url = bundlerUrl.toLowerCase();
  if (url.includes("alchemy.com"))
    return BundlerType.ALCHEMY;
  if (url.includes("pimlico.io"))
    return BundlerType.PIMLICO;
  if (url.includes("stackup"))
    return BundlerType.STACKUP;
  if (url.includes("candide.dev"))
    return BundlerType.CANDIDE;
  return BundlerType.UNKNOWN;
}

// ../paymaster/dist/V4/PaymasterClient.js
var PaymasterClient = class _PaymasterClient {
  /**
   * @private
   * Static utility class, should not be instantiated.
   */
  constructor() {
  }
  static makePlaceholderSignature(byteLength) {
    const clamped = Math.max(0, Math.min(byteLength, 1e4));
    return `0x${"11".repeat(clamped)}`;
  }
  static estimatePreVerificationGasV07(userOp) {
    const encoded = encodeAbiParameters(parseAbiParameters("(address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)"), [
      [
        userOp.sender,
        userOp.nonce,
        userOp.initCode,
        userOp.callData,
        userOp.accountGasLimits,
        userOp.preVerificationGas,
        userOp.gasFees,
        userOp.paymasterAndData,
        userOp.signature
      ]
    ]);
    const bytes = toBytes(encoded);
    let calldataCost = 0n;
    for (const b of bytes)
      calldataCost += b === 0 ? 4n : 16n;
    return calldataCost + 26000n;
  }
  /**
   * Get user's deposited balance on the Paymaster.
   */
  static async getDepositedBalance(publicClient, address, user, token) {
    return publicClient.readContract({
      address,
      abi: [{
        name: "balances",
        type: "function",
        inputs: [
          { name: "user", type: "address" },
          { name: "token", type: "address" }
        ],
        outputs: [{ name: "", type: "uint256" }],
        stateMutability: "view"
      }],
      functionName: "balances",
      args: [user, token]
    });
  }
  /**
   * Deposit tokens to Paymaster for a user (enables gasless transactions).
   */
  static async depositFor(wallet, address, user, token, amount) {
    return wallet.writeContract({
      address,
      abi: parseAbi(["function depositFor(address user, address token, uint256 amount) external"]),
      functionName: "depositFor",
      args: [user, token, amount],
      chain: wallet.chain
    });
  }
  /**
   * Approve the Paymaster (or any spender) to spend gas tokens.
   */
  static async approveGasToken(wallet, token, spender, amount) {
    return wallet.writeContract({
      address: token,
      abi: parseAbi(["function approve(address spender, uint256 amount) external returns (bool)"]),
      functionName: "approve",
      args: [spender, amount],
      chain: wallet.chain
    });
  }
  /**
   * Estimate Gas for a UserOperation.
   */
  static async estimateUserOperationGas(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, options) {
    if (!options?.operator) {
      try {
        const cache = await client.readContract({
          address: paymasterAddress,
          abi: parseAbi(["function cachedPrice() view returns (uint208 price, uint48 updatedAt)"]),
          functionName: "cachedPrice"
        });
        const cachedPrice = BigInt(cache?.price ?? cache?.[0] ?? 0);
        const cachedUpdatedAt = BigInt(cache?.updatedAt ?? cache?.[1] ?? 0);
        const now = BigInt(Math.floor(Date.now() / 1e3));
        let stalenessThreshold = 0n;
        try {
          stalenessThreshold = await client.readContract({
            address: paymasterAddress,
            abi: parseAbi(["function priceStalenessThreshold() view returns (uint256)"]),
            functionName: "priceStalenessThreshold"
          });
        } catch {
        }
        const isStale = cachedPrice === 0n || cachedUpdatedAt === 0n || stalenessThreshold > 0n && cachedUpdatedAt + stalenessThreshold < now;
        if (isStale) {
          const chainId2 = client.chain?.id || await client.getChainId();
          const isTestnet2 = [11155111, 11155420, 31337].includes(chainId2);
          if (isTestnet2) {
            const updateHash = await wallet.writeContract({
              address: paymasterAddress,
              abi: parseAbi(["function updatePrice() external"]),
              functionName: "updatePrice"
            });
            await client.waitForTransactionReceipt({ hash: updateHash });
            console.log("[PaymasterClient] \u2705 cachedPrice refreshed via updatePrice()");
          } else {
            throw new Error(`Paymaster cachedPrice is stale on Mainnet (chainId: ${chainId2}). This requires Keeper to call updatePrice(). Please ensure Keeper is running.`);
          }
        }
      } catch (e) {
        if (e.message?.includes("requires Keeper"))
          throw e;
        console.log("[PaymasterClient] \u26A0\uFE0F  Failed to check cachedPrice:", e.message?.slice(0, 50));
      }
    }
    let paymasterAndData;
    if (options?.operator) {
      paymasterAndData = buildSuperPaymasterData(paymasterAddress, options.operator, {
        verificationGasLimit: 300000n,
        postOpGasLimit: 300000n
      });
    } else {
      paymasterAndData = buildPaymasterData(paymasterAddress, token, {
        validityWindow: options?.validityWindow,
        verificationGasLimit: 250000n,
        postOpGasLimit: 150000n
      });
    }
    const chainId = client.chain?.id || await client.getChainId();
    const isTestnet = [11155111, 11155420, 31337].includes(chainId);
    const TESTNET_PRIORITY_FLOOR = 500000000n;
    let maxFeePerGas = 0n;
    let maxPriorityFeePerGas = 0n;
    try {
      const feeData = await client.estimateFeesPerGas();
      maxFeePerGas = (feeData.maxFeePerGas ?? 0n) * 115n / 100n;
      maxPriorityFeePerGas = (feeData.maxPriorityFeePerGas ?? 0n) * 115n / 100n;
    } catch {
    }
    if (!maxFeePerGas) {
      try {
        const gasPrice = await client.getGasPrice();
        maxFeePerGas = gasPrice * 120n / 100n;
      } catch {
      }
    }
    if (isTestnet) {
      if (maxPriorityFeePerGas < TESTNET_PRIORITY_FLOOR)
        maxPriorityFeePerGas = TESTNET_PRIORITY_FLOOR;
      if (maxFeePerGas < TESTNET_PRIORITY_FLOOR * 2n)
        maxFeePerGas = TESTNET_PRIORITY_FLOOR * 2n;
    }
    if (!maxFeePerGas)
      maxFeePerGas = 1n;
    if (maxFeePerGas < maxPriorityFeePerGas)
      maxFeePerGas = maxPriorityFeePerGas + 1n;
    const partialUserOp = {
      sender: aaAddress,
      nonce: 0n,
      initCode: options?.factory && options?.factoryData ? concat([options.factory, options.factoryData]) : "0x",
      callData,
      accountGasLimits: concat([pad(toHex(250000n), { size: 16 }), pad(toHex(500000n), { size: 16 })]),
      preVerificationGas: 0n,
      gasFees: concat([pad(toHex(maxPriorityFeePerGas), { size: 16 }), pad(toHex(maxFeePerGas), { size: 16 })]),
      paymasterAndData,
      signature: _PaymasterClient.makePlaceholderSignature(65)
    };
    try {
      const nonce = await client.readContract({
        address: aaAddress,
        abi: parseAbi(["function getNonce() view returns (uint256)"]),
        functionName: "getNonce"
      });
      partialUserOp.nonce = BigInt(nonce);
    } catch (e) {
    }
    partialUserOp.preVerificationGas = _PaymasterClient.estimatePreVerificationGasV07(partialUserOp) * 120n / 100n + 5000n;
    const userOpHash = getUserOpHashV07(partialUserOp, entryPoint, BigInt(client.chain.id));
    partialUserOp.signature = await wallet.account.signMessage({ message: { raw: userOpHash } });
    const payload = {
      jsonrpc: "2.0",
      id: 1,
      method: "eth_estimateUserOperationGas",
      params: [formatUserOpV07(partialUserOp), entryPoint]
    };
    const response = await fetch(bundlerUrl, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload, (_, v) => typeof v === "bigint" ? "0x" + v.toString(16) : v)
    });
    const result = await response.json();
    if (bundlerUrl.includes("candide")) {
      console.log("[PaymasterClient] Candide Request:", JSON.stringify(payload.params[0], null, 2));
      console.log("[PaymasterClient] Candide Response:", JSON.stringify(result, null, 2));
    }
    const data = result.result;
    console.log("[PaymasterClient] Gas Estimation Result:", JSON.stringify(data, null, 2));
    if (result.error && (result.error.code === -32601 || result.error.message?.includes("Method not found"))) {
      console.log("[PaymasterClient] EstimateUserOp failed (Method not found). Using Anvil defaults.");
      return {
        preVerificationGas: partialUserOp.preVerificationGas,
        verificationGasLimit: 1000000n,
        callGasLimit: 2000000n,
        paymasterVerificationGasLimit: 100000n,
        paymasterPostOpGasLimit: 100000n
      };
    }
    if (result.error)
      throw new Error(`Estimation Error: ${JSON.stringify(result.error)}`);
    const estVGL = BigInt(data.verificationGasLimit);
    const estPMVGL = data.paymasterVerificationGasLimit ? BigInt(data.paymasterVerificationGasLimit) : 100000n;
    return {
      preVerificationGas: BigInt(data.preVerificationGas) * 120n / 100n + 5000n,
      verificationGasLimit: tuneGasLimit(estVGL, 35000n, 0.45),
      callGasLimit: BigInt(data.callGasLimit) * 110n / 100n,
      // Small 1.1x buffer
      paymasterVerificationGasLimit: tuneGasLimit(estPMVGL, 35000n, 0.45),
      paymasterPostOpGasLimit: data.paymasterPostOpGasLimit ? BigInt(data.paymasterPostOpGasLimit) : 100000n
    };
  }
  /**
   * High-level API to submit a gasless UserOperation.
   * Automatically handles nonce fetching, gas estimation (if not provided), signing, and submission.
   */
  static async submitGaslessUserOperation(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, options) {
    let gasLimits = {
      preVerificationGas: options?.preVerificationGas,
      verificationGasLimit: options?.verificationGasLimit,
      callGasLimit: options?.callGasLimit,
      paymasterVerificationGasLimit: options?.paymasterVerificationGasLimit,
      paymasterPostOpGasLimit: options?.paymasterPostOpGasLimit ?? 200000n
    };
    if (options?.autoEstimate !== false && (!gasLimits.verificationGasLimit || !gasLimits.callGasLimit)) {
      const est = await this.estimateUserOperationGas(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, {
        validityWindow: options?.validityWindow,
        operator: options?.operator,
        factory: options?.factory,
        factoryData: options?.factoryData
      });
      gasLimits.preVerificationGas = options?.preVerificationGas ?? est.preVerificationGas;
      gasLimits.verificationGasLimit = options?.verificationGasLimit ?? est.verificationGasLimit;
      gasLimits.callGasLimit = options?.callGasLimit ?? est.callGasLimit;
      gasLimits.paymasterVerificationGasLimit = options?.paymasterVerificationGasLimit ?? est.paymasterVerificationGasLimit;
      if (!options?.paymasterPostOpGasLimit) {
        const _base = est.paymasterPostOpGasLimit + 100000n;
        gasLimits.paymasterPostOpGasLimit = _base > 200000n ? _base : 200000n;
      }
    }
    const nonce = await client.readContract({
      address: aaAddress,
      abi: parseAbi(["function getNonce() view returns (uint256)"]),
      functionName: "getNonce"
    });
    const chainId = client.chain?.id || await client.getChainId();
    const isTestnet = [11155111, 11155420, 31337].includes(chainId);
    const TESTNET_PRIORITY_FLOOR = 500000000n;
    let maxFeePerGas = options?.maxFeePerGas;
    let maxPriorityFeePerGas = options?.maxPriorityFeePerGas;
    if (!maxFeePerGas || !maxPriorityFeePerGas) {
      try {
        const feeData = await client.estimateFeesPerGas();
        maxFeePerGas = maxFeePerGas ?? (feeData.maxFeePerGas ?? 0n) * 115n / 100n;
        maxPriorityFeePerGas = maxPriorityFeePerGas ?? (feeData.maxPriorityFeePerGas ?? 0n) * 115n / 100n;
      } catch (e) {
        maxFeePerGas = maxFeePerGas ?? void 0;
        maxPriorityFeePerGas = maxPriorityFeePerGas ?? void 0;
      }
    }
    if (!maxFeePerGas) {
      try {
        maxFeePerGas = await client.getGasPrice() * 150n / 100n;
      } catch {
      }
    }
    if (isTestnet) {
      maxPriorityFeePerGas = maxPriorityFeePerGas ?? TESTNET_PRIORITY_FLOOR;
      if (maxPriorityFeePerGas < TESTNET_PRIORITY_FLOOR)
        maxPriorityFeePerGas = TESTNET_PRIORITY_FLOOR;
      if (!maxFeePerGas || maxFeePerGas < TESTNET_PRIORITY_FLOOR * 2n)
        maxFeePerGas = TESTNET_PRIORITY_FLOOR * 2n;
    }
    maxFeePerGas = maxFeePerGas ?? 1n;
    maxPriorityFeePerGas = maxPriorityFeePerGas ?? 0n;
    if (maxFeePerGas < maxPriorityFeePerGas)
      maxFeePerGas = maxPriorityFeePerGas + 1n;
    console.log(`[PaymasterClient] Gas Pricing: ${isTestnet ? "TESTNET (0.5 Gwei floor)" : "MAINNET (dynamic)"} | priority=${maxPriorityFeePerGas} maxFee=${maxFeePerGas}`);
    let paymasterAndData;
    if (options?.operator) {
      paymasterAndData = buildSuperPaymasterData(paymasterAddress, options.operator, {
        verificationGasLimit: gasLimits.paymasterVerificationGasLimit ?? gasLimits.verificationGasLimit ?? 150000n,
        postOpGasLimit: gasLimits.paymasterPostOpGasLimit ?? 100000n
      });
    } else {
      const pmVerGas = gasLimits.paymasterVerificationGasLimit ?? 75000n;
      paymasterAndData = buildPaymasterData(paymasterAddress, token, {
        validityWindow: options?.validityWindow,
        verificationGasLimit: pmVerGas,
        postOpGasLimit: gasLimits.paymasterPostOpGasLimit ?? 100000n
      });
    }
    const initCode = options?.factory && options?.factoryData ? concat([options.factory, options.factoryData]) : "0x";
    const accountGasLimits = concat([
      pad(toHex(gasLimits.verificationGasLimit ?? 75000n), { size: 16 }),
      pad(toHex(gasLimits.callGasLimit ?? 500000n), { size: 16 })
    ]);
    const gasFees = concat([
      pad(toHex(maxPriorityFeePerGas), { size: 16 }),
      pad(toHex(maxFeePerGas), { size: 16 })
    ]);
    const preVerificationGas = gasLimits.preVerificationGas ?? _PaymasterClient.estimatePreVerificationGasV07({
      sender: aaAddress,
      nonce: BigInt(nonce),
      initCode,
      callData,
      accountGasLimits,
      preVerificationGas: 0n,
      gasFees,
      paymasterAndData,
      signature: _PaymasterClient.makePlaceholderSignature(65)
    }) * 120n / 100n + 5000n;
    const userOp = {
      sender: aaAddress,
      nonce: BigInt(nonce),
      initCode,
      callData,
      accountGasLimits,
      preVerificationGas,
      gasFees,
      paymasterAndData,
      signature: "0x"
    };
    const userOpHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
    const signature = await wallet.account.signMessage({ message: { raw: userOpHash } });
    userOp.signature = signature;
    const bundlerType = detectBundlerType(bundlerUrl);
    console.log(`[PaymasterClient] Using ${bundlerType} Bundler`);
    for (let attempt = 0; attempt < 5; attempt++) {
      const response = await fetch(bundlerUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          jsonrpc: "2.0",
          id: 1,
          method: "eth_sendUserOperation",
          params: [formatUserOpV07(userOp), entryPoint]
        }, (_, v) => typeof v === "bigint" ? "0x" + v.toString(16) : v)
      });
      const result = await response.json();
      if (result.error && attempt < 4) {
        const msg = result.error.message || "";
        const errData = result.error.data || {};
        if (result.error.code === -32602 || msg.includes("replacement underpriced")) {
          console.log(`[PaymasterClient] \u26A0\uFE0F  Replacement Underpriced. Bumping fees to replace pending UserOp...`);
          let newMaxPriority = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(2, 34)) : 0n;
          let newMaxFee = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(34)) : 0n;
          if (errData.currentMaxPriorityFee && errData.currentMaxFee) {
            const currentPriority = BigInt(errData.currentMaxPriorityFee);
            const currentMax = BigInt(errData.currentMaxFee);
            newMaxPriority = currentPriority * 110n / 100n;
            newMaxFee = currentMax * 110n / 100n;
          } else {
            newMaxPriority = newMaxPriority * 115n / 100n;
            newMaxFee = newMaxFee * 115n / 100n;
          }
          console.log(`   -> New Priority: ${newMaxPriority}, New MaxFee: ${newMaxFee}`);
          userOp.gasFees = concat([
            pad(toHex(newMaxPriority), { size: 16 }),
            pad(toHex(newMaxFee), { size: 16 })
          ]);
          const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
          userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
          continue;
        }
        const matchPriority = msg.match(/maxPriorityFeePerGas.*(?:at least|expected) (\d+)/i) || msg.match(/priority fee.*(?:at least|expected) (\d+)/i);
        const matchMaxFee = msg.match(/maxFeePerGas.*(?:at least|expected) (\d+)/i);
        if (matchPriority || matchMaxFee) {
          console.log(`[PaymasterClient] \u26A0\uFE0F  Fee Error: ${msg}. Retrying with higher fees...`);
          let newMaxPriority = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(2, 34)) : 0n;
          let newMaxFee = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(34)) : 0n;
          if (matchPriority && matchPriority[1]) {
            const required = BigInt(matchPriority[1]);
            if (required > newMaxPriority) {
              console.log(`   -> Bumping Priority Fee to ${required}`);
              const delta = required - newMaxPriority;
              newMaxPriority = required;
              newMaxFee += delta;
            }
          }
          if (matchMaxFee && matchMaxFee[1]) {
            const required = BigInt(matchMaxFee[1]);
            if (required > newMaxFee) {
              console.log(`   -> Bumping Max Fee to ${required}`);
              newMaxFee = required;
            }
          }
          if (newMaxFee < newMaxPriority)
            newMaxFee = newMaxPriority + 1n;
          userOp.gasFees = concat([
            pad(toHex(newMaxPriority), { size: 16 }),
            pad(toHex(newMaxFee), { size: 16 })
          ]);
          const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
          userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
          continue;
        }
        const matchPVG = msg.match(/preVerificationGas.*(?:at least|expected) (\d+)/i);
        if (matchPVG && matchPVG[1]) {
          const requiredPVG = BigInt(matchPVG[1]);
          const currentPVG = BigInt(userOp.preVerificationGas);
          if (requiredPVG > currentPVG) {
            console.log(`[PaymasterClient] \u26A0\uFE0F  PVG Error: ${msg}. Updating preVerificationGas...`);
            const bufferedPVG = requiredPVG * 105n / 100n;
            console.log(`   -> Updating PVG from ${currentPVG} to ${bufferedPVG} (inc. buffer)`);
            userOp.preVerificationGas = bufferedPVG;
            const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
            userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
            continue;
          }
        }
      }
      if (result.error && (result.error.code === -32601 || result.error.message?.includes("Method not found"))) {
        console.log("[PaymasterClient] SendUserOp failed (Method not found). Falling back to direct handleOps...");
        const caller = wallet.account?.address ? wallet.account.address : wallet.account;
        return await wallet.writeContract({
          address: entryPoint,
          abi: parseAbi(["function handleOps((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[], address) external"]),
          functionName: "handleOps",
          args: [[userOp], caller],
          chain: wallet.chain,
          account: wallet.account
        });
      }
      if (result.error)
        throw new Error(`Bundler Error: ${JSON.stringify(result.error)}`);
      console.log("[PaymasterClient] \u2705 Submitted via", bundlerType, "hash:", result.result);
      return result.result;
    }
    throw new Error("Failed to submit UserOp after retries");
  }
  /**
   * Helper to extract the actual Gas Token fee from a UserOperation receipt.
   * Looks for the 'PostOpProcessed' event emitted by the Paymaster.
   */
  static getFeeFromReceipt(receipt, paymasterAddress) {
    const TOPIC_POST_OP = "0x62544d7f48b11c32334310ebd306b47224fca220163218d4a7264322c52ae073";
    for (const log of receipt.logs) {
      if (log.address.toLowerCase() === paymasterAddress.toLowerCase() && log.topics[0] === TOPIC_POST_OP) {
        const data = log.data.replace("0x", "");
        if (data.length >= 192) {
          const actualGasCostWei = BigInt("0x" + data.slice(0, 64));
          const tokenCost = BigInt("0x" + data.slice(64, 128));
          return { tokenCost, actualGasCostWei };
        }
      }
    }
    return null;
  }
  /**
   * Get the fee for a specific transaction hash.
   * Fetches the receipt (no scanning required) and decodes the log.
   */
  static async getTransactionFee(publicClient, txHash, paymasterAddress) {
    const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
    return this.getFeeFromReceipt(receipt, paymasterAddress);
  }
  // ===========================================
  // 🛠️ Semantic CallData Builders (For DX)
  // ===========================================
  /**
   * Helper: Encode a standardized ERC-20 Transfer.
   * Returns the raw function data: `transfer(to, amount)`
   */
  static encodeTokenTransfer(recipient, amount) {
    return encodeFunctionData({
      abi: parseAbi(["function transfer(address to, uint256 amount) external returns (bool)"]),
      functionName: "transfer",
      args: [recipient, amount]
    });
  }
  /**
   * Helper: Encode a SimpleAccount execution.
   * Wraps the inner call into: `execute(target, value, data)`
   * This is the payload signed by the user.
   */
  static encodeExecution(target, value, data) {
    return encodeFunctionData({
      abi: parseAbi(["function execute(address dest, uint256 value, bytes func) external"]),
      functionName: "execute",
      args: [target, value, data]
    });
  }
  /**
   * More robust version of waitForUserOperationReceipt.
   * Catches timeouts and returns a cleaner result.
   */
  static async waitForUserOperation(bundlerClient, hash, timeout = 18e4) {
    try {
      return await bundlerClient.waitForUserOperationReceipt({ hash, timeout });
    } catch (error) {
      const errName = error.name || "";
      const errMsg = error.message || "";
      if (errName === "TimeoutError" || errName === "WaitForUserOperationReceiptTimeoutError" || /timed? out/i.test(errMsg)) {
        return { timeout: true, hash };
      }
      throw error;
    }
  }
};
var PaymasterOperator = class {
  /**
   * Update the cached ETH/USD price from Chainlink Oracle.
   * Must be called if cachedPrice is 0 (uninitialized).
   */
  static async updatePrice(wallet, address) {
    return wallet.writeContract({
      address,
      abi: parseAbi(["function updatePrice() external"]),
      functionName: "updatePrice",
      chain: wallet.chain
    });
  }
  /**
   * Set the token price (in 8 decimals, e.g., 1e8 = $1 USD).
   */
  static async setTokenPrice(wallet, address, token, priceUSD) {
    return wallet.writeContract({
      address,
      abi: parseAbi(["function setTokenPrice(address token, uint256 price) external"]),
      functionName: "setTokenPrice",
      args: [token, priceUSD],
      chain: wallet.chain
    });
  }
  static async getCachedPrice(publicClient, address) {
    const result = await publicClient.readContract({
      address,
      abi: [{
        name: "cachedPrice",
        type: "function",
        inputs: [],
        outputs: [
          { name: "price", type: "uint208" },
          { name: "updatedAt", type: "uint48" }
        ],
        stateMutability: "view"
      }],
      functionName: "cachedPrice"
    });
    return { price: result[0], updatedAt: result[1] };
  }
  static async getTokenPrice(publicClient, address, token) {
    return publicClient.readContract({
      address,
      abi: [{
        name: "tokenPrices",
        type: "function",
        inputs: [{ name: "token", type: "address" }],
        outputs: [{ name: "", type: "uint256" }],
        stateMutability: "view"
      }],
      functionName: "tokenPrices",
      args: [token]
    });
  }
  static async getDepositedBalance(publicClient, address, user, token) {
    return publicClient.readContract({
      address,
      abi: [{
        name: "balances",
        type: "function",
        inputs: [
          { name: "user", type: "address" },
          { name: "token", type: "address" }
        ],
        outputs: [{ name: "", type: "uint256" }],
        stateMutability: "view"
      }],
      functionName: "balances",
      args: [user, token]
    });
  }
  static async ensurePriceInitialized(wallet, publicClient, address) {
    const { price } = await this.getCachedPrice(publicClient, address);
    if (price === 0n) {
      await this.updatePrice(wallet, address);
      return true;
    }
    return false;
  }
  static async addStake(wallet, address, amount, unstakeDelaySec) {
    return wallet.writeContract({
      address,
      abi: parseAbi(["function addStake(uint32 unstakeDelaySec) external payable"]),
      functionName: "addStake",
      args: [unstakeDelaySec],
      value: amount,
      chain: wallet.chain
    });
  }
  static async addDeposit(wallet, address, amount) {
    return wallet.writeContract({
      address,
      abi: parseAbi(["function addDeposit() external payable"]),
      functionName: "addDeposit",
      value: amount,
      chain: wallet.chain
    });
  }
  static async addGasToken(wallet, address, token) {
    return wallet.writeContract({
      address,
      abi: ["function addGasToken(address token)"],
      functionName: "addGasToken",
      args: [token],
      chain: wallet.chain
    });
  }
  static async removeGasToken(wallet, address, token) {
    return wallet.writeContract({
      address,
      abi: ["function removeGasToken(address token)"],
      functionName: "removeGasToken",
      args: [token],
      chain: wallet.chain
    });
  }
  static async setServiceFeeRate(wallet, address, rate) {
    return wallet.writeContract({
      address,
      abi: ["function setServiceFeeRate(uint256 rate)"],
      functionName: "setServiceFeeRate",
      args: [rate],
      chain: wallet.chain
    });
  }
  static async setMaxGasCostCap(wallet, address, cap) {
    return wallet.writeContract({
      address,
      abi: ["function setMaxGasCostCap(uint256 cap)"],
      functionName: "setMaxGasCostCap",
      args: [cap],
      chain: wallet.chain
    });
  }
  static async withdrawPNT(wallet, address, to, token, amount) {
    return wallet.writeContract({
      address,
      abi: ["function withdrawPNT(address to, address token, uint256 amount)"],
      functionName: "withdrawPNT",
      args: [to, token, amount],
      chain: wallet.chain
    });
  }
  // --- Diagnostics & Automation ---
  static async checkGaslessReadiness(publicClient, entryPoint, paymasterAddress, user, token) {
    const issues = [];
    const depositInfo = await publicClient.readContract({
      address: entryPoint,
      abi: parseAbi(["function getDepositInfo(address account) external view returns (uint256 deposit, bool staked, uint256 stake, uint32 unstakeDelaySec, uint48 withdrawTime)"]),
      functionName: "getDepositInfo",
      args: [paymasterAddress]
    });
    if (depositInfo[2] < 50000000000000000n)
      issues.push("Paymaster stake in EntryPoint is less than 0.05 ETH");
    if (depositInfo[3] < 86400)
      issues.push("Paymaster unstake delay is less than 1 day");
    if (depositInfo[0] < 100000000000000000n)
      issues.push("Paymaster deposit in EntryPoint is less than 0.1 ETH");
    const ethPrice = await publicClient.readContract({
      address: paymasterAddress,
      abi: parseAbi(["function cachedPrice() external view returns (uint208 price, uint48 updatedAt)"]),
      functionName: "cachedPrice"
    }).catch(() => [0n, 0n]);
    if (ethPrice[0] === 0n)
      issues.push("Paymaster ETH/USD price not initialized");
    const [tokenPrice, userTokenBal, userPMDeposit] = await Promise.all([
      this.getTokenPrice(publicClient, paymasterAddress, token),
      publicClient.readContract({
        address: token,
        abi: parseAbi(["function balanceOf(address account) external view returns (uint256)"]),
        functionName: "balanceOf",
        args: [user]
      }),
      this.getDepositedBalance(publicClient, paymasterAddress, user, token)
    ]);
    if (tokenPrice === 0n)
      issues.push("Token price not set in Paymaster");
    if (userPMDeposit === 0n)
      issues.push("User has no deposit in Paymaster");
    return {
      isReady: issues.length === 0,
      issues,
      details: {
        paymasterStake: depositInfo[2],
        paymasterDeposit: depositInfo[0],
        ethUsdPrice: ethPrice.price,
        tokenSupported: true,
        tokenPrice,
        userTokenBalance: userTokenBal,
        userPaymasterDeposit: userPMDeposit
      }
    };
  }
  static async prepareGaslessEnvironment(operatorWallet, publicClient, entryPoint, paymasterAddress, token, options = {}) {
    const report = await this.checkGaslessReadiness(publicClient, entryPoint, paymasterAddress, operatorWallet.account.address, token);
    const results = [];
    if (report.details.paymasterStake < (options.minStake || 50000000000000000n)) {
      const hash = await this.addStake(operatorWallet, paymasterAddress, options.minStake || 50000000000000000n, 86400);
      await publicClient.waitForTransactionReceipt({ hash });
      results.push({ step: "Stake", hash, status: "Confirmed" });
    }
    if (report.details.paymasterDeposit < (options.minDeposit || 100000000000000000n)) {
      const hash = await this.addDeposit(operatorWallet, paymasterAddress, options.minDeposit || 300000000000000000n);
      await publicClient.waitForTransactionReceipt({ hash });
      results.push({ step: "Deposit", hash, status: "Confirmed" });
    }
    if (report.details.ethUsdPrice === 0n) {
      const hash = await this.updatePrice(operatorWallet, paymasterAddress);
      await publicClient.waitForTransactionReceipt({ hash });
      results.push({ step: "OraclePrice", hash, status: "Confirmed" });
    }
    if (report.details.tokenPrice === 0n) {
      try {
        const hash = await this.addGasToken(operatorWallet, paymasterAddress, token);
        await publicClient.waitForTransactionReceipt({ hash });
        results.push({ step: "AddGasToken", hash, status: "Confirmed" });
      } catch (e) {
      }
      if (options.tokenPriceUSD) {
        const hash = await this.setTokenPrice(operatorWallet, paymasterAddress, token, options.tokenPriceUSD);
        await publicClient.waitForTransactionReceipt({ hash });
        results.push({ step: "TokenPrice", hash, status: "Confirmed" });
      }
    }
    return results;
  }
};
var SuperPaymasterClient = class {
  /**
   * @private
   * Static utility class, should not be instantiated.
   */
  constructor() {
  }
  /**
   * Submit a gasless transaction using SuperPaymaster.
   * Automatically handles gas estimation with a smart efficiency buffer.
   */
  static async submitGaslessTransaction(client, wallet, aaAddress, entryPoint, bundlerUrl, config) {
    const callData = encodeFunctionData({
      abi: parseAbi(["function execute(address dest, uint256 value, bytes func) external"]),
      functionName: "execute",
      args: [
        config.token,
        0n,
        encodeFunctionData({
          abi: parseAbi(["function transfer(address to, uint256 amount) external returns (bool)"]),
          functionName: "transfer",
          args: [config.recipient, config.amount]
        })
      ]
    });
    console.log(`[SuperPaymasterClient] \u{1F3AF} Target Info:`);
    console.log(`   - Paymaster: ${config.paymasterAddress}`);
    console.log(`   - Token: ${config.token}`);
    console.log(`   - Operator: ${config.operator}`);
    console.log("[SuperPaymasterClient] \u2601\uFE0F  Estimating Gas usage...");
    const est = await PaymasterClient.estimateUserOperationGas(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
      operator: config.operator,
      factory: config.factory,
      factoryData: config.factoryData
    });
    console.log("[SuperPaymasterClient] \u2601\uFE0F  Bundler Estimates:", est);
    const tunedVGL = tuneGasLimit(est.verificationGasLimit, 35000n, 0.45);
    const bundlerEstimateVGL = est.paymasterVerificationGasLimit || 100000n;
    const tunedPMVerificationGas = tuneGasLimit(bundlerEstimateVGL, 60000n, 0.45);
    const _postOpBase = est.paymasterPostOpGasLimit + 100000n;
    const tunedPostOp = _postOpBase > 200000n ? _postOpBase : 200000n;
    console.log(`[SuperPaymasterClient] \u{1F527} Tuned Limits: VGL=${tunedVGL}, PMVGL=${tunedPMVerificationGas}, PostOp=${tunedPostOp}`);
    return PaymasterClient.submitGaslessUserOperation(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
      operator: config.operator,
      verificationGasLimit: tunedVGL,
      callGasLimit: est.callGasLimit,
      preVerificationGas: est.preVerificationGas,
      paymasterVerificationGasLimit: tunedPMVerificationGas,
      // EXPLICIT PM LIMIT
      paymasterPostOpGasLimit: tunedPostOp,
      autoEstimate: false,
      // We did it ourselves
      factory: config.factory,
      factoryData: config.factoryData
    });
  }
};

// ../paymaster/dist/PaymasterManager.js
var PaymasterManager = class _PaymasterManager {
  knownPaymasters;
  constructor(opts) {
    this.knownPaymasters = /* @__PURE__ */ new Map();
    if (opts?.knownPaymasters) {
      for (const [address, type] of Object.entries(opts.knownPaymasters)) {
        this.setKnownPaymaster(address, type);
      }
    }
  }
  /**
   * Register a known paymaster address → type mapping so that callers can
   * omit the explicit `type` and have it resolved from the address.
   */
  registerPaymaster(address, type) {
    this.setKnownPaymaster(address, type);
  }
  /**
   * Record an address → type mapping, throwing on a CONFLICTING re-registration.
   * Silently overwriting a v4 address with `super` (or vice-versa) would later
   * pack the wrong-length paymasterData for a `type`-less call, so a conflicting
   * re-registration is treated as a programmer error. Re-registering the SAME
   * type (including a case-variant of the address) is an idempotent no-op.
   */
  setKnownPaymaster(address, type) {
    const normalized = address.toLowerCase();
    const existing = this.knownPaymasters.get(normalized);
    if (existing && existing !== type) {
      throw new Error(`Paymaster ${address} is already registered as '${existing}'; refusing to re-register as '${type}'`);
    }
    this.knownPaymasters.set(normalized, type);
  }
  /**
   * Resolve a paymaster's type from a registered address. Returns undefined
   * if the address is not registered.
   */
  resolveType(address) {
    return this.knownPaymasters.get(address.toLowerCase());
  }
  /**
   * Build `paymasterAndData`, auto-selecting the correct byte layout for the
   * paymaster type. Dispatches to the existing per-type packers.
   */
  buildPaymasterData(params) {
    const type = params.type ?? this.resolveType(params.paymasterAddress);
    if (!type) {
      throw new Error(`PaymasterManager: cannot resolve paymaster type for ${params.paymasterAddress}. Pass an explicit \`type\` ('v4' | 'super') or register the address via registerPaymaster().`);
    }
    return _PaymasterManager.dispatch(type, params);
  }
  /**
   * Static helper: build `paymasterAndData` for an explicit type without an
   * instance. Useful when the caller already knows the type.
   */
  static buildPaymasterData(type, params) {
    return _PaymasterManager.dispatch(type, params);
  }
  static dispatch(type, params) {
    switch (type) {
      case "v4": {
        if (!params.token) {
          throw new Error("PaymasterManager: type 'v4' requires `token`.");
        }
        return buildPaymasterData(params.paymasterAddress, params.token, {
          validityWindow: params.validityWindow,
          verificationGasLimit: params.verificationGasLimit,
          postOpGasLimit: params.postOpGasLimit
        });
      }
      case "super": {
        if (!params.operator) {
          throw new Error("PaymasterManager: type 'super' requires `operator`.");
        }
        return buildSuperPaymasterData(params.paymasterAddress, params.operator, {
          verificationGasLimit: params.verificationGasLimit,
          postOpGasLimit: params.postOpGasLimit,
          maxRate: params.maxRate
        });
      }
      default: {
        const _never = type;
        throw new Error(`PaymasterManager: unsupported paymaster type '${_never}'.`);
      }
    }
  }
};

export { PaymasterClient, PaymasterManager, PaymasterOperator, SuperPaymasterAdminClient, SuperPaymasterClient, buildPaymasterData, buildSuperPaymasterData, checkEligibility, formatUserOpV07, getPaymasterV4Middleware, getSuperPaymasterMiddleware, getUserOpHashV07, tuneGasLimit };
//# sourceMappingURL=chunk-MPOMWT2J.js.map
//# sourceMappingURL=chunk-MPOMWT2J.js.map