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.isAclPropagationError
Right after addDelegate lands on-chain, a delegated decrypt against the new delegate (decryption.delegatedDecryptValues on a Zama 3.6 ZamaSDK) can fail with "not propagated to the gateway yet" for a short window (about 10 blocks, longer behind a lagging RPC). isAclPropagationError(error), a standalone function exported from @tokenops/sdk/fhe-airdrop (not a client method), classifies that response so a caller can retry instead of treating it as a hard denial. Where the SDK maps the Zama error itself, the same failure arrives as the retryable AclNotPropagatedError (TOKENOPS_ACL_NOT_PROPAGATED), which isAclPropagationError also recognises.Airdrop v2 · Client@tokenops/sdk/fhe-airdrop
ComplianceManagerClient
One clone per campaign instance, created and initialized atomically by the factory inside createEcdsaAirdrop/createMerkleAirdrop - there is no observable deployed-but-not-wired state, and initialize is never exposed here. Two delegate slots: an irrevocable platform delegate set once at create (only if the factory's compliance policy was on for that creator), and client delegates this client adds and removes. The clone starts with one: complianceAdmin (the creator when left zero), seeded at create with never-expiring decrypt rights over the instance; revokeDelegate removes it.
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 { createComplianceManagerClient } from "@tokenops/sdk/fhe-airdrop";
const client = createComplianceManagerClient({
publicClient,
walletClient,
// address optional: resolved from publicClient.chain.id
});Methods
Write · 2
- Grant a client delegate permanent user-decryption rights over this instance. DELEGATION_ADMIN_ROLE; throws InvalidArgumentError on a zero address, an already-added delegate, or the platform delegate's own address.
client.addDelegate()React:useAddComplianceDelegate - Revoke a client delegate. DELEGATION_ADMIN_ROLE. Cannot add and revoke the same delegate in one block - the FHEVM ACL reverts AlreadyDelegatedOrRevokedInSameBlock opaquely, with no decodable selector.
client.revokeDelegate()React:useRevokeComplianceDelegate
Read · 4
- The one airdrop instance this clone serves. Bundled with complianceDelegate and clientDelegates in useComplianceInfo.
client.airdrop()React:useComplianceInfo - The platform delegate, or the zero address meaning the factory's compliance policy was off at create time. Irrevocable once set - no method ever clears it.
client.complianceDelegate()React:useComplianceInfo - Every current client delegate, excluding the platform delegate.
client.clientDelegates()React:useComplianceInfo - Authoritative check covering BOTH delegate slots - reads the ACL expiration directly rather than reconstructing state from addDelegate/revokeDelegate events.
client.isActiveDelegate()React:useIsActiveDelegate
Roles · RBAC · 10
- Role bytes32 for addDelegate / revokeDelegate. Bundled with DEFAULT_ADMIN_ROLE in useComplianceRoleConstants.
client.DELEGATION_ADMIN_ROLE()React:useComplianceRoleConstants - Administers DELEGATION_ADMIN_ROLE. No last-admin floor here - emptying it permanently freezes the delegate set.
client.DEFAULT_ADMIN_ROLE()React:useComplianceRoleConstants - Check whether an address holds a given role on this clone.
client.hasRole()React:useComplianceHasRole client.getRoleAdmin()Which role administers a given role on this clone. Always DEFAULT_ADMIN_ROLE for both roles.- Number of holders of a role. Bundled with enumeration in useComplianceRoleMembers.
client.getRoleMemberCount()React:useComplianceRoleMembers - One role holder by enumeration index.
client.getRoleMember()React:useComplianceRoleMembers - Every current holder of a role on this clone.
client.getRoleMembers()React:useComplianceRoleMembers - Grant a role on this clone.
client.grantRole()React:useComplianceGrantRole - Revoke a role from a holder on this clone.
client.revokeRole()React:useComplianceRevokeRole - Give up a role yourself - takes no holder argument; OpenZeppelin v5 requires the caller to confirm itself.
client.renounceRole()React:useComplianceRenounceRole