Project Setup
In this section, we'll set up a NextJS project and configure it to work with Coinbase Smart Wallet.
What you'll achieve
By the end of this guide, you will:
- Set up a NextJS project and configure it to work with Coinbase Smart Wallet
- Create a Coinbase Wallet Context to manage the state and functions needed to interact with Coinbase Smart Wallet
Creating a New Project
We'll be using NextJS to bootstrap this project, but you can adapt these concepts to any frontend framework of your choice.
First, create a new NextJS project:
npx create-next-app@latest my-app
Navigate into the project directory:
cd my-app
Install Coinbase Wallet SDK (only on canary version for now)
npm install @coinbase/wallet-sdk@canary
Install viem for blockchain interactions
npm install viem
Note: Make sure you're using version 4.4.0 or above of the Coinbase Wallet SDK.
Project Structure
After running these commands, your project should have the following basic structure:
app/
layout.tsx
page.tsx
Setting up the Coinbase Wallet Context
This section will walk you through setting up Coinbase Wallet Context to manage the state and functions needed to interact with Coinbase Smart Wallet.
Create a new directory called context
under the app
directory and add a React Context for the Coinbase SDK.
// app/context/CoinbaseWalletContext.tsx
'use client';
import { createCoinbaseWalletSDK, ProviderInterface } from '@coinbase/wallet-sdk';
import {
createContext,
useContext,
useEffect,
useState,
ReactNode,
useMemo,
useCallback,
} from 'react';
import { Address, createWalletClient, custom } from 'viem';
import { baseSepolia } from 'viem/chains';
interface CoinbaseWalletContextType {
provider: ProviderInterface | null;
connect: () => Promise<void>;
disconnect: () => void;
isConnected: boolean;
address: Address | null;
}
const CoinbaseWalletContext = createContext<CoinbaseWalletContextType>({
provider: null,
connect: async () => {},
disconnect: () => {},
isConnected: false,
address: null,
});
export function CoinbaseWalletProvider({ children }: { children: ReactNode }) {
const [provider, setProvider] = useState<ProviderInterface | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [address, setAddress] = useState<Address | null>(null);
useEffect(() => {
// Initialize Coinbase Wallet SDK
const coinbaseWalletSDK = createCoinbaseWalletSDK({
appName: 'Coinbase Wallet demo',
appChainIds: [baseSepolia.id],
preference: {
options: 'smartWalletOnly',
keysUrl: 'https://keys-dev.coinbase.com/connect',
},
});
setProvider(coinbaseWalletSDK.getProvider());
}, []);
const walletClient = useMemo(() => {
if (!provider) return null;
return createWalletClient({
chain: baseSepolia,
transport: custom({
async request({ method, params }) {
const response = await provider.request({ method, params });
return response;
},
}),
});
}, [provider]);
const connect = useCallback(async () => {
if (!walletClient || !provider) return;
walletClient.requestAddresses().then(async (addresses) => {
if (addresses.length > 0) {
setAddress(addresses[0]);
setIsConnected(true);
}
});
}, [walletClient, provider]);
const disconnect = () => {
if (!provider) return;
try {
provider.disconnect();
setIsConnected(false);
setAddress(null);
} catch (error) {
console.error('Failed to disconnect from Coinbase Wallet:', error);
}
};
return (
<CoinbaseWalletContext.Provider
value={{
provider,
connect,
disconnect,
isConnected,
address,
}}
>
{children}
</CoinbaseWalletContext.Provider>
);
}
export function useCoinbaseWallet() {
const context = useContext(CoinbaseWalletContext);
if (context === undefined) {
throw new Error('useCoinbaseWallet must be used within a CoinbaseWalletProvider');
}
return context;
}
Creating the Provider Wrapper
Create a providers file to wrap your application:
// app/providers.tsx
'use client';
import { CoinbaseWalletProvider } from '@/context/CoinbaseWalletContext';
export default function Providers({ children }: { children: ReactNode }) {
return <CoinbaseWalletProvider>{children}</CoinbaseWalletProvider>;
}
Updating the Root Layout
Update your root layout to include the providers:
// app/layout.tsx
import Providers from '@/app/providers';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
Creating the Home Page
Update your main page to include wallet connection functionality:
// app/page.tsx
'use client';
import { useCoinbaseWallet } from './context/CoinbaseWalletContext';
export default function Home() {
const { isConnected, connect, disconnect, address } = useCoinbaseWallet();
return (
<div>
{isConnected ? (
<div>
<p>Connected address: {address}</p>
<button onClick={disconnect}>Disconnect Wallet</button>
</div>
) : (
<button onClick={connect}>Connect Wallet</button>
)}
</div>
);
}
Testing the Setup
- Start your development server:
npm run dev
- Open your browser and navigate to
http://localhost:3000
. - Click the "Connect Wallet" button to connect your Coinbase Smart Wallet.
- After connecting, you should see your wallet address displayed on the page
Now that you have the basic setup complete, you're ready to start implementing Sub Accounts! Continue to the next section to learn how to create Sub Accounts for your users.
Next Steps
In the next section, we'll cover Creating Sub Accounts and how to integrate them into your application.