UNPKG

cdp-wallet-onramp-kit

Version:

Complete toolkit for Coinbase Developer Platform (CDP) Embedded Wallets and Onramp integration with reusable components, utilities, and documentation

539 lines (411 loc) 14.6 kB
# Add Coinbase Embedded Wallets to Existing Next.js App **Purpose:** Comprehensive instructions for integrating [Coinbase Developer Platform (CDP) Embedded Wallets](https://docs.cdp.coinbase.com/embedded-wallets/docs) into an existing Next.js (App Router) application using local documentation and best practices. **Scope:** All AI-generated advice or code related to CDP Embedded Wallets must follow these guardrails and utilize the provided documentation. --- ## **STEP 1: Install Documentation Package** **IMPORTANT:** Before starting the integration, install the embedded wallet documentation package to access comprehensive guides and examples: ```bash npx -p embedded-wallet-docs-cli embedded-wallet-docs setup ``` Or use the interactive setup: ```bash npx -p embedded-wallet-docs-cli embedded-wallet-setup ``` This will create `doc/embedded-wallet/` in your project with the following documentation: - `wallet/cors-configuration.md` - CORS setup requirements - `wallet/embedded-wallets.md` - Core wallet functionality - `wallet/overview.md` - Introduction and concepts - `wallet/quickstart.md` - Getting started guide - `wallet/react-components.md` - Pre-built UI components - `wallet/react-hooks.md` - Custom hook implementations - `wallet/wagmi.md` - Wagmi integration patterns **CRITICAL:** Reference these documentation files throughout the integration process for specific implementation details, troubleshooting, and best practices. --- ## **🚨 CRITICAL INSTRUCTIONS FOR AI CODING AGENTS 🚨** ### **ABSOLUTE REQUIREMENTS FOR NEXT.JS** You **MUST** follow these requirements or the implementation will **BREAK**: 1. **ALWAYS add `"use client"` directive** at the top of ANY file using CDP components or hooks: ```tsx "use client"; // MUST be the first line import { useSignInWithEmail } from "@coinbase/cdp-hooks"; ``` 2. **NEVER use Node.js 21** - Only Node.js 20 or 22 are supported 3. **ALWAYS configure CORS first** - Check `doc/embedded-wallet/wallet/cors-configuration.md` for setup instructions 4. **ALWAYS use App Router structure** (`app/` directory, not `pages/`) 5. **NEVER import CDP providers directly in layout.tsx** - Create a client wrapper component: ```tsx // WRONG - Will cause SSR errors in Next.js App Router // app/layout.tsx import { CDPReactProvider } from '@coinbase/cdp-react'; export default function RootLayout({ children }) { return <CDPReactProvider>...</CDPReactProvider> // Server-side error! } // CORRECT - Create separate client component wrapper // components/cdp-provider.tsx "use client"; import { CDPReactProvider } from '@coinbase/cdp-react'; const cdpConfig = { /* your config */ }; const appConfig = { /* your app config */ }; export function CDPProvider({ children }: { children: React.ReactNode }) { return ( <CDPReactProvider config={cdpConfig} app={appConfig}> {children} </CDPReactProvider> ); } // app/layout.tsx import { CDPProvider } from '@/components/cdp-provider'; export default function RootLayout({ children }) { return ( <html> <body> <CDPProvider>{children}</CDPProvider> </body> </html> ); } ``` 6. **ALWAYS check documentation files** - Reference relevant files in `doc/embedded-wallet/wallet/` for implementation patterns ### **CRITICAL ERROR PATTERNS TO AVOID** ```tsx // NEVER GENERATE THIS - WILL BREAK APPLICATION // Missing "use client" directive import { useSignInWithEmail } from "@coinbase/cdp-hooks"; // NEVER GENERATE THIS - WRONG NODE VERSION // Using Node.js 21 (unsupported) // NEVER GENERATE THIS - PAGES ROUTER PATTERN // Using pages/ directory structure for new implementations // NEVER GENERATE THIS - MISSING CORS // Implementing without CORS configuration // NEVER GENERATE THIS - PROVIDER IN LAYOUT.TSX // Direct CDP provider import in server-side layout import { CDPReactProvider } from '@coinbase/cdp-react'; export default function RootLayout({ children }) { return <CDPReactProvider>...</CDPReactProvider> // SSR error! } ``` --- ## **STEP 2: Choose Integration Approach** Based on your project needs, select ONE of these approaches. Consult `doc/embedded-wallet/wallet/overview.md` for detailed comparison: ### **Option A: React Components (Recommended for Rapid Development)** - Pre-built, customizable UI components - Fastest implementation - See `doc/embedded-wallet/wallet/react-components.md` for details ### **Option B: React Hooks (Custom UI)** - Full control over UI/UX - Custom authentication flows - See `doc/embedded-wallet/wallet/react-hooks.md` for implementation ### **Option C: Wagmi Integration (Existing Wagmi Apps)** - Bridge to existing wagmi ecosystem - Maintain current patterns - See `doc/embedded-wallet/wallet/wagmi.md` for setup --- ## **STEP 3: Installation and Setup** ### **Install Required Packages** ```bash # Choose based on your selected approach: # Option A: React Components npm install @coinbase/cdp-react @coinbase/cdp-core @coinbase/cdp-hooks # Option B: React Hooks npm install @coinbase/cdp-hooks @coinbase/cdp-core # Option C: Wagmi Integration npm install @coinbase/cdp-wagmi @coinbase/cdp-core @tanstack/react-query viem wagmi ``` ### **Environment Configuration** Create or update your `.env.local` file: ```bash # Get your Project ID from https://portal.cdp.coinbase.com NEXT_PUBLIC_CDP_PROJECT_ID=your-project-id-here ``` ### **CORS Configuration (MANDATORY)** **CRITICAL:** Before any code will work, you MUST configure CORS: 1. Visit https://portal.cdp.coinbase.com/products/embedded-wallets/cors 2. Add your origins: - Development: `http://localhost:3000` - Production: `https://yourdomain.com` 3. Save changes (takes effect immediately) Refer to `doc/embedded-wallet/wallet/cors-configuration.md` for detailed CORS setup instructions and troubleshooting. --- ## **STEP 4: Provider Setup** ### **Option A: React Components Provider** **IMPORTANT:** Create a client wrapper component to avoid SSR issues: ```tsx // components/cdp-provider.tsx "use client"; import { CDPReactProvider, type Theme } from '@coinbase/cdp-react'; const cdpConfig = { projectId: process.env.NEXT_PUBLIC_CDP_PROJECT_ID!, basePath: "https://api.cdp.coinbase.com/platform", useMock: false, debugging: false, }; const appConfig = { name: "Your App Name", logoUrl: "https://your-logo-url.com/logo.png", }; export function CDPProvider({ children }: { children: React.ReactNode }) { return ( <CDPReactProvider config={cdpConfig} app={appConfig}> {children} </CDPReactProvider> ); } ``` ```tsx // app/layout.tsx import { CDPProvider } from '@/components/cdp-provider'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <CDPProvider> {/* Your existing layout content */} {children} </CDPProvider> </body> </html> ); } ``` ### **Option B: React Hooks Provider** **IMPORTANT:** Create a client wrapper component to avoid SSR issues: ```tsx // components/cdp-provider.tsx "use client"; import { CDPHooksProvider } from "@coinbase/cdp-hooks"; const cdpConfig = { projectId: process.env.NEXT_PUBLIC_CDP_PROJECT_ID!, basePath: "https://api.cdp.coinbase.com/platform", useMock: false, debugging: false, }; export function CDPProvider({ children }: { children: React.ReactNode }) { return ( <CDPHooksProvider config={cdpConfig}> {children} </CDPHooksProvider> ); } ``` ```tsx // app/layout.tsx import { CDPProvider } from '@/components/cdp-provider'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <CDPProvider> {/* Your existing layout content */} {children} </CDPProvider> </body> </html> ); } ``` ### **Option C: Wagmi Integration** ```tsx // app/layout.tsx import { Config } from '@coinbase/cdp-core'; import { createCDPEmbeddedWalletConnector } from '@coinbase/cdp-wagmi'; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { http } from "viem"; import { base, baseSepolia } from 'viem/chains'; import { WagmiProvider, createConfig } from 'wagmi'; const cdpConfig: Config = { projectId: process.env.NEXT_PUBLIC_CDP_PROJECT_ID!, }; const connector = createCDPEmbeddedWalletConnector({ cdpConfig, providerConfig: { chains: [base, baseSepolia], transports: { [base.id]: http(), [baseSepolia.id]: http() } } }); const wagmiConfig = createConfig({ connectors: [connector], chains: [base, baseSepolia], transports: { [base.id]: http(), [baseSepolia.id]: http(), }, }); const queryClient = new QueryClient(); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <WagmiProvider config={wagmiConfig}> <QueryClientProvider client={queryClient}> {/* Your existing layout content */} {children} </QueryClientProvider> </WagmiProvider> </body> </html> ); } ``` --- ## **STEP 5: Authentication Integration** ### **Add Wallet Authentication to Your App** Create a new component or integrate into existing components: ```tsx // components/WalletAuth.tsx "use client"; import { useIsInitialized, useIsSignedIn } from "@coinbase/cdp-hooks"; import { AuthButton } from "@coinbase/cdp-react"; // Option A only export function WalletAuth() { const isInitialized = useIsInitialized(); const isSignedIn = useIsSignedIn(); if (!isInitialized) { return <div>Loading wallet...</div>; } return ( <div> {/* Option A: Use pre-built component */} <AuthButton /> {/* Option B: Custom implementation - see doc/embedded-wallet/wallet/react-hooks.md */} {isSignedIn && ( <div> <p>✅ Wallet connected!</p> {/* Add your wallet dashboard here */} </div> )} </div> ); } ``` ### **Integrate into Your Existing Layout** ```tsx // app/layout.tsx (add to your existing layout) import { WalletAuth } from '@/components/WalletAuth'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> {/* Your existing provider setup */} <header> {/* Your existing header content */} <WalletAuth /> </header> {children} </body> </html> ); } ``` --- ## **STEP 6: Transaction Implementation** For transaction functionality, reference the appropriate documentation: - `doc/embedded-wallet/wallet/embedded-wallets.md` for core transaction patterns - `doc/embedded-wallet/wallet/quickstart.md` for basic examples ```tsx // components/SendTransaction.tsx "use client"; import { useState } from "react"; import { useSendEvmTransaction, useEvmAddress } from "@coinbase/cdp-hooks"; export function SendTransaction() { const sendTransaction = useSendEvmTransaction(); const evmAddress = useEvmAddress(); const [isLoading, setIsLoading] = useState(false); const handleSend = async () => { if (!evmAddress) return; setIsLoading(true); try { const result = await sendTransaction({ evmAccount: evmAddress, transaction: { to: "0xRecipientAddress", value: 100000000000000n, // 0.0001 ETH in wei chainId: 84532, // Base Sepolia type: "eip1559", }, network: "base-sepolia", }); console.log("Transaction hash:", result.transactionHash); } catch (error) { console.error("Transaction failed:", error); } finally { setIsLoading(false); } }; return ( <button onClick={handleSend} disabled={!evmAddress || isLoading}> {isLoading ? "Sending..." : "Send Test Transaction"} </button> ); } ``` --- ## **STEP 7: Testing and Verification** ### **Development Testing** 1. **Start your development server:** ```bash npm run dev ``` 2. **Visit your app and test:** - Sign in with email + OTP - Verify wallet creation - Test basic transactions (if implemented) 3. **Check console for errors** - Enable debugging in development: ```tsx const cdpConfig = { projectId: process.env.NEXT_PUBLIC_CDP_PROJECT_ID!, debugging: true, // Enable for development // ... other config }; ``` ### **Common Issues and Solutions** Reference `doc/embedded-wallet/wallet/` documentation for troubleshooting: 1. **CORS Errors:** Check `cors-configuration.md` 2. **Authentication Issues:** See authentication patterns in relevant docs 3. **Transaction Failures:** Review transaction examples in `embedded-wallets.md` --- ## **AI MODEL VERIFICATION STEPS** Before generating any CDP Embedded Wallet code, you **MUST** verify: 1. **Documentation Reference**: Did you reference the appropriate files in `doc/embedded-wallet/wallet/`? 2. **Client Directive**: Does EVERY file using CDP hooks/components start with `"use client";`? 3. **Package Imports**: Are you importing from the correct packages? 4. **App Router**: Are you using `app/` directory structure? 5. **Environment Variables**: Are you using `NEXT_PUBLIC_CDP_PROJECT_ID`? 6. **CORS Mention**: Did you instruct about CORS configuration? 7. **Chain IDs**: Are you using correct chain IDs (Base: 8453, Base Sepolia: 84532)? If ANY check **fails**, **STOP** and revise until compliance is achieved. --- ## **DEPLOYMENT CHECKLIST** Before deploying to production: - [ ] CORS configured for production domain - [ ] Environment variables set in deployment platform - [ ] HTTPS enabled - [ ] Error handling implemented - [ ] Loading states added - [ ] Transaction flows tested - [ ] Documentation reviewed for production considerations --- ## **SUPPORT AND DOCUMENTATION** - **Local Documentation:** `doc/embedded-wallet/wallet/` (installed via setup command) - **CDP Portal:** https://portal.cdp.coinbase.com - **Official Docs:** https://docs.cdp.coinbase.com/embedded-wallets/docs **Remember:** Always reference the local documentation first, as it contains the most relevant patterns and examples for your specific use case. --- **FINAL NOTE:** This integration provides your users with a seamless Web3 experience without requiring external wallet installations, seed phrase management, or complex crypto knowledge. The embedded wallet handles all the complexity while giving you full control over the user experience.