> For the complete documentation index, see [llms.txt](https://docs.zama.org/protocol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zama.org/protocol/sdk/api-references/react/query-keys.md).

# Query keys

Reference for the zamaQueryKeys factory used for manual React Query cache control.

The `zamaQueryKeys` object is a factory for React Query cache keys. Use it to invalidate, prefetch, or remove cached data manually.

Mutations auto-invalidate related caches, so you only need `zamaQueryKeys` for advanced cache control.

## Import

```ts
import { zamaQueryKeys } from "@zama-fhe/sdk/query";
```

## Usage

```tsx
import { useQueryClient } from "@tanstack/react-query";
import { invalidateBalanceQueries, zamaQueryKeys } from "@zama-fhe/sdk/query";

const queryClient = useQueryClient();

// Recommended: invalidate a token's balance across BOTH balance namespaces
// (single-token and batched) in one call.
invalidateBalanceQueries(queryClient, "0xToken");

// Lower-level: raw key factories for finer targeting.
queryClient.invalidateQueries({ queryKey: zamaQueryKeys.confidentialBalance.token("0xToken") });
queryClient.invalidateQueries({
  queryKey: zamaQueryKeys.confidentialBalance.owner("0xToken", "0xOwner"),
});
```

{% hint style="warning" %}
`confidentialBalance` (single-token) and `confidentialBalances` (batched, multi-token) are **disjoint** root namespaces with no shared prefix, so invalidating one never touches the other. `useConfidentialBalance` writes to the first and the batched `useConfidentialBalances` to the second — a manual `invalidateQueries({ queryKey: zamaQueryKeys.confidentialBalance.all })` silently leaves every batched entry stale. Prefer [`invalidateBalanceQueries`](#invalidatebalancequeries), which invalidates both.
{% endhint %}

## Key factories

### `zamaQueryKeys.confidentialBalance`

Single-token decrypted balance.

| Key                   | Scope                             |
| --------------------- | --------------------------------- |
| `.all`                | All decrypted balances            |
| `.token(addr)`        | All balances for one token        |
| `.owner(addr, owner)` | One owner's balance for one token |

### `zamaQueryKeys.confidentialBalances`

Multi-token batch balances.

| Key                     | Scope                                     |
| ----------------------- | ----------------------------------------- |
| `.all`                  | All batch balance queries                 |
| `.tokens(addrs, owner)` | Batch query for specific tokens and owner |

### `invalidateBalanceQueries`

Because the two balance namespaces above are disjoint, invalidating a token's balance correctly means hitting both. `invalidateBalanceQueries` does exactly that — invalidate a token in `confidentialBalance` and refetch every batched `confidentialBalances` query — so callers don't have to compose two keys and risk dropping half the cache. This is the same helper the SDK's own mutations use to auto-invalidate after a shield, transfer, or unshield.

```ts
import { invalidateBalanceQueries } from "@zama-fhe/sdk/query";

invalidateBalanceQueries(queryClient, "0xToken");
```

### `zamaQueryKeys.hasPermit`

Permit coverage status.

| Key    | Scope                   |
| ------ | ----------------------- |
| `.all` | All `hasPermit` queries |

### `zamaQueryKeys.underlyingAllowance`

ERC-20 allowance of the underlying token for the wrapper.

| Key                   | Scope                                      |
| --------------------- | ------------------------------------------ |
| `.all`                | All allowance queries                      |
| `.token(addr)`        | Allowances for one token                   |
| `.scope(addr, owner)` | Specific owner's allowance for the wrapper |

### `zamaQueryKeys.wrappersRegistry`

On-chain wrappers registry queries.

| Key                                                         | Scope                                 |
| ----------------------------------------------------------- | ------------------------------------- |
| `.all`                                                      | All registry queries                  |
| `.chainId()`                                                | Chain ID resolution                   |
| `.tokenPairs(registryAddr)`                                 | All pairs for a registry              |
| `.tokenPairsLength(registryAddr)`                           | Pair count                            |
| `.tokenPairsSlice(registryAddr, from, to)`                  | Index-based slice                     |
| `.tokenPair(registryAddr, index)`                           | Single pair by index                  |
| `.confidentialTokenAddress(registryAddr, tokenAddr)`        | Forward lookup (plain → confidential) |
| `.tokenAddress(registryAddr, confidentialAddr)`             | Reverse lookup (confidential → plain) |
| `.isConfidentialTokenValid(registryAddr, confidentialAddr)` | Validity check                        |
| `.listPairs(registryAddr, page, pageSize, metadata)`        | Paginated listing                     |

### `zamaQueryKeys.decryption`

Cached decrypted values. Populated by [`useDecryptValues`](/protocol/sdk/api-references/react/usedecryptvalues.md).

```ts
import { zamaQueryKeys } from "@zama-fhe/sdk/query";
```

| Key                                                   | Scope                                          |
| ----------------------------------------------------- | ---------------------------------------------- |
| `.encryptedValue(encryptedValue, contractAddress?)`   | Single clear value by encrypted value          |
| `.encryptedInputs(encryptedInputs[], walletAccount?)` | Multiple clear values by encrypted-input array |

### `vaultQueryKeys`

Batch reads for confidential ERC-4626 vaults, used by [`useCurrentBatchId`](/protocol/sdk/api-references/react/usecurrentbatchid.md), [`useBatchState`](/protocol/sdk/api-references/react/usebatchstate.md) and [`useTimeUntilDispatchable`](/protocol/sdk/api-references/react/usetimeuntildispatchable.md). Lives in the `vaults` subpath, not on `zamaQueryKeys`.

```ts
import { vaultQueryKeys, invalidateBatchQueries } from "@zama-fhe/sdk/vaults";
```

| Key                                             | Scope                                   |
| ----------------------------------------------- | --------------------------------------- |
| `.currentBatchId.batcher(batcherAddr)`          | One batcher's open batch id             |
| `.batchState.batcher(batcherAddr)`              | All batch states for one batcher        |
| `.batchState.batch(batcherAddr, batchId)`       | One batch's state                       |
| `.timeUntilDispatchable.batcher(batcherAddr)`   | All dispatch countdowns for one batcher |
| `.timeUntilDispatchable.batch(batcherAddr, id)` | One batch's dispatch countdown          |

A `batcher(...)` key is a prefix of every `batch(...)` key for that batcher, so invalidating it clears all of them at once. `invalidateBatchQueries(queryClient, batcherAddr)` invalidates all three namespaces for a batcher — this is what the vault mutation hooks call after a join, quit, recover or dispatch. Balances on the batcher's input and output tokens go through the regular [`invalidateBalanceQueries`](#invalidatebalancequeries).

## Common patterns

### Invalidate after an external transaction

```tsx
import { invalidateBalanceQueries } from "@zama-fhe/sdk/query";

// After a transfer made outside the SDK — refreshes both balance namespaces
invalidateBalanceQueries(queryClient, "0xToken");
```

### Prefetch balances on hover

```tsx
queryClient.prefetchQuery({
  queryKey: zamaQueryKeys.confidentialBalance.owner("0xToken", "0xOwner"),
  queryFn: () => fetchBalance("0xToken", "0xOwner"),
});
```

### Clear all cached data on disconnect

Use `invalidateWalletLifecycleQueries` — it removes wallet-local caches (decrypted values, permits) and invalidates every Zama query across all namespaces, so a stale entitlement can't leak across accounts. Hand-composing `removeQueries` on a single balance namespace would miss the batched balances, permits, and decryption caches.

```tsx
import { invalidateWalletLifecycleQueries } from "@zama-fhe/sdk/query";

invalidateWalletLifecycleQueries(queryClient);
```

## Related

* [ZamaProvider](/protocol/sdk/api-references/react/zamaprovider.md) — provider setup and hook overview
* [`useConfidentialBalance`](/protocol/sdk/api-references/react/useconfidentialbalance.md) — the hook whose cache these keys control


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.zama.org/protocol/sdk/api-references/react/query-keys.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
