Token
Read/write interface for an ERC-7984 confidential token — balances, transfers, operator approvals.
Token is the high-level ERC-20-style interface for an ERC-7984 confidential token. It hides FHE complexity (encryption, decryption, EIP-712 signing) behind familiar methods.
For ERC-7984 ERC-20 wrappers (shield / unshield / allowance), use WrappedToken instead — it extends Token with wrapper-specific operations.
Import
Created via sdk.createToken():
import { ZamaSDK } from "@zama-fhe/sdk";
const sdk = new ZamaSDK(config); // config from createConfig()
const token = sdk.createToken("0xConfidentialToken");
const balance = await token.balanceOf(ownerAddress);
await token.confidentialTransfer("0xRecipient", 500n);For shield / unshield, create a WrappedToken via sdk.createWrappedToken("0xWrapper") — see WrappedToken.
Methods
balanceOf
(owner: Address) => Promise<bigint>
Returns the decrypted confidential balance. The first call prompts a wallet signature to create FHE permits; subsequent calls use cached permits silently. Decrypted values are cached in storage automatically.
confidentialBalanceOf
(owner: Address) => Promise<EncryptedValue>
Returns the raw encrypted value without decrypting. Use with isEncryptedValueZero() or pass to sdk.decryption.decryptValues() for decryption.
decryptBalanceAs
({ delegatorAddress, accountAddress? }) => Promise<bigint>
Decrypt a delegator's balance using delegated credentials. The connected wallet must hold an active delegation from delegatorAddress covering this token's contract.
confidentialTransfer
(to: Address, amount: bigint, options?: TransferOptions) => Promise<TransactionResult>
Transfers encrypted tokens. The amount is encrypted before hitting the chain.
By default, the SDK validates the confidential balance before submitting. If credentials are cached, it auto-decrypts silently. Set skipBalanceCheck: true to bypass (e.g. for smart wallets that cannot produce EIP-712 signatures).
skipBalanceCheck
boolean
false
Skip balance validation
onEncryptComplete
() => void
—
Fired after FHE encryption completes
onTransferSubmitted
(txHash) => void
—
Fired after transfer tx submitted
Throws:
InsufficientConfidentialBalanceError— if the confidential balance is less thanamount(exposesrequested,available,token)BalanceCheckUnavailableError— if balance validation is required but decryption is not possible (no stored permits). Callsdk.permits.grantPermit([token.address])first or useskipBalanceCheck: true
confidentialTransferFrom
(from: Address, to: Address, amount: bigint, callbacks?: TransferCallbacks) => Promise<TransactionResult>
Operator transfer on behalf of an address that has approved you.
setOperator
(operator: Address, until?: number) => Promise<{ txHash: Hex; receipt: TransactionReceipt }>
Approves another address to operate on your confidential tokens (e.g. a DEX or multisig). Default duration: 1 hour.
isOperator
(holder: Address, spender: Address) => Promise<boolean>
Checks whether a spender is currently an approved operator for a given holder.
name / symbol / decimals
ERC-20-style metadata reads. Each returns a Promise of the value.
isConfidential / isWrapper
ERC-165 introspection.
Token.batchBalancesOf (static)
(tokens: Token[], owner: Address) => Promise<BatchBalancesResult>
Decrypts multiple balances in one batch. Balances that decrypt successfully land in results, per-token failures in errors. A failure that affects the whole session (rejected signature, RPC rate limit, revoked KMS context) rejects the call instead.
Token.batchDecryptBalancesAs (static)
(tokens: Token[], options: BatchDecryptAsOptions) => Promise<Map<Address, bigint>>
Batch delegated decryption.
Related
ZamaSDK — creates
TokenviacreateToken()WrappedToken — extends
Tokenwith shield / unshield / allowance / wrapper operations
Last updated