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

# Privy

> Integrate Privy signers with Rhinestone smart accounts.

## Overview

Privy provides simple, secure wallet infrastructure that enables seamless user authentication and wallet management. This guide shows you how to integrate Privy signers with Rhinestone smart accounts to create a smooth, cross-chain wallet experience.

**How it works:** Privy handles user authentication and wallet creation, then provides a wagmi-compatible client that we wrap with Rhinestone's smart account functionality. You get the best of both worlds - Privy's seamless onboarding and Rhinestone's cross-chain capabilities.

## Prerequisites

* A Privy account and application
* Privy App ID
* React application setup

<Steps>
  <Step title="Install Dependencies">
    Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @privy-io/react-auth @privy-io/wagmi @tanstack/react-query @rhinestone/sdk viem wagmi
      ```

      ```bash pnpm theme={null}
      pnpm add @privy-io/react-auth @privy-io/wagmi @tanstack/react-query @rhinestone/sdk viem wagmi
      ```

      ```bash bun theme={null}
      bun install @privy-io/react-auth @privy-io/wagmi @tanstack/react-query @rhinestone/sdk viem wagmi
      ```
    </CodeGroup>

    <Note>Make sure to import `createConfig` and `WagmiProvider` from `@privy-io/wagmi` rather than from `wagmi` directly. Privy's wrappers ensure the two libraries stay in sync.</Note>
  </Step>

  <Step title="Set Up Providers">
    Set up the Privy, wagmi, and TanStack Query providers in your React application:

    ```tsx theme={null}
    import { PrivyProvider } from '@privy-io/react-auth'
    import { createConfig, WagmiProvider } from '@privy-io/wagmi'
    import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
    import { http } from 'wagmi'
    import { mainnet, polygon, arbitrum, base } from 'viem/chains'

    const queryClient = new QueryClient()

    const wagmiConfig = createConfig({
      chains: [mainnet, polygon, arbitrum, base],
      transports: {
        [mainnet.id]: http(),
        [polygon.id]: http(),
        [arbitrum.id]: http(),
        [base.id]: http(),
      },
    })

    function App() {
      return (
        <PrivyProvider
          appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
          config={{
            loginMethods: ['email', 'wallet', 'google', 'twitter'],
            appearance: {
              theme: 'light',
              accentColor: '#676FFF',
            },
            embeddedWallets: {
              ethereum: {
                createOnLogin: 'users-without-wallets',
              },
            },
            defaultChain: base,
            supportedChains: [mainnet, polygon, arbitrum, base],
          }}
        >
          <QueryClientProvider client={queryClient}>
            <WagmiProvider config={wagmiConfig}>
              {/* Your app components */}
            </WagmiProvider>
          </QueryClientProvider>
        </PrivyProvider>
      )
    }
    ```
  </Step>

  <Step title="Create Integration Hook">
    Create a custom hook that integrates Privy authentication with Rhinestone accounts. This hook demonstrates the key pattern: **use wagmi to get the wallet client from Privy, then pass it to Rhinestone as a signer**.

    <Note>The `useWalletClient()` hook from wagmi automatically connects to Privy's embedded wallets and external wallet connections.</Note>

    ```tsx theme={null}
    import { useState, useEffect } from 'react'
    import { usePrivy, useWallets } from "@privy-io/react-auth"
    import { useWalletClient, useAccount } from "wagmi"
    import { RhinestoneSDK, walletClientToAccount } from "@rhinestone/sdk"

    interface PrivyWalletState {
      rhinestoneAccount: any | null
      isLoading: boolean
      error: string | null
    }

    export function usePrivyWallet() {
      const { ready, authenticated, login, logout } = usePrivy()
      const { wallets } = useWallets()
      const { address } = useAccount()
      const { data: walletClient } = useWalletClient()
      const [state, setState] = useState<PrivyWalletState>({
        rhinestoneAccount: null,
        isLoading: false,
        error: null,
      })

      const initializeAccount = async () => {
        if (!ready || !authenticated || !address || !walletClient) {
          setState({ rhinestoneAccount: null, isLoading: false, error: null })
          return
        }

        setState(prev => ({ ...prev, isLoading: true, error: null }))

        try {
          // wrap the wagmi client for the sdk
          const wrappedWalletClient = walletClientToAccount(walletClient)

          // create the rhinestone account
          const rhinestone = new RhinestoneSDK({
            apiKey: process.env.NEXT_PUBLIC_RHINESTONE_API_KEY,
          })
          const account = await rhinestone.createAccount({
            owners: {
              type: "ecdsa",
              accounts: [wrappedWalletClient],
            },
          })

          setState({ rhinestoneAccount: account, isLoading: false, error: null })
        } catch (error) {
          console.error('Failed to initialize Rhinestone account:', error)
          setState({
            rhinestoneAccount: null,
            isLoading: false,
            error: error instanceof Error ? error.message : 'Failed to initialize account',
          })
        }
      }

      useEffect(() => {
        initializeAccount()
      }, [ready, authenticated, address, walletClient])

      return {
        rhinestoneAccount: state.rhinestoneAccount,
        isLoading: state.isLoading,
        error: state.error,
        authenticated,
        login,
        logout,
        reconnect: initializeAccount,
      }
    }
    ```
  </Step>
</Steps>

## Usage

### Basic Authentication Flow

Use the hook to handle Privy authentication and smart account creation:

```tsx theme={null}
import { usePrivyWallet } from './hooks/usePrivyWallet'

function PrivyWalletDashboard() {
  const { authenticated, login, logout, rhinestoneAccount, isLoading, error, reconnect } = usePrivyWallet()

  if (isLoading) {
    return <p>Setting up your wallet...</p>
  }

  if (error) {
    return (
      <div>
        <p>Error: {error}</p>
        <button onClick={reconnect}>Try Again</button>
      </div>
    )
  }

  if (!authenticated) {
    return (
      <div>
        <h2>Welcome to Rhinestone</h2>
        <button onClick={login}>Sign in with Privy</button>
      </div>
    )
  }

  return (
    <div>
      <h2>Connected!</h2>
      <p>Smart Account: {rhinestoneAccount?.getAddress()}</p>
      <button onClick={logout}>Logout</button>
    </div>
  )
}
```

### Cross-Chain Transactions

Send transactions using the Privy-connected wallet:

```tsx theme={null}
import { encodeFunctionData, parseUnits } from 'viem'
import { erc20Abi } from 'viem'
import { baseSepolia, arbitrumSepolia } from 'viem/chains'

async function handleCrossChainTransfer(rhinestoneAccount) {
  const transaction = await rhinestoneAccount.sendTransaction({
    sourceChains: [baseSepolia],
    targetChain: arbitrumSepolia,
    calls: [
      {
        to: "USDC",
        data: encodeFunctionData({
          abi: erc20Abi,
          functionName: "transfer",
          args: ["0xrecipient", parseUnits("10", 6)],
        }),
      },
    ],
    tokenRequests: [
      {
        address: "USDC",
        amount: parseUnits("10", 6),
      },
    ],
  })
}
```

## The Integration Pattern

All embedded signer integrations follow the same pattern:

1. **Provider Setup**: Configure the embedded wallet provider (Privy, Dynamic, Turnkey)
2. **Get Wallet Client**: Use wagmi hooks (or viem accounts for Turnkey) to access the authenticated wallet
3. **Pass to Rhinestone**: Create a Rhinestone account using the wallet client as a signer
4. **Use Cross-Chain Features**: The resulting account has all of Rhinestone's capabilities

This pattern means you can easily switch between providers or support multiple providers in the same app.

## Authentication Methods

Privy supports multiple authentication methods out of the box:

* **Email**: Users can sign in with their email address
* **Social**: Google, Twitter, Discord, and other OAuth providers
* **Wallet**: Connect external wallets like MetaMask
* **SMS**: Phone number verification

The `login()` function will show Privy's authentication modal with all configured methods.

## Environment Variables

Make sure to set the following environment variables:

```bash theme={null}
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id
NEXT_PUBLIC_RHINESTONE_API_KEY=your_rhinestone_api_key
```

## Complete Example

Try the full integration in our example repository:

```bash theme={null}
git clone https://github.com/rhinestonewtf/e2e-examples.git
cd e2e-examples/privy
npm install && npm run dev
```

The example demonstrates:

* Privy authentication flows (email, social, wallet)
* Embedded wallet creation and management
* Rhinestone smart account integration
* Cross-chain transaction execution

## Next Steps

* **See it in action**: [Privy + Rhinestone Example](https://github.com/rhinestonewtf/e2e-examples/tree/main/privy)
* Learn more about [Privy's authentication flows](https://docs.privy.io/)
* Explore [embedded wallet features](https://docs.privy.io/guide/react/wallets/embedded/creation)
* Explore [chain abstraction](../../chain-abstraction/unified-balance) capabilities
* Check out [creating an account](../create-account) for more details
