import { BaseClient, entryPointActions, accountActions, sbtActions, tokenActions, stakingActions, registryActions } from './chunk-ZSSNU3UF.js';
import { encodeFunctionData } from 'viem';
import { bundlerActions } from 'viem/account-abstraction';

var UserClient = class extends BaseClient {
  accountAddress;
  sbtAddress;
  entryPointAddress;
  gTokenStakingAddress;
  registryAddress;
  gTokenAddress;
  bundlerClient;
  constructor(config) {
    super(config);
    this.bundlerClient = config.bundlerClient;
    this.accountAddress = config.accountAddress;
    this.sbtAddress = config.sbtAddress;
    this.entryPointAddress = config.entryPointAddress;
    this.gTokenStakingAddress = config.gTokenStakingAddress;
    this.registryAddress = config.registryAddress;
    this.gTokenAddress = config.gTokenAddress;
  }
  /**
   * Deploy a new Smart Account (Supports multiple factory types)
   * Static helper to facilitate onboarding before instantiating the UserClient.
   *
   * @param client - WalletClient to sign the deployment transaction
   * @param params - Deployment parameters
   * @returns Object containing the deployed account address and transaction hash
   */
  static async deployAccount(client, params) {
    const { accountFactoryActions, SimpleAccountFactoryABI } = await import('./index.node-55LOPHNQ.js');
    let abi = params.customAbi || (SimpleAccountFactoryABI?.abi || SimpleAccountFactoryABI);
    const factoryAddr = params.factoryAddress || "0x9406Cc6185a346906296840746125a0E44976454";
    const salt = params.salt || 0n;
    const readClient = params.publicClient || client;
    const factoryRead = accountFactoryActions(factoryAddr, abi)(readClient);
    const factoryWrite = accountFactoryActions(factoryAddr, abi)(client);
    const accountAddress = await factoryRead.getAddress({
      owner: params.owner,
      salt
    });
    try {
      const hash = await factoryWrite.createAccount({
        owner: params.owner,
        salt,
        account: client.account
      });
      return { accountAddress, hash };
    } catch (error) {
      const messageParts = [
        error?.shortMessage,
        error?.message,
        error?.details,
        error?.cause?.shortMessage,
        error?.cause?.message,
        error?.cause?.details,
        error?.cause?.cause?.shortMessage,
        error?.cause?.cause?.message
      ].filter(Boolean);
      const message = messageParts.join(" ");
      if (message.includes("gas required exceeds allowance") || message.includes("intrinsic gas too low")) {
        const data = encodeFunctionData({
          abi,
          functionName: "createAccount",
          args: [params.owner, salt]
        });
        const hash = await client.sendTransaction({
          to: factoryAddr,
          data,
          gas: 2000000n,
          account: client.account
        });
        return { accountAddress, hash };
      }
      throw error;
    }
  }
  // ========================================
  // 1. 账户基本操作 (基于 L1 simpleAccountActions)
  // ========================================
  /**
   * Get the nonce of the account from EntryPoint (more reliable for 4337)
   */
  async getNonce(key = 0n) {
    try {
      if (!this.entryPointAddress) {
        throw new Error("EntryPoint address required for this client");
      }
      const entryPoint = entryPointActions(this.entryPointAddress);
      return await entryPoint(this.getStartPublicClient()).getNonce({
        sender: this.accountAddress,
        key
      });
    } catch (error) {
      throw error;
    }
  }
  /**
   * Get the owner of the AA account
   */
  async getOwner() {
    try {
      const account = accountActions(this.accountAddress);
      return await account(this.getStartPublicClient()).owner();
    } catch (error) {
      throw error;
    }
  }
  /**
   * Execute a transaction from the AA account
   */
  async execute(target, value, data, options) {
    try {
      const account = accountActions(this.accountAddress);
      return await account(this.client).execute({
        dest: target,
        value,
        func: data,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  /**
   * Execute a batch of transactions
   */
  async executeBatch(targets, values, datas, options) {
    try {
      const account = accountActions(this.accountAddress);
      return await account(this.client).executeBatch({
        dest: targets,
        value: values,
        func: datas,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // identity 与 SBT (基于 L1 sbtActions)
  // ========================================
  /**
   * Get user's SBT balance
   */
  async getSBTBalance() {
    try {
      if (!this.sbtAddress)
        throw new Error("SBT address required for this client");
      const sbt = sbtActions(this.sbtAddress);
      return await sbt(this.getStartPublicClient()).balanceOf({
        owner: this.accountAddress
      });
    } catch (error) {
      throw error;
    }
  }
  async mintSBT(roleId, options) {
    try {
      if (!this.sbtAddress)
        throw new Error("SBT address required for this client");
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "mintForRole", type: "function", inputs: [{ name: "user", type: "address" }, { name: "roleId", type: "bytes32" }, { name: "roleData", type: "bytes" }], outputs: [{ type: "uint256" }] }],
        functionName: "mintForRole",
        args: [this.accountAddress, roleId, "0x"]
      });
      return await this.execute(this.sbtAddress, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 3. 资产管理 (基于 L1 tokenActions)
  // ========================================
  async transferToken(token, to, amount, options) {
    try {
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "transfer", type: "function", inputs: [{ name: "to", type: "address" }, { name: "amount", type: "uint256" }], outputs: [{ type: "bool" }] }],
        functionName: "transfer",
        args: [to, amount]
      });
      return await this.execute(token, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  /**
   * Get Token Balance
   */
  async getTokenBalance(token) {
    try {
      const tokens = tokenActions()(this.getStartPublicClient());
      return await tokens.balanceOf({
        token,
        account: this.accountAddress
      });
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 4. 委托与质押 (Delegation & Staking)
  // ========================================
  async stakeForRole(roleId, amount, options) {
    try {
      if (!this.gTokenStakingAddress)
        throw new Error("GTokenStaking address required for this client");
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "lockStake", type: "function", inputs: [{ name: "user", type: "address" }, { name: "roleId", type: "bytes32" }, { name: "stakeAmount", type: "uint256" }, { name: "entryBurn", type: "uint256" }, { name: "payer", type: "address" }], outputs: [] }],
        functionName: "lockStake",
        args: [this.accountAddress, roleId, amount, 0n, this.accountAddress]
      });
      return await this.execute(this.gTokenStakingAddress, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  async unstakeFromRole(roleId, options) {
    try {
      if (!this.gTokenStakingAddress)
        throw new Error("GTokenStaking address required for this client");
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "unlockAndTransfer", type: "function", inputs: [{ name: "user", type: "address" }, { name: "roleId", type: "bytes32" }], outputs: [{ name: "netAmount", type: "uint256" }] }],
        functionName: "unlockAndTransfer",
        args: [this.accountAddress, roleId]
      });
      return await this.execute(this.gTokenStakingAddress, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  /**
   * Get staked balance for a specific role
   */
  async getStakedBalance(roleId) {
    try {
      if (!this.gTokenStakingAddress)
        throw new Error("GTokenStaking address required for this client");
      const staking = stakingActions(this.gTokenStakingAddress);
      return await staking(this.getStartPublicClient()).getLockedStake({
        user: this.accountAddress,
        roleId
      });
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 5. 生命周期管理 (Lifecycle)
  // ========================================
  async exitRole(roleId, options) {
    try {
      if (!this.registryAddress)
        throw new Error("Registry address required for this client");
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "exitRole", type: "function", inputs: [{ name: "roleId", type: "bytes32" }], outputs: [] }],
        functionName: "exitRole",
        args: [roleId]
      });
      return await this.execute(this.registryAddress, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  async leaveCommunity(community, options) {
    try {
      if (!this.sbtAddress)
        throw new Error("SBT address required for this client");
      const { encodeFunctionData: encodeFunctionData2 } = await import('viem');
      const data = encodeFunctionData2({
        abi: [{ name: "leaveCommunity", type: "function", inputs: [{ name: "comm", type: "address" }], outputs: [] }],
        functionName: "leaveCommunity",
        args: [community]
      });
      return await this.execute(this.sbtAddress, 0n, data, options);
    } catch (error) {
      throw error;
    }
  }
  /**
   * Register as EndUser (One-click: Approve + Register)
   * Handles GToken approval to Staking contract and Role registration.
   */
  async registerAsEndUser(communityAddress, stakeAmount, options) {
    try {
      if (!this.registryAddress)
        throw new Error("Registry address required for this client");
      if (!this.gTokenStakingAddress)
        throw new Error("GTokenStaking address required for this client");
      if (!this.gTokenAddress)
        throw new Error("GToken address required for this client");
      const { encodeAbiParameters, keccak256, toBytes, parseEther } = await import('viem');
      const ROLE_ENDUSER = keccak256(toBytes("ENDUSER"));
      const registry = registryActions(this.registryAddress);
      const publicClient = this.getStartPublicClient();
      const tokens = tokenActions()(publicClient);
      const allowance = await tokens.allowance({
        token: this.gTokenAddress,
        owner: this.accountAddress,
        spender: this.gTokenStakingAddress
      });
      console.log(`   \u{1F50D} Debug Allowance: Account=${this.accountAddress}, Allowance=${allowance}, Needed=${stakeAmount}`);
      const txs = [];
      if (allowance < stakeAmount) {
        const approveData = encodeFunctionData({
          abi: [{ name: "approve", type: "function", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }], stateMutability: "nonpayable" }],
          functionName: "approve",
          args: [this.gTokenStakingAddress, parseEther("1000")]
        });
        txs.push({ target: this.gTokenAddress, value: 0n, data: approveData });
      }
      const roleData = encodeAbiParameters([
        { type: "address", name: "account" },
        { type: "address", name: "community" },
        { type: "string", name: "avatarURI" },
        { type: "string", name: "ensName" },
        { type: "uint256", name: "stakeAmount" }
      ], [
        this.accountAddress,
        communityAddress,
        "",
        "",
        stakeAmount
      ]);
      const registerData = encodeFunctionData({
        abi: [{ name: "registerRoleSelf", type: "function", inputs: [{ type: "bytes32" }, { type: "bytes" }], outputs: [{ type: "uint256" }], stateMutability: "nonpayable" }],
        functionName: "registerRoleSelf",
        args: [ROLE_ENDUSER, roleData]
      });
      txs.push({ target: this.registryAddress, value: 0n, data: registerData });
      console.log(`   \u{1F50D} Debug Onboard: Community=${communityAddress}, AA=${this.accountAddress}, Stake=${stakeAmount}`);
      console.log(`   \u{1F50D} Debug Batch: Txs=${txs.length}, Targets=${txs.map((t) => t.target)}`);
      const hashes = [];
      for (const tx of txs) {
        const h = await this.execute(tx.target, tx.value, tx.data, options);
        hashes.push(h);
        await this.getStartPublicClient().waitForTransactionReceipt({ hash: h });
      }
      return hashes[hashes.length - 1];
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 6. Gasless Execution (Advanced)
  // ========================================
  /**
   * Execute a transaction with Gasless Sponsorship
   */
  async executeGasless(params, options) {
    try {
      const client = this.bundlerClient ? this.bundlerClient.extend(bundlerActions) : this.client.extend(bundlerActions);
      const ep = this.requireEntryPoint();
      const callData = encodeFunctionData({
        abi: [{ name: "execute", type: "function", inputs: [{ name: "dest", type: "address" }, { name: "value", type: "uint256" }, { name: "func", type: "bytes" }], outputs: [] }],
        functionName: "execute",
        args: [params.target, params.value, params.data]
      });
      const { PaymasterClient: SDKPaymasterClient } = await import('./dist-GHTBO7CD.js');
      let verificationGasLimit;
      let paymasterVerificationGasLimit;
      let paymasterPostOpGasLimit;
      let autoEstimate = true;
      if (params.paymasterType === "Super") {
        const { tuneGasLimit } = await import('./dist-GHTBO7CD.js');
        const est = await SDKPaymasterClient.estimateUserOperationGas(
          this.client,
          this.client,
          this.accountAddress,
          ep,
          params.paymaster,
          params.target,
          // placeholder
          this.bundlerClient?.transport?.url || this.client.transport.url || "",
          callData,
          {
            operator: params.operator,
            factory: void 0,
            factoryData: void 0
          }
        );
        const bundlerEstimate = est.paymasterVerificationGasLimit || 100000n;
        paymasterVerificationGasLimit = tuneGasLimit(bundlerEstimate, 60000n, 0.45);
        const SAFETY_PAD = 80000n;
        verificationGasLimit = est.verificationGasLimit + SAFETY_PAD;
        const _postOpBase = est.paymasterPostOpGasLimit + 100000n;
        paymasterPostOpGasLimit = _postOpBase > 200000n ? _postOpBase : 200000n;
        autoEstimate = false;
      }
      const txHash = await SDKPaymasterClient.submitGaslessUserOperation(
        this.client,
        this.client,
        // WalletClient acts as signer
        this.accountAddress,
        ep,
        params.paymaster,
        params.target,
        // placeholder for token if V4
        this.bundlerClient?.transport?.url || this.client.transport.url || "",
        callData,
        {
          operator: params.operator,
          autoEstimate,
          verificationGasLimit,
          paymasterVerificationGasLimit,
          paymasterPostOpGasLimit
        }
      );
      return txHash;
    } catch (error) {
      console.error("   \u274C executeGasless Error:", error.message);
      throw error;
    }
  }
};

export { UserClient };
//# sourceMappingURL=chunk-DI3E6PMI.js.map
//# sourceMappingURL=chunk-DI3E6PMI.js.map