Documentation Index Fetch the complete documentation index at: https://docs.cloud.coinbase.com/llms.txt
Use this file to discover all available pages before exploring further.
Learn how to integrate CDP wallets as a wallet provider with the Gelato Bundler for sponsored user operations.
Prerequisites
A free CDP Portal account and project
Node.js 22+
A node package manager installed (i.e., npm, pnpm, or yarn)
Basic familiarity with React and TypeScript
Configured your domain in CDP Portal (see below)
How to configure your domain in CDP Portal
Step 1: Access CDP Portal Navigate to the Security Configuration in CDP Portal, and click Add domain to include your local app. Step 2: Add your domain
For local development: Use http://localhost:3000 (or your preferred port)
For production: Use your actual domain (e.g., https://yourapp.com)
For production apps, only add your actual production domain. Do not add localhost to production CDP projects as malicious apps running locally could impersonate your frontend and abuse your project credentials.
Step 3: Save your changes Click Add domain again to save your changes. You should see your domain listed in the CDP Portal dashboard. The allowlist will take effect immediately upon saving.
A Gelato account with an app and API key generated from Paymaster & Bundler > API Keys
Install the required CDP packages:
# npm
npm install @coinbase/cdp-react @coinbase/cdp-hooks @coinbase/cdp-core viem
Set up .env file
Set the environment variables in your .env.local file: NEXT_PUBLIC_PROJECT_ID = your_coinbase_cdp_project_id
NEXT_PUBLIC_GELATO_API_KEY = your_gelato_api_key
Import Dependencies
import { CDPReactProvider } from "@coinbase/cdp-react" ;
import { AuthButton } from "@coinbase/cdp-react/components/AuthButton" ;
import { useCurrentUser , useEvmAddress } from "@coinbase/cdp-hooks" ;
import { toViemAccount } from "@coinbase/cdp-core" ;
import { baseSepolia } from "viem/chains" ;
import { createPublicClient , http } from "viem" ;
import {
createBundlerClient ,
toCoinbaseSmartAccount ,
} from "viem/account-abstraction" ;
Configure React provider
Set up the CDP React Provider in your app: "use client" ;
import { CDPReactProvider } from "@coinbase/cdp-react" ;
function Providers ({ children } : { children : React . ReactNode }) {
return (
< CDPReactProvider
config = { {
projectId: process . env . NEXT_PUBLIC_PROJECT_ID as string ,
ethereum: {
createOnLogin: "eoa" ,
},
appName: "Your App Name" ,
} }
>
{ children }
</ CDPReactProvider >
);
}
Create Bundler Client
Set up your component to use Coinbase CDP hooks and create a bundler client with Gelato integration: "use client" ;
import { AuthButton } from "@coinbase/cdp-react/components/AuthButton" ;
import { useCurrentUser , useEvmAddress } from "@coinbase/cdp-hooks" ;
import { toViemAccount } from "@coinbase/cdp-core" ;
import { baseSepolia } from "viem/chains" ;
import { createPublicClient , http } from "viem" ;
import {
createBundlerClient ,
toCoinbaseSmartAccount ,
} from "viem/account-abstraction" ;
export default function Home () {
const { evmAddress } = useEvmAddress ();
const { currentUser } = useCurrentUser ();
const createAccount = async () => {
if ( ! currentUser ?. evmAccounts ) return ;
const viemAccount = await toViemAccount ( currentUser ?. evmAccounts [ 0 ]);
const client = createPublicClient ({
chain: baseSepolia ,
transport: http (),
});
const account = await toCoinbaseSmartAccount ({
client ,
owners: [ viemAccount ],
version: "1.1" ,
});
const bundlerClient = createBundlerClient ({
client: client ,
transport: http (
`https://api.gelato.digital/bundlers/ ${ baseSepolia . id } /rpc?apiKey= ${ process . env . NEXT_PUBLIC_GELATO_API_KEY } &sponsored=true`
),
});
console . log ( "Bundler client created:" , bundlerClient );
console . log ( "Smart account address:" , account . address );
};
return (
< div >
< AuthButton />
< div > { evmAddress } </ div >
< button onClick = { createAccount } > Create Account </ button >
</ div >
);
}
Send User Operations
Send sponsored user operations using the bundler client: const sendUserOperation = async () => {
const response = await bundlerClient . sendUserOperation ({
account ,
calls: [
{
to: account . address ,
value: BigInt ( 0 ),
data: "0x" ,
},
],
maxFeePerGas: BigInt ( 0 ),
maxPriorityFeePerGas: BigInt ( 0 ),
});
console . log ( "User operation response:" , response );
};