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.Encrypted readcustom hookencrypted handle Curated
useDecryptedHandle
Subscribe to a single encrypted handle and reactively decrypt via the connected wallet.
Import
@tokenops/sdk/fhe/reactReturn
(see signature — custom result type)Lifecycle
Encrypted readDescription
Decrypt a single EncryptedHandle returned by an FHE-product encrypted
view (e.g. EncryptedViewResult.handle from
ConfidentialVestingManagerClient.getClaimableAmount()).
import { useZamaSDK } from "@zama-fhe/react-sdk";
import { useDecryptedHandle } from "@tokenops/sdk/fhe/react";
import { useConnection } from "wagmi"; // wagmi v2: useAccount
const sdk = useZamaSDK();
const { address } = useConnection();
const { status, value } = useDecryptedHandle({
handle: viewResult?.handle,
contractAddress: managerAddress,
userDecryptor: () => sdk.decryption,
account: address,
});Numeric results (bigint, or number for euint8/16/32) resolve to a bigint.
A missing entry or any other value type yields a TokenOpsValidationError;
decryptor failures are mapped to typed TokenOpsSdkErrors (for example
UserDecryptNotAllowedError when the signer has no ACL grant).
Signature
@tokenops/sdk/fhe/react
ts
function useDecryptedHandle(opts: UseDecryptedHandleOptions): UseDecryptedHandleResult;Parameters
Shape of the options object passed to the hook itself.
| Property | Type | Description |
|---|---|---|
| handle | EncryptedHandle | undefined | The encrypted handle to decrypt. undefined keeps the hook in idle state, e.g. while the query producing the handle has not resolved. |
| contractAddress | Address | undefined | The contract that granted ACL access to the handle. Decryption is checked against the (handle, contractAddress, signer) triple, so the wrong contract makes the decryption fail. |
| userDecryptor | UserDecryptorSource | undefined | Lazy or eager decryptor. Recommended in React: const sdk = useZamaSDK(); then userDecryptor: () => sdk.decryption. The lazy form is called per decryption, so it always sees the live SDK. A lazy source that resolves to undefined (an SDK still initializing) leaves the hook in error; it decrypts once the source resolves. The hook compares the resolved decryptor by identity on every render. When it becomes a different object, for example a new ZamaSDK for another signer, the shown value is dropped at once and the handle is decrypted again with the new decryptor. Pass a stable decryptor: sdk.decryption and () => sdk.decryption resolve to the same object across renders; memoize anything else. A decryptor that resolves to a new object on consecutive renders (an object literal built inline) makes a swap undetectable, so the hook fails closed: it shows no value and reports error with a TokenOpsValidationError instead of decrypting. It decrypts again once the decryptor keeps its identity for a render. |
| account | Address | undefined | The connected signer's address, for example wagmi's useConnection().address (v3) or useAccount().address (v2). Pass it whenever the wallet can change: a ZamaSDK keeps the same decryption object across account switches, so without it a switch that leaves handle and contractAddress as they were keeps showing the previous account's clear value. A change drops that value, aborts an in-flight decryption, and decrypts again as the new account, which fails if that account has no ACL grant. Replacing the decryptor itself (a new ZamaSDK) is detected without it. |
| enabled | boolean | undefined | Skip the decrypt (defaults to false). Useful to render an "Encrypted" placeholder until the user opts in. |
Example
components/useDecryptedHandleExample.tsx
tsx
"use client";
import { useDecryptedHandle } from "@tokenops/sdk/fhe/react";
export function Example() {
const read = useDecryptedHandle(/* args */);
// Encrypted view: read.mutate() submits a tx that calls FHE.allow,
// so the connected wallet gains ACL on the returned handle.
// Pair read.data.handle with useDecryptedHandle (from @tokenops/sdk/fhe/react)
// to user-decrypt via the Zama relayer.
}Auto-generated from the hook's shape (the SDK doesn't carry a TSDoc @example here yet).