Skip to content

Latest commit

Β 

History

History
executable file
Β·
447 lines (342 loc) Β· 15.4 KB

File metadata and controls

executable file
Β·
447 lines (342 loc) Β· 15.4 KB

Privy Smart Wallets Template for Monad Testnet

A production-ready Next.js template for using smart wallets with Privy Auth on Monad Testnet. This template demonstrates how to integrate Privy's smart wallet functionality, enabling seamless user onboarding and transaction execution without requiring users to manage private keys.

πŸš€ Features

  • πŸ” Smart Wallet Integration - Automatic smart wallet creation for all users via Privy
  • πŸ’Ό Embedded Wallets - No need for users to install browser extensions
  • πŸ”„ Batch Transactions - Execute multiple transactions in a single batch
  • πŸ“ Transaction Examples - Complete examples for minting NFTs, approvals, and batch operations
  • 🌐 Monad Testnet Support - Pre-configured for Monad Testnet (Chain ID: 10143)
  • πŸ”’ Server-Side Auth - Secure authentication with server-side token verification
  • πŸ“± Responsive Design - Modern UI built with Tailwind CSS
  • ⚑ TypeScript - Fully typed for better developer experience
  • 🎨 Beautiful UI - Custom graphics and styling

πŸ“‹ Tech Stack

  • Framework: Next.js (Pages Router)
  • Language: TypeScript
  • Styling: Tailwind CSS
  • Authentication: Privy Auth
  • Smart Wallets: Privy Smart Wallets
  • Blockchain: Monad Testnet (Chain ID: 10143)
  • Blockchain Library: Viem
  • UI Components: Headless UI, Heroicons

πŸ“ Project Structure

Smart-Wallet-Privy-Template/
β”œβ”€β”€ pages/
β”‚   β”œβ”€β”€ _app.tsx              # Root app component with PrivyProvider and SmartWalletsProvider
β”‚   β”œβ”€β”€ index.tsx             # Login page with server-side auth check
β”‚   β”œβ”€β”€ dashboard.tsx         # Dashboard with smart wallet transaction examples
β”‚   └── api/
β”‚       └── verify.ts         # API route for token verification
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ graphics/
β”‚   β”‚   β”œβ”€β”€ login.tsx         # Login page graphics
β”‚   β”‚   └── portal.tsx        # Portal graphics component
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   └── abis/
β”‚   β”‚       └── mint.ts       # NFT mint ABI
β”‚   β”œβ”€β”€ formatted-date.tsx    # Date formatting component
β”‚   β”œβ”€β”€ layout.tsx            # Layout component
β”‚   β”œβ”€β”€ logo.tsx              # Logo component
β”‚   └── navbar.tsx            # Navigation bar
β”œβ”€β”€ styles/
β”‚   └── globals.css           # Global styles
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ fonts/                # Custom fonts
β”‚   β”œβ”€β”€ images/               # Static images
β”‚   └── logos/                # Logo assets
β”œβ”€β”€ .env.local                # Environment variables (create this)
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
└── README.md

πŸ› οΈ Getting Started

Prerequisites

Before you begin, ensure you have:

  • Node.js 18+ installed
  • npm 9+ (or yarn/pnpm)
  • A Privy account with an app created
  • Smart wallets configured in your Privy dashboard
  • Monad Testnet configured in your wallet (Chain ID: 10143)
  • Testnet tokens from the Monad Faucet

1. Clone or Use This Template

# If cloning from a repository
git clone <repository-url>
cd Smart-Wallet-Privy-Template

# Or use this as a template for your project

2. Install Dependencies

npm install
# or
yarn install
# or
pnpm install

3. Configure Environment Variables

Create a .env.local file in the root directory:

# Privy App ID (public, safe to expose)
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id_here

# Privy App Secret (server-side only, keep private!)
PRIVY_APP_SECRET=your_privy_app_secret_here

Getting Your Privy Credentials

  1. Sign up/Login to Privy Dashboard
  2. Create a new app or select an existing one
  3. Get your App ID:
    • Go to Settings β†’ API Keys
    • Copy your App ID (this is public and safe to expose)
  4. Get your App Secret:
    • In the same section, copy your App Secret (keep this private!)
    • Only use this server-side, never expose it to the client

Configure Smart Wallets

  1. In your Privy dashboard, navigate to Wallets β†’ Smart Wallets
  2. Enable smart wallets for your app
  3. Configure your smart wallet settings:
    • Choose your smart wallet provider (e.g., Privy's default)
    • Set up gas sponsorship if desired
    • Configure wallet creation settings

4. Update Contract Address (Optional)

The template includes example transactions with an NFT contract. Update the contract address in pages/dashboard.tsx:

const NFT_CONTRACT_ADDRESS = "0xYourContractAddressOnMonadTestnet" as const;

Note: You'll need to deploy your own contract on Monad Testnet or use an existing contract address.

5. Run the Development Server

npm run dev
# or
yarn dev
# or
pnpm dev

Open http://localhost:3000 in your browser.

🎯 How It Works

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client    │────────▢│   Next.js    │────────▢│    Privy    β”‚
β”‚  (Browser)  β”‚         β”‚   Server     β”‚         β”‚   Service   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚                          β”‚                         β”‚
     β”‚  1. Login Request        β”‚                         β”‚
     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚                         β”‚
     β”‚                          β”‚  2. Authenticate        β”‚
     β”‚                          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚
     β”‚                          β”‚                         β”‚
     β”‚                          β”‚  3. Auth Token          β”‚
     β”‚                          │◀─────────────────────────
     β”‚                          β”‚                         β”‚
     β”‚  4. Auth Cookie          β”‚                         β”‚
     │◀──────────────────────────                         β”‚
     β”‚                          β”‚                         β”‚
     β”‚  5. Smart Wallet Created β”‚                         β”‚
     β”‚                          β”‚                         β”‚
     β”‚  6. Execute Transaction  β”‚                         β”‚
     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚                         β”‚
     β”‚                          β”‚  7. Send to Monad       β”‚
     β”‚                          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚
     β”‚                          β”‚                         β”‚
     β”‚  8. Transaction Receipt  β”‚                         β”‚
     │◀──────────────────────────                         β”‚

Authentication Flow

  1. User Login: User clicks "Log in" button on the home page
  2. Privy Modal: Privy authentication modal opens
  3. Authentication: User authenticates via email, social login, or wallet
  4. Smart Wallet Creation: Privy automatically creates a smart wallet for the user
  5. Server Verification: Server verifies the auth token and sets a cookie
  6. Dashboard Access: User is redirected to the dashboard

Smart Wallet Transactions

The template demonstrates three types of transactions:

  1. Single Transaction (Mint NFT):

    smartWalletClient.sendTransaction({
      to: NFT_CONTRACT_ADDRESS,
      data: encodeFunctionData({ abi: mintAbi, functionName: "mint", args: [...] }),
    });
  2. Single Transaction (Approve):

    smartWalletClient.sendTransaction({
      to: NFT_CONTRACT_ADDRESS,
      data: encodeFunctionData({ abi: erc721Abi, functionName: "setApprovalForAll", args: [...] }),
    });
  3. Batch Transaction:

    smartWalletClient.sendTransaction({
      account: smartWalletClient.account,
      calls: [
        { to: NFT_CONTRACT_ADDRESS, data: mintData },
        { to: NFT_CONTRACT_ADDRESS, data: approveData },
      ],
    });

Key Components

App Setup (pages/_app.tsx)

  • PrivyProvider: Wraps the app with Privy authentication
  • SmartWalletsProvider: Enables smart wallet functionality
  • Monad Testnet Configuration: Defines the Monad testnet chain

Login Page (pages/index.tsx)

  • Server-Side Auth Check: Verifies existing auth tokens
  • Login Flow: Handles user authentication
  • Redirect Logic: Redirects authenticated users to dashboard

Dashboard (pages/dashboard.tsx)

  • Smart Wallet Client: Uses useSmartWallets hook to get the smart wallet client
  • Transaction Examples: Demonstrates minting, approvals, and batch transactions
  • User Info Display: Shows the authenticated user object

πŸ”§ Customization

Changing the Network

The template is configured for Monad Testnet. To change networks, update pages/_app.tsx:

// Define your chain
const yourChain = defineChain({
  id: YOUR_CHAIN_ID,
  name: "Your Chain Name",
  // ... chain configuration
});

// Update PrivyProvider config
<PrivyProvider
  config={{
    defaultChain: yourChain,
    supportedChains: [yourChain],
    // ...
  }}
>

Adding Custom Transactions

Add new transaction functions in pages/dashboard.tsx:

const onCustomTransaction = () => {
  if (!smartWalletClient) return;

  smartWalletClient.sendTransaction({
    to: YOUR_CONTRACT_ADDRESS,
    data: encodeFunctionData({
      abi: yourAbi,
      functionName: "yourFunction",
      args: [/* your args */],
    }),
  });
};

Customizing UI

The template uses Tailwind CSS for styling. Modify components to customize the appearance:

  • Colors: Update Tailwind classes in components
  • Layout: Modify component structure in pages/ and components/
  • Graphics: Replace graphics in components/graphics/

Adding More Pages

Create new pages in the pages/ directory:

// pages/your-page.tsx
import { usePrivy } from "@privy-io/react-auth";
import { useSmartWallets } from "@privy-io/react-auth/smart-wallets";

export default function YourPage() {
  const { authenticated } = usePrivy();
  const { client } = useSmartWallets();
  
  // Your page content
}

πŸ› Troubleshooting

"NEXT_PUBLIC_PRIVY_APP_ID is not set"

  • βœ… Check .env.local exists in root directory
  • βœ… Verify variable name is exactly NEXT_PUBLIC_PRIVY_APP_ID
  • βœ… Restart dev server after adding env vars

"PRIVY_APP_SECRET is not set"

  • βœ… Ensure variable name is exactly PRIVY_APP_SECRET
  • βœ… Check .env.local file (not .env)
  • βœ… Restart dev server

Smart Wallet Not Creating

  • βœ… Verify smart wallets are enabled in Privy dashboard
  • βœ… Check smart wallet configuration in dashboard
  • βœ… Ensure you're using the correct App ID
  • βœ… Check browser console for errors

Transactions Failing

  • βœ… Verify contract address is correct for Monad Testnet
  • βœ… Ensure contract exists on Monad Testnet
  • βœ… Check smart wallet has sufficient balance
  • βœ… Verify ABI matches your contract
  • βœ… Check browser console for detailed error messages

Authentication Not Working

  • βœ… Verify Privy App ID is correct
  • βœ… Check Privy dashboard for app status
  • βœ… Ensure cookies are enabled in browser
  • βœ… Check server logs for authentication errors

Network Issues

  • βœ… Verify Monad Testnet is correctly configured
  • βœ… Check RPC endpoint is accessible: https://testnet-rpc.monad.xyz
  • βœ… Ensure wallet is connected to Monad Testnet
  • βœ… Verify Chain ID is 10143

🚒 Deployment

Deploy to Vercel

  1. Push to GitHub

    git add .
    git commit -m "Initial commit"
    git push origin main
  2. Import to Vercel

    • Go to Vercel
    • Click "New Project"
    • Import your repository
  3. Add Environment Variables

    • NEXT_PUBLIC_PRIVY_APP_ID: Your Privy App ID
    • PRIVY_APP_SECRET: Your Privy App Secret
  4. Deploy

    • Click "Deploy"
    • Wait for build to complete

Other Platforms

This is a standard Next.js app and can be deployed to any platform supporting Next.js:

  • Netlify: Set build command to npm run build and publish directory to .next
  • Railway/Render: Set build command to npm run build and start command to npm start
  • AWS Amplify: Follow Next.js deployment guide
  • Self-hosted: Run npm run build and npm start

Environment Variables

Required for Production:

  • NEXT_PUBLIC_PRIVY_APP_ID: Public App ID (exposed to browser)
  • PRIVY_APP_SECRET: Private App Secret (server-side only)

Security Notes:

  • βœ… Never commit .env.local to git
  • βœ… Use platform-specific env var management
  • βœ… PRIVY_APP_SECRET should never be exposed client-side
  • βœ… NEXT_PUBLIC_* variables are exposed to browser

πŸ“š Additional Resources

🀝 Contributing

This is a template repository. Feel free to fork and customize for your needs!

If you have improvements or find issues:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

πŸ“ License

This template is provided as-is for educational and development purposes.

⚠️ Important Notes

  • Testnet Only: This template is configured for Monad Testnet - use testnet tokens only
  • Contract Address: The NFT contract address in dashboard.tsx is a placeholder - update it with your own contract
  • Smart Wallet Configuration: Ensure smart wallets are properly configured in your Privy dashboard
  • API Keys: Keep your PRIVY_APP_SECRET secure and never commit it to version control
  • Gas Sponsorship: Configure gas sponsorship in Privy dashboard if you want to sponsor user transactions
  • Rate Limits: Be aware of Privy API rate limits for production use

🌐 Monad Testnet Configuration

This template is pre-configured for Monad Testnet:


Built for the Monad Ecosystem πŸš€

Happy Building! πŸŽ‰