2.0 RC docsView 1.x docs
v2.0.0-rc.1 release candidate
The API is frozen and later candidates carry fixes only, except the receipt-free and Safe create surface of /fhe-airdrop, which is @beta. Published on the next dist-tag; latest stays on 1.6.0 until 2.0.0.
Airdrop v2 · Client@tokenops/sdk/fhe-airdrop

ConfidentialAirdropFactoryClient

One factory serves both claim variants. createEcdsaAirdrop/createMerkleAirdrop take a CommonAirdropParams (token, startTime, endTime, canExtendClaimWindow, unwrappable, complianceAdmin, maxAcceptedGasFee) with no admin field - the factory injects admin = msg.sender, and every create returns { hash, airdrop, complianceManager, managerImplementation, complianceDelegate }. Every create commits to the instance address, the compliance-manager implementation and the compliance delegate, and the factory reverts before consuming the salt if any of them drifted. Everything below setup and prediction is protocol-operator surface: fee policy, implementation pointers, compliance-wiring policy, and upgradeability policy, none of it existed on the v1 factory. The admin setters are positional and take an optional account then gas; gasHeadroomPercent on the config pads every write. The factory address resolves from DEPLOYED_ADDRESSES on mainnet and Sepolia.

Construct

Headless TS — non-React consumers (Node, Vite, server workers). React hosts use the per-hook surface; same method names, lazy encryptor.

@tokenops/sdk/fhe-airdrop
ts
import { createConfidentialAirdropFactoryClient } from "@tokenops/sdk/fhe-airdrop";

const client = createConfidentialAirdropFactoryClient({
  publicClient,
  walletClient,
  // address optional: resolved from publicClient.chain.id
});

Methods

Setup · 7

Introspection · 5

  • client.predictEcdsaAirdropAddress()CREATE2 address an ECDSA create would deploy to, given the same params, mode, deployer, and userSalt.
  • client.predictMerkleAirdropAddress()CREATE2 address a Merkle create would deploy to.
  • client.getEcdsaInitCodeHash()Init-code hash behind an ECDSA prediction - read before and after a campaign build to detect an implementation swap mid-flight.
  • client.getMerkleInitCodeHash()Init-code hash behind a Merkle prediction, same drift-check role.
  • client.predictComplianceManagerClone()Free function from @tokenops/sdk/fhe-airdrop/advanced: the compliance clone address the factory deploys for { factory, managerImplementation, airdrop }.

Configure · 15

  • client.setFeeCollector()Set the account seeded with FEE_COLLECTOR_ROLE on instances created after this call. Existing instances keep their collectors, and the fee goes to whatever recipient withdrawGasFee names. FEE_MANAGER_ROLE.
  • client.setDefaultGasFee()Set the chain-wide default per-claim ETH fee new instances are created with. FEE_MANAGER_ROLE.
  • client.setCustomFee()Override the default fee for one creator. FEE_MANAGER_ROLE.
  • client.disableCustomFee()Clear a creator's fee override, falling back to the default. FEE_MANAGER_ROLE.
  • client.setMaxGasFee()Set the ceiling every configurable fee and every create-time resolved fee must sit under. DEFAULT_ADMIN_ROLE, deliberately not FEE_MANAGER_ROLE - the fee manager moves fees only inside a range the admin owns. Lowering it below a configured fee succeeds and does not rewrite that fee: the stale fee stays in storage and the next create reverts GasFeeExceedsMaximum (InvalidArgumentError on gasFee), so lower the configured fees in the same operation and read them back.
  • client.setEcdsaImplementation()Point future ECDSA clones at a new implementation. IMPL_MANAGER_ROLE.
  • client.setMerkleImplementation()Point future Merkle clones at a new implementation. IMPL_MANAGER_ROLE.
  • client.setComplianceManagerImpl()Point future per-instance compliance clones at a new implementation. COMPLIANCE_WIRING_ROLE.
  • client.setComplianceDelegate()Rotate the platform delegate wired into future instances' compliance clones. The constructor already seeds a non-zero delegate with compliance ON, so there is no post-deploy wiring step; this rotates but can never clear it. COMPLIANCE_WIRING_ROLE.
  • client.setDefaultDelegateToCompliance()Chain-wide default for whether new instances wire in the platform delegate. COMPLIANCE_WIRING_ROLE.
  • client.setCompliancePolicy()Override the default delegate-to-compliance policy for one creator. COMPLIANCE_WIRING_ROLE.
  • client.clearCompliancePolicy()Clear a creator's compliance-policy override, falling back to the default. COMPLIANCE_WIRING_ROLE.
  • client.setDefaultUpgradeable()Chain-wide default for whether creators may deploy mode: "uups" instances. UPGRADE_MANAGER_ROLE.
  • client.setUpgradeabilityPolicy()Override the UUPS-allowed policy for one creator. UPGRADE_MANAGER_ROLE.
  • client.clearUpgradeabilityPolicy()Clear a creator's upgradeability override, falling back to the default. UPGRADE_MANAGER_ROLE.

Read · 20

Roles · RBAC · 13

  • client.FEE_MANAGER_ROLE()Role bytes32 for fee administration. Bundled with the other four factory role constants.
  • client.IMPL_MANAGER_ROLE()Role bytes32 for implementation-pointer administration.
  • client.COMPLIANCE_WIRING_ROLE()Role bytes32 for compliance-wiring policy administration.
  • client.UPGRADE_MANAGER_ROLE()Role bytes32 for upgradeability-policy administration.
  • client.DEFAULT_ADMIN_ROLE()OpenZeppelin's default admin role - administers all four operational roles above.
  • client.hasRole()Check whether an address holds a given factory role.
  • client.getRoleAdmin()Which role administers a given role. Always DEFAULT_ADMIN_ROLE for all five factory roles - the factory has no self-administered role.
  • client.getRoleMemberCount()Number of holders of a role. Bundled with member enumeration in useFactoryRoleMembers.
  • client.getRoleMember()One role holder by enumeration index.
  • client.getRoleMembers()Every current holder of a role - the only way to answer who holds this, no roleHolders() view exists.
  • client.grantRole()Grant a factory role to an address. DEFAULT_ADMIN_ROLE.
  • client.revokeRole()Revoke a factory role from an address. The factory floors DEFAULT_ADMIN_ROLE at one member: revoking the sole holder reverts LastAdmin. Hand over by granting the successor first.
  • client.renounceRole()Give up a role yourself. The same LastAdmin floor applies: the sole DEFAULT_ADMIN_ROLE holder cannot renounce, so grant the successor first, then renounce.