Encrypting Inputs
encryptInputs encrypts plaintext values into FHE ciphertexts that can be passed as inputs to a confidential smart contract transaction. Values must be encrypted before being passed on-chain to preserve confidentiality.
It returns an EncryptInputsBuilder which lets you configure the encryption and then call .execute() to run it.
The flow is as follows:
- Decide which plaintext value(s) you want to encrypt.
- Wrap each value with a typing helper (e.g.
Encryptable.uint32(…)) to construct typed encryptable inputs (seeEncryptable— typing inputs). - Call
client.encryptInputs([...]).execute()to produceEncryptedItemInputobjects (see Builder API). - Submit a transaction to your contract and pass the encrypted inputs as
InE*parameters (see Writing encrypted data to a contract).
Prerequisites
- Create and connect a client (see the client page).
encryptInputs(...) requires a connected client so the SDK can resolve chainId, account, and the underlying RPC clients.
- Know which encrypted type you want to encode each value as.
The type is chosen by which Encryptable.* factory you use (and must match the Solidity parameter type your contract expects, e.g. InEuint32 vs InEuint64).
Basic usage
await cofheClient.connect(publicClient, walletClient);
const encrypted = await cofheClient
.encryptInputs([
Encryptable.uint32(42n),
Encryptable.bool(true),
Encryptable.address('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'),
])
.execute();
const [eUint32, eBool, eAddress] = encrypted;The return type is a typed tuple that mirrors the array you pass in — each element is the corresponding Encrypted*Input type.
For the exact shape of each item, see EncryptedItemInput — the result type.
What encryptInputs returns
Running .execute() returns a typed tuple of EncryptedItemInput items that mirrors the array you passed to encryptInputs([...]).
Each item contains the handle (ctHash in the SDK type), the encrypted type (utype), the security zone, and a verifier signature authorizing that input.
For the exact shape, see EncryptedItemInput — the result type.
Builder API
.execute() — required, call last
Runs the encryption pipeline and returns the EncryptedItemInput[] tuple.
await cofheClient.connect(publicClient, walletClient);
const [encryptedAge, encryptedFlag] = await cofheClient
.encryptInputs([Encryptable.uint8(25n), Encryptable.bool(true)])
.execute(); .setAccount(address) — optional
Override the address that "owns" the encrypted input. Only that address will be allowed to use the encrypted inputs on-chain. Defaults to the account from the connected WalletClient.
await cofheClient.connect(publicClient, walletClient);
const encrypted = await cofheClient
.encryptInputs([Encryptable.uint64(10n)])
.setAccount('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')
.execute();.setChainId(chainId) — optional
Override the chain the encrypted input will be used on. Defaults to the chain ID of the connected PublicClient.
await cofheClient.connect(publicClient, walletClient);
const encrypted = await cofheClient
.encryptInputs([Encryptable.uint64(10n)])
.setChainId(11155111)
.execute();.setUseWorker(boolean) — optional
Overrides the useWorkers flag from CofheConfig for this specific call. When true (the default), ZK proof generation runs in a Web Worker to avoid blocking the main thread.
No-op in a node environment.
await cofheClient.connect(publicClient, walletClient);
const encrypted = await cofheClient
.encryptInputs([Encryptable.uint32(7n)])
.setUseWorker(false)
.execute();.onStep(callback) — optional
Registers a callback that fires at the start and end of each encryption step. Useful for building progress indicators.
The callback receives the current EncryptStep enum value and a context object with isStart, isEnd, and duration (milliseconds, only meaningful on isEnd).
await cofheClient.connect(publicClient, walletClient);
const encrypted = await cofheClient
.encryptInputs([Encryptable.uint64(10n)])
.onStep((step, ctx) => {
if (ctx?.isStart) console.log(`Starting: ${step}`);
if (ctx?.isEnd) console.log(`Done: ${step} (${ctx.duration}ms)`);
})
.execute();The EncryptStep enum values fired in order:
EncryptStep.InitTfhe; // 'initTfhe'
EncryptStep.FetchKeys; // 'fetchKeys'
EncryptStep.Pack; // 'pack'
EncryptStep.Prove; // 'prove'
EncryptStep.Verify; // 'verify'The encryption flow
Calling .execute() runs five sequential steps. You can observe them via the .onStep() callback.
| Step | Description |
|---|---|
InitTfhe | Lazy-initializes the TFHE WASM module (browser/Node). A no-op after the first call. |
FetchKeys | Fetches (or loads from cache) the FHE public key and CRS for the target chain. |
Pack | Packs the plaintext values into a ZK list ready for proving. |
Prove | Generates the ZK proof of knowledge (ZKPoK). Uses a Web Worker when available. |
Verify | Sends the proof to the CoFHE verifier. Returns signed EncryptedItemInput objects. |
Encryptable — typing inputs
Use the Encryptable factory to create the items you want to encrypt. Each factory function accepts the plaintext value and an optional securityZone.
| Factory | Data type | Solidity input param |
|---|---|---|
Encryptable.bool(value) | boolean | InEbool |
Encryptable.uint8(value) | bigint | string | InEuint8 |
Encryptable.uint16(value) | bigint | string | InEuint16 |
Encryptable.uint32(value) | bigint | string | InEuint32 |
Encryptable.uint64(value) | bigint | string | InEuint64 |
Encryptable.uint128(value) | bigint | string | InEuint128 |
Encryptable.address(value) | bigint | string | InEaddress |
You can also use the generic Encryptable.create(type, value) form:
Encryptable.create('uint32', 42n);
Encryptable.create('bool', false);
Encryptable.create('address', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');Bit limit: A single encryptInputs call may encrypt at most 2048 bits of plaintext in total. Exceeding this limit throws a ZkPackFailed error.
EncryptedItemInput — the result type
Each element of the returned array is an EncryptedItemInput:
type EncryptedItemInput = {
ctHash: bigint; // The handle registered with CoFHE
securityZone: number; // The security zone the input was encrypted under
utype: FheTypes; // The FHE type (Bool, Uint8, …, Uint160)
signature: string; // CoFHE verifier signature authorizing this input
};Pass these directly into a contract function that accepts InEuint* structs. The contract's CoFHE library validates the signature on-chain before operating on the ciphertext.
Common pitfalls
- Wrong
Encryptabletype:Encryptable.uint32(...)must match what your Solidity function expects (e.g.InEuint32). - Wrong account / chain: encrypted inputs are authorized for a specific
account + chainId. If you override these (or connect to the wrong network/wallet), your inputs may not be usable for the intended transaction. - Bit limit exceeded: a single call can encrypt at most 2048 bits of plaintext. Exceeding this throws
ZkPackFailed.