> ## Documentation Index
> Fetch the complete documentation index at: https://cyphers-3138df4b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# React setup

> Wrap your app with CypherProvider and configure the QueryClient.

The React integration lives in `@cypher-zk/sdk/react`. It wraps a `CypherClient` instance in context so every component can call hooks without passing the client around manually.

## Install dependencies

<CodeGroup>
  ```bash bun theme={null}
  bun add @cypher-zk/sdk @solana/web3.js @tanstack/react-query
  ```

  ```bash npm theme={null}
  npm install @cypher-zk/sdk @solana/web3.js @tanstack/react-query
  ```

  ```bash yarn theme={null}
  yarn add @cypher-zk/sdk @solana/web3.js @tanstack/react-query
  ```

  ```bash pnpm theme={null}
  pnpm add @cypher-zk/sdk @solana/web3.js @tanstack/react-query
  ```
</CodeGroup>

## Set up the provider

<Tabs>
  <Tab title="Next.js app router">
    ```typescript TypeScript theme={null}
    // src/providers/cypher-provider.tsx
    "use client";

    import { useMemo } from "react";
    import { Connection } from "@solana/web3.js";
    import { CypherClient, readonlyWallet } from "@cypher-zk/sdk";
    import { CypherProvider as BaseCypherProvider } from "@cypher-zk/sdk/react";
    import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
    import { useWallet } from "@solana/wallet-adapter-react";

    const queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          refetchOnWindowFocus: false,
          retry: false,
        },
      },
    });

    export function CypherProvider({ children }: { children: React.ReactNode }) {
      const { wallet, publicKey, signTransaction, signAllTransactions } = useWallet();

      const client = useMemo(() => {
        const connection = new Connection(
          process.env.NEXT_PUBLIC_RPC_URL!,
          "confirmed"
        );
        const w =
          wallet && publicKey && signTransaction && signAllTransactions
            ? { publicKey, signTransaction, signAllTransactions }
            : readonlyWallet(publicKey ?? /* fallback pk */);

        return new CypherClient({ connection, wallet: w, cluster: "devnet" });
      }, [wallet, publicKey, signTransaction, signAllTransactions]);

      return (
        <QueryClientProvider client={queryClient}>
          <BaseCypherProvider client={client}>
            {children}
          </BaseCypherProvider>
        </QueryClientProvider>
      );
    }
    ```

    Add to your root layout:

    ```typescript TypeScript theme={null}
    // src/app/layout.tsx
    import "@/lib/buffer-polyfill";
    import { CypherProvider } from "@/providers/cypher-provider";

    export default function RootLayout({ children }) {
      return (
        <html>
          <body>
            <CypherProvider>{children}</CypherProvider>
          </body>
        </html>
      );
    }
    ```
  </Tab>

  <Tab title="Vite / CRA">
    ```typescript TypeScript theme={null}
    // src/main.tsx
    import { Connection } from "@solana/web3.js";
    import { CypherClient, keypairToWallet } from "@cypher-zk/sdk";
    import { CypherProvider } from "@cypher-zk/sdk/react";
    import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

    const connection = new Connection("https://api.devnet.solana.com", "confirmed");
    const client = new CypherClient({
      connection,
      wallet: keypairToWallet(myKeypair), // or wallet adapter
      cluster: "devnet",
    });

    const queryClient = new QueryClient({
      defaultOptions: { queries: { refetchOnWindowFocus: false, retry: false } },
    });

    ReactDOM.createRoot(document.getElementById("root")!).render(
      <QueryClientProvider client={queryClient}>
        <CypherProvider client={client}>
          <App />
        </CypherProvider>
      </QueryClientProvider>
    );
    ```
  </Tab>
</Tabs>

## Read-only mode

Use `readonlyWallet` when the user isn't connected yet. It lets fetch hooks run without a signer - mutation hooks will throw if called.

```typescript TypeScript theme={null}
import { readonlyWallet } from "@cypher-zk/sdk";

const client = new CypherClient({
  connection,
  wallet: readonlyWallet(somePublicKey),
  cluster: "devnet",
});
```

## Access the client directly

Inside any component, `useCypherClient()` returns the client from context:

```typescript TypeScript theme={null}
import { useCypherClient } from "@cypher-zk/sdk/react";

function MyComponent() {
  const client = useCypherClient();
  // client.markets.all(), client.actions.placeBet(...), etc.
}
```

<Note>
  `useCypherClient()` throws if called outside `<CypherProvider>`. Make sure the hook is inside the provider tree.
</Note>

## Building with AI

If you use an AI coding agent (Claude, Cursor, etc.), the `cypher-skill` gives it deep context about the SDK - provider wiring, hook patterns, encryption flows, and common pitfalls.

<Prompt description="Add cypher-skill to your project - covers CypherProvider setup, all React hooks, onProgress patterns, x25519 secret persistence, and market phase gating." icon="wand-magic-sparkles" actions={["copy"]}>
  npx skills add cypher-zk/cypher-skill
</Prompt>

## What's next

* [Query hooks](/sdk/react/query-hooks) - fetch markets, positions, global state
* [Mutation hooks](/sdk/react/mutation-hooks) - place bets, claim, resolve
