> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inco.org/llms.txt
> Use this file to discover all available pages before exploring further.

# React setup & wallet adapters

> Use wagmi or supply your own wallet client, with customizable tokens and images.

## Install React peers

```bash theme={null}
npm install @inco/ctoken viem @inco/lightning-js react react-dom wagmi @tanstack/react-query
# Add motion when using @inco/ctoken/ui:
npm install motion
```

## Complete provider tree

```tsx theme={null}
"use client";
import { useState, type ReactNode } from "react";
import { WagmiProvider, createConfig, usePublicClient, http } from "wagmi";
import { injected } from "wagmi/connectors";
import { baseSepolia } from "wagmi/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { CTokenProvider } from "@inco/ctoken/react";
import { ConfidentialWallet } from "@inco/ctoken/ui";
import "@inco/ctoken/ui/styles.css";

const config = createConfig({
  chains: [baseSepolia],
  connectors: [injected()],
  transports: { [baseSepolia.id]: http("https://your-app.example/api/rpc") },
  ssr: true,
});

export function Providers({ children }: { children: ReactNode }) {
  const [queryClient] = useState(() => new QueryClient());
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <TokenProvider>{children}</TokenProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}

// Replace the URL above with your paid read endpoint or application proxy.
function TokenProvider({ children }: { children: ReactNode }) {
  const publicClient = usePublicClient({ chainId: baseSepolia.id });
  if (!publicClient) throw new Error("Configure your read client.");
  return <CTokenProvider network="baseSepolia" publicClient={publicClient}>
    {children}
  </CTokenProvider>;
}

export function TokenWallet() {
  return <ConfidentialWallet triggerLabel="Open wallet" />;
}
```

Connect through your existing wagmi/RainbowKit button, or use:

```tsx theme={null}
import { useAccount, useConnect } from "wagmi";

export function ConnectWallet() {
  const { address } = useAccount();
  const { connect, connectors, isPending } = useConnect();
  if (address) return <span>{address}</span>;
  return (
    <button
      disabled={isPending || !connectors[0]}
      onClick={() => connect({ connector: connectors[0] })}
    >Connect wallet</button>
  );
}
```

## CTokenProvider props

Required: `network`, `publicClient`, and `children`. Optional: `walletClient`, `tokens`, and the [core configuration options](/ctoken/configuration#all-client-options). In Next.js, create clients inside a Client Component.

Tokens display in array order; discovered holdings append when indexing is enabled. `tokens={[]}` disables defaults. See [token hooks](/ctoken/hooks#read-hooks) for resolution helpers.

## Token images

```tsx theme={null}
import type { TokenConfig } from "@inco/ctoken";

const TOKENS: TokenConfig[] = [
  { erc20: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", symbol: "USDC", icon: "/tokens/usdc.svg" },
  { erc20: "0x0a215D8ba66387DCA84B284D18c3B4ec3de6E54a", symbol: "USDT", icon: "/tokens/usdt.png" },
  { erc20: "0x808456652fdb597867f38412077A9182bf77359F", symbol: "EURC", icon: "/tokens/eurc.svg" },
];

<CTokenProvider network="baseSepolia" publicClient={publicClient} tokens={TOKENS}>
  {children}
</CTokenProvider>
```

`icon` accepts an image URL or app-served path; place these files in `public/tokens`. Omit it for built-in metadata. Missing/broken images use generated avatars. Indexing is unnecessary.

## Supply your wallet client

An explicit `walletClient` works without `WagmiProvider`. Keep `QueryClientProvider` around hooks and widgets:

```tsx theme={null}
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState, type ReactNode } from "react";
import { CTokenProvider, type CTokenProviderProps } from "@inco/ctoken/react";

export function AppProviders({ publicClient, walletClient, children }: {
  publicClient: CTokenProviderProps["publicClient"];
  walletClient: CTokenProviderProps["walletClient"];
  children: ReactNode;
}) {
  const [queryClient] = useState(() => new QueryClient());
  return <QueryClientProvider client={queryClient}>
    <CTokenProvider network="baseSepolia" publicClient={publicClient}
      walletClient={walletClient}>
      {children}
    </CTokenProvider>
  </QueryClientProvider>;
}
```

| Wallet prop                                         | Source and behavior                                                                                                       |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Omitted                                             | Use the connected wallet from wagmi. Requires `WagmiProvider`.                                                            |
| `walletClient={yourClient}`                         | Use that client for owner identity, sessions, signing, writes, and chain switching. Overrides any connected wagmi wallet. |
| `walletClient={undefined}` or `walletClient={null}` | Explicitly disconnected. Does not fall back to a different wagmi wallet while connecting or after disconnecting.          |

Set the client’s `account`, keep it stable between renders, replace it on account/chain changes, and pass null/undefined on disconnect. Use your own connect/disconnect UI.

Keep the wagmi peer dependency installed even when supplying your own wallet.

The public client handles reads and receipts; the wallet client signs and submits transactions. Session vouchers authorize reveals but cannot replace the wallet for writes.

## Ethers or another wallet library

Adapt an ethers v6 `BrowserProvider` to the required viem `WalletClient`:

```ts theme={null}
import type { BrowserProvider } from "ethers";
import { createWalletClient, custom, getAddress } from "viem";
import { baseSepolia } from "viem/chains";

// Call after the user's connect action; retain the result in app state.
export async function walletClientFromEthers(provider: BrowserProvider) {
  const signer = await provider.getSigner();
  return createWalletClient({
    account: getAddress(await signer.getAddress()),
    chain: baseSepolia,
    transport: custom({
      request: ({ method, params }) => provider.send(method, params ?? []),
    }),
  });
}

// Pass the result to <CTokenProvider walletClient={walletClient} ...>.
```

For an existing EIP-1193 provider, use `custom(walletProvider)` directly. Refresh the adapter on account/chain changes and clear it on disconnect. Other signers need a compatible signing adapter. See [ethers BrowserProvider](https://docs.ethers.org/v6/api/providers/#BrowserProvider) and [viem WalletClient](https://viem.sh/docs/clients/wallet).
