import { BaseClient, xPNTsFactoryActions, registryActions, tokenActions, sbtActions, reputationActions } from './chunk-ZSSNU3UF.js';
import { parseEther, encodeAbiParameters, parseAbiParameters } from 'viem';

var CommunityClient = class extends BaseClient {
  sbtAddress;
  factoryAddress;
  reputationAddress;
  constructor(config) {
    super(config);
    this.sbtAddress = config.sbtAddress;
    this.factoryAddress = config.factoryAddress;
    this.reputationAddress = config.reputationAddress;
  }
  // ========================================
  // 1. 社区创建与配置
  // ========================================
  /**
   * Create a new Community Token (xPNTs) and register it.
   * Note: In the current architecture, creating a community often involves:
   * 1. Registering the ROLE_COMMUNITY on Registry (if not exists) -> usually manual or self-register
   * 2. Deploying a Token (xPNTs) via Factory
   * 3. Linking the Token to the Community in Registry
   */
  async createCommunityToken(params, options) {
    try {
      if (!this.factoryAddress) {
        throw new Error("Factory address required for this client");
      }
      const factory = xPNTsFactoryActions(this.factoryAddress);
      return await factory(this.client).createToken({
        name: params.name,
        symbol: params.tokenSymbol,
        community: this.getAddress(),
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  /**
   * Get Community Details (Decodes Role Metadata)
   * @param communityAddress - The address of the community manager (defaults to self)
   */
  async getCommunityInfo(communityAddress) {
    try {
      const target = communityAddress || this.getAddress();
      const registryAddr = this.requireRegistry();
      const registry = registryActions(registryAddr);
      const publicClient = this.getStartPublicClient();
      const API_ROLE_COMMUNITY = await registry(publicClient).ROLE_COMMUNITY();
      let metadataHex;
      try {
        metadataHex = await registry(publicClient).roleMetadata({
          roleId: API_ROLE_COMMUNITY,
          user: target
        });
      } catch (err) {
        const m = (err instanceof Error ? `${err.message} ${err.cause?.message ?? ""}` : String(err)).toLowerCase();
        const isContractGap = m.includes("revert") || m.includes("returned no data") || m.includes("does not exist") || m.includes("is not a function") || m.includes("no data was returned");
        if (!isContractGap)
          throw err;
        metadataHex = void 0;
      }
      if (!metadataHex || metadataHex === "0x") {
        let stakeAmount2 = 0n;
        try {
          stakeAmount2 = await registry(publicClient).roleStakes({ roleId: API_ROLE_COMMUNITY, user: target });
        } catch {
        }
        return { name: "", ensName: "", website: "", description: "", logoURI: "", stakeAmount: stakeAmount2 };
      }
      let dataToDecode = metadataHex;
      if (metadataHex.startsWith("0x0000000000000000000000000000000000000000000000000000000000000020")) {
        dataToDecode = `0x${metadataHex.slice(66)}`;
      }
      const { decodeAbiParameters, parseAbiParameters: parseAbiParameters2 } = await import('viem');
      const [name, ensName, website, description, logoURI, stakeAmount] = decodeAbiParameters(parseAbiParameters2("string, string, string, string, string, uint256"), dataToDecode);
      return {
        name,
        ensName,
        website,
        description,
        logoURI,
        stakeAmount
      };
    } catch (error) {
      throw error;
    }
  }
  /**
   * Register self as a Community Manager.
   * This method handles all necessary steps:
   * 1. Checks and approves GToken to GTokenStaking
   * 2. Encodes CommunityRoleData with provided parameters
   * 3. Calls registerRoleSelf on Registry
   *
   * @param params Community registration parameters
   * @param options Transaction options
   * @returns Transaction hash
   */
  async registerAsCommunity(params, options) {
    try {
      const registryAddr = this.requireRegistry();
      const registry = registryActions(registryAddr);
      const gTokenStakingAddr = this.requireGTokenStaking();
      const gTokenAddr = this.requireGToken();
      const roleCommunity = await registry(this.getStartPublicClient()).ROLE_COMMUNITY();
      const stakeAmount = params.stakeAmount || parseEther("30");
      const gToken = tokenActions();
      const allowance = await gToken(this.getStartPublicClient()).allowance({
        token: gTokenAddr,
        owner: this.getAddress(),
        spender: gTokenStakingAddr
      });
      if (allowance < stakeAmount) {
        const approveHash = await gToken(this.client).approve({
          token: gTokenAddr,
          spender: gTokenStakingAddr,
          amount: stakeAmount * BigInt(2),
          // Approve 2x for future use
          account: options?.account
        });
        await this.getStartPublicClient().waitForTransactionReceipt({ hash: approveHash });
      }
      const communityData = encodeAbiParameters(parseAbiParameters("string, string, string, string, string, uint256"), [
        params.name,
        params.ensName || "",
        params.website || "",
        params.description || `${params.name} Community`,
        params.logoURI || "",
        stakeAmount
      ]);
      return await registry(this.client).registerRoleSelf({
        roleId: roleCommunity,
        data: communityData,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  /**
   * One-click Setup: Register Community + Deploy Token
   * Orchestrates the complete community initialization flow.
   */
  async setupCommunity(params, options) {
    const hashes = [];
    let tokenAddress = "0x0000000000000000000000000000000000000000";
    const registry = registryActions(this.requireRegistry())(this.getStartPublicClient());
    const ROLE_COMMUNITY = await registry.ROLE_COMMUNITY();
    const hasRole = await registry.hasRole({ roleId: ROLE_COMMUNITY, user: this.getAddress() });
    if (!hasRole) {
      const hReg = await this.registerAsCommunity({
        name: params.name,
        ensName: params.website,
        // Mapping website to ENS param for now as per legacy behavior
        website: params.website,
        description: params.description,
        logoURI: params.logoURI,
        stakeAmount: params.stakeAmount
      }, options);
      hashes.push(hReg);
      await this.getStartPublicClient().waitForTransactionReceipt({ hash: hReg });
    }
    if (this.factoryAddress) {
      const factoryReader = xPNTsFactoryActions(this.factoryAddress)(this.getStartPublicClient());
      const existingToken = await factoryReader.getTokenAddress({ community: this.getAddress() });
      if (existingToken && existingToken !== "0x0000000000000000000000000000000000000000") {
        tokenAddress = existingToken;
      } else {
        const hToken = await this.createCommunityToken({
          name: params.tokenName,
          tokenSymbol: params.tokenSymbol,
          description: params.description
        }, options);
        hashes.push(hToken);
        await this.getStartPublicClient().waitForTransactionReceipt({ hash: hToken });
        for (let i = 0; i < 5; i++) {
          tokenAddress = await factoryReader.getTokenAddress({ community: this.getAddress() });
          if (tokenAddress && tokenAddress !== "0x0000000000000000000000000000000000000000")
            break;
          await new Promise((r) => setTimeout(r, 2e3));
        }
        if (!tokenAddress || tokenAddress === "0x0000000000000000000000000000000000000000") {
          console.warn(`Warning: Token address not found after 10s. Factory might be slow indexing.`);
        }
      }
    }
    return { tokenAddress, hashes };
  }
  // ========================================
  // 2. 成员管理
  // ========================================
  /**
   * Airdrop SBTs to users to make them members
   */
  async airdropSBT(users, roleId, options) {
    try {
      if (!this.sbtAddress)
        throw new Error("SBT address required for this client");
      const sbt = sbtActions(this.sbtAddress);
      if (users.length === 1) {
        const roleIdHex = `0x${roleId.toString(16).padStart(64, "0")}`;
        return await sbt(this.client).mintForRole({
          user: users[0],
          roleId: roleIdHex,
          roleData: "0x",
          account: options?.account
        });
      }
      throw new Error("Batch airdrop not fully implemented in L1 yet, use single user");
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 3. 信誉系统
  // ========================================
  async setReputationRule(ruleId, ruleConfig, options) {
    try {
      if (!this.reputationAddress)
        throw new Error("Reputation address required for this client");
      const reputation = reputationActions(this.reputationAddress);
      const ruleIdHex = `0x${ruleId.toString(16).padStart(64, "0")}`;
      return await reputation(this.client).setReputationRule({
        ruleId: ruleIdHex,
        rule: ruleConfig,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  // ========================================
  // 4. 管理功能
  // ========================================
  /**
   * Revoke membership (Burn SBT)
   */
  async revokeMembership(userAddr, options) {
    try {
      if (!this.sbtAddress)
        throw new Error("SBT address required for this client");
      const sbt = sbtActions(this.sbtAddress);
      return await sbt(this.client).burnSBT({
        user: userAddr,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
  /**
   * Transfer ownership of the Community Token
   */
  async transferCommunityTokenOwnership(tokenAddress, newOwner, options) {
    try {
      const token = tokenActions()(this.client);
      return await token.transferOwnership({
        token: tokenAddress,
        newOwner,
        account: options?.account
      });
    } catch (error) {
      throw error;
    }
  }
};
var UserLifecycle = class extends BaseClient {
  accountAddress;
  registryAddress;
  sbtAddress;
  gTokenAddress;
  gTokenStakingAddress;
  entryPointAddress;
  gaslessConfig;
  config;
  constructor(config) {
    super(config);
    this.config = config;
    this.accountAddress = config.accountAddress;
    this.registryAddress = config.registryAddress;
    this.sbtAddress = config.sbtAddress;
    this.gTokenAddress = config.gTokenAddress;
    this.gTokenStakingAddress = config.gTokenStakingAddress;
    this.entryPointAddress = config.entryPointAddress;
    this.gaslessConfig = config.gasless;
  }
  // ===========================================
  // 1. Onboarding Phase (Registration)
  // ===========================================
  /**
   * Check if user is eligible to join a community
   * @param community Address of the community
   */
  async checkEligibility(community) {
    const publicClient = this.getStartPublicClient();
    registryActions(this.registryAddress)(publicClient);
    return true;
  }
  /**
   * One-click Onboarding: Approve -> Stake -> Register -> Mint SBT
   * @param community Address of the community to join
   * @param stakeAmount Amount of GToken to stake (default 0.4 GT)
   */
  async onboard(community, stakeAmount = parseEther("0.4")) {
    try {
      const registry = registryActions(this.registryAddress)(this.getStartPublicClient());
      const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
        ...this.config,
        accountAddress: this.accountAddress,
        registryAddress: this.registryAddress,
        gTokenStakingAddress: this.gTokenStakingAddress,
        gTokenAddress: this.gTokenAddress,
        sbtAddress: this.sbtAddress
      }));
      const txHash = await userClient.registerAsEndUser(community, stakeAmount);
      let hasRole = false;
      for (let i = 0; i < 5; i++) {
        hasRole = await registry.hasRole({
          roleId: await registry.ROLE_ENDUSER(),
          user: this.accountAddress
        });
        if (hasRole)
          break;
        await new Promise((r) => setTimeout(r, 2e3));
      }
      return {
        success: hasRole,
        txHash
      };
    } catch (error) {
      console.error("Onboarding failed:", error);
      return { success: false };
    }
  }
  /**
   * Enable or update Gasless configuration
   */
  async enableGasless(config) {
    this.gaslessConfig = config;
  }
  // ===========================================
  // 2. Operational Phase (Execute & Interact)
  // ===========================================
  /**
   * Execute a transaction effectively using Gasless configuration if available
   */
  async executeGaslessTx(params) {
    if (!this.gaslessConfig) {
      throw new Error("Gasless configuration not enabled. Call enableGasless() first.");
    }
    const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
      ...this.config,
      accountAddress: this.accountAddress,
      // Pass minimal config needed for execution
      entryPointAddress: this.entryPointAddress,
      bundlerClient: this.config.bundlerClient
    }));
    const paymasterType = this.gaslessConfig.policy === "CREDIT" ? "Super" : "V4";
    const registry = registryActions(this.registryAddress)(this.client);
    const paymasterAddress = await registry.SUPER_PAYMASTER();
    return await userClient.executeGasless({
      target: params.target,
      value: params.value,
      data: params.data,
      paymaster: paymasterAddress,
      paymasterType,
      operator: params.operator
    });
  }
  async claimSBT(roleId, options) {
    const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
      ...this.config,
      accountAddress: this.accountAddress,
      sbtAddress: this.sbtAddress
    }));
    return await userClient.mintSBT(roleId, options);
  }
  // ===========================================
  // 3. Query Phase (Info & Stats)
  // ===========================================
  async getMyReputation() {
    const publicClient = this.getStartPublicClient();
    const registry = registryActions(this.registryAddress)(publicClient);
    const [score, creditLimit] = await Promise.all([
      registry.globalReputation({ user: this.accountAddress }),
      registry.getCreditLimit({ user: this.accountAddress })
    ]);
    return {
      score,
      level: 0n,
      // TODO: Add level calculation logic
      creditLimit
    };
  }
  async getCreditLimit() {
    const registry = registryActions(this.registryAddress)(this.client);
    return await registry.getCreditLimit({ user: this.accountAddress });
  }
  // ===========================================
  // 4. Exit Phase (Cleanup)
  // ===========================================
  async leaveCommunity(community, options) {
    const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
      ...this.config,
      accountAddress: this.accountAddress,
      sbtAddress: this.sbtAddress
    }));
    return await userClient.leaveCommunity(community, options);
  }
  async exitRole(roleId, options) {
    const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
      ...this.config,
      accountAddress: this.accountAddress,
      registryAddress: this.registryAddress
    }));
    return await userClient.exitRole(roleId, options);
  }
  async unstakeAll(roleId, options) {
    const userClient = await import('./UserClient-YUHCJJJL.js').then((m) => new m.UserClient({
      ...this.config,
      accountAddress: this.accountAddress,
      gTokenStakingAddress: this.gTokenStakingAddress
    }));
    return await userClient.unstakeFromRole(roleId, options);
  }
};

export { CommunityClient, UserLifecycle };
//# sourceMappingURL=chunk-YHM77LIP.js.map
//# sourceMappingURL=chunk-YHM77LIP.js.map