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

# Frontend Integration

## Demo Project

A complete example project demonstrating how to use the Privacy Cash EVM SDK in a Next.js frontend:

[https://github.com/Privacy-Cash/base-sdk-demo-interface](https://github.com/Privacy-Cash/base-sdk-demo-interface)

## Installation

```bash theme={null}
npm install privacycash-evm wagmi viem @rainbow-me/rainbowkit @tanstack/react-query --save
```

<Info>
  Requires **Node.js 20+**. The SDK is written in TypeScript and includes type definitions.
</Info>

***

## Wallet Provider Setup

Wrap your app with Wagmi and RainbowKit providers configured for the supported EVM mainnets:

```typescript theme={null}
'use client'
import { RainbowKitProvider } from '@rainbow-me/rainbowkit'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { WagmiProvider, createConfig, http } from 'wagmi'
import { base, mainnet } from 'wagmi/chains'
import { walletConnect, coinbaseWallet } from 'wagmi/connectors'

const config = createConfig({
  ssr: true,
  chains: [base, mainnet],
  connectors: [
    coinbaseWallet({ appName: 'Your App' }),
    walletConnect({ projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID! }),
  ],
  transports: {
    [base.id]: http(process.env.NEXT_PUBLIC_BASE_RPC_URL),
    [mainnet.id]: http(process.env.NEXT_PUBLIC_ETH_RPC_URL),
  },
})

const queryClient = new QueryClient()

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>
      <WagmiProvider config={config}>
        <RainbowKitProvider initialChain={base}>
          {children}
        </RainbowKitProvider>
      </WagmiProvider>
    </QueryClientProvider>
  )
}
```

***

## Deriving Encryption Key

Before a user can interact with Privacy Cash, they must sign an off-chain message. This signature is used to derive their private encryption key and UTXO keypair — **neither key ever leaves the client**.

```typescript theme={null}
import { useSignMessage } from 'wagmi'

const SIGN_MESSAGE = 'Privacy Money account sign in'
const LS_KEY_PREFIX = 'evm_sign_'

function saveSignature(address: string, signature: string) {
  localStorage.setItem(`${LS_KEY_PREFIX}${address}`, signature)
}

function getStoredSignature(address: string): string | null {
  return localStorage.getItem(`${LS_KEY_PREFIX}${address}`)
}

// In your component:
const { signMessage } = useSignMessage()
const { address } = useAccount()

function handleSignIn() {
  signMessage(
    { message: SIGN_MESSAGE },
    {
      onSuccess(signature) {
        saveSignature(address!, signature)
      },
    }
  )
}
```

Auto-prompt the user to sign when they connect their wallet:

```typescript theme={null}
useEffect(() => {
  if (!isConnected || !address) return
  const stored = getStoredSignature(address)
  if (!stored) handleSignIn()
}, [isConnected, address])
```

***

## Circuit Key File

Place the `circuit2.zkey` file in your Next.js `public/` folder. Pass the base path (without extension) to each SDK function:

```text theme={null}
public/
  circuit2.zkey    ← download from the SDK repo
```

```typescript theme={null}
keyBasePath: '/circuit'  // resolves to /circuit2.zkey at runtime
```

***

## Selecting a Network

Pass the active EVM network to SDK calls. Base is the default when `network` is omitted, but explicit selection keeps multi-chain apps predictable.

```typescript theme={null}
import { BASE_NETWORK, ETH_NETWORK, getBalance } from 'privacycash-evm'
import { useChainId } from 'wagmi'

function BalanceLoader({ signature, address }: { signature: string, address: string }) {
  const chainId = useChainId()
  const network = chainId === 1 ? ETH_NETWORK : chainId === 8453 ? BASE_NETWORK : undefined

  async function refreshBalance() {
    if (!network) throw new Error('Switch to Base or Ethereum mainnet.')

    return getBalance({
      signature,
      address,
      network,
    })
  }

  return null // Render your balance UI here.
}
```

## Common Issues

1. **Signature re-prompt on every page refresh** — Store the signature in `localStorage` keyed by address as shown above.
2. **`walletClient` temporarily undefined** — Use `connector.getProvider()` as a fallback when `useWalletClient()` is unavailable during initial mount.
3. **Wrong chain data** — Pass `network: BASE_NETWORK` or `network: ETH_NETWORK` to each SDK call after checking the connected wallet chain.

## Warnings

Privacy Cash SDK requires consistent signature generation, otherwise the deposited tokens might be lost forever since the encrypted UTXO can't be decrypted. Please make sure deriveKeys() generates the same result for the same params passed in. Most wallets returns the same result, but some non major wallets might generate different result.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.