In this tutorial, I'll walk you through the process of setting up Coinbase Smart Wallet inside a front-end application. By the end of the tutorial, we'll build a simple Next.js application where users can:
Connect to your application via Coinbase Smart Wallet.
Perform transactions from their newly created wallet.
Pay no gas fees! Thanks to the power of paymasters to cover user's gas fees.
Below is a quick demo video of what we'll build:
If it sounds like you're in the right place, great! Let's get started!
Setting Up the Project
If you prefer to start from the complete code, the full source code is available on GitHub below, with instructions in the README on how to get started locally.
For those starting from scratch, create a simple Next.js app using npx create next-app
:
pnpm create next-app@latest coinbase-smart-wallet-demo --typescript --tailwind --eslint
Next, install the thirdweb React SDK which includes the ConnectButton
component:
# Ensure you run the command from the coinbase-smart-wallet-demo directory
pnpm i thirdweb
thirdweb API Key
To instantiate the thirdweb React SDK, you'll need a thirdweb API key To get one:
Head to the Settings tab on the thirdweb dashboard.
Click + Create API Key.
Give your key a name and set the allowed domains.
Click Next and copy your app's Client ID.
To keep things brief for the tutorial, I'll store my thirdweb client ID in plain text, however, you should keep the values safe, using environment variables.
Nice! All our setup is done. This gives us everything we need to build our app.
Integrating Coinbase Smart Wallet
We'll break down the Coinbase Smart Wallet integration into three steps:
Wrapping our application in the
ThirdwebProvider
.Adding the
ConnectButton
component.Showcasing a simple test transaction with a
TransactionButton
component.
Wrapping the App in the ThirdwebProvider
The thirdweb SDK uses a provider pattern, meaning we wrap our application with a ThirdwebProvider
component to use thirdweb SDK features throughout our code.
First, wrap your application in the ThirdwebProvider
component like so:
// File: src/app/layout.tsx
import { ThirdwebProvider } from "thirdweb/react";
export default function RootLayout({ children }) {
return (
<ThirdwebProvider>
<body>{children}</body>
</ThirdwebProvider>
);
}
Adding the Connect Wallet Button
The thirdweb SDK includes a ConnectButton
component that opens a modal and allows users to connect their wallets. We'll use it to show the Coinbase Smart Wallet prompt.
Using the code below, we can render a "Connect Wallet" button that prompts the user to connect to our application using Coinbase Smart Wallet, by:
Importing what chain we want to use from the
thirdweb/chains
package.Rendering the
ConnectButton
from the thirdweb SDK.Providing your thirdweb client ID to the
createThirdwebClient
function.Calling the
createWallet
function withcom.coinbase.wallet
(Coinbase Wallet).Setting
smartWalletOnly
to disable the Coinbase Wallet Browser Extension.
// File: /src/app/page.tsx
"use client"; // thirdweb SDK doesn't support server-side rendering yet.
import { createThirdwebClient } from "thirdweb"; // Create the thirdweb client with your client ID
import { ConnectButton } from "thirdweb/react"; // The component we can prompt the user to connect their wallet with
import { createWallet } from "thirdweb/wallets"; // Function to specify we want to use Coinbase smart wallet
import { polygon } from "thirdweb/chains"; // Import the the blockchain you want to use
export default function Home() {
return (
<>
<ConnectButton
client={createThirdwebClient({
clientId: "your-thirdweb-client-id-goes-here",
})}
wallets={[
createWallet("com.coinbase.wallet", {
walletConfig: {
// Specify we do not want coinbase wallet browser extension support, just smart wallet
options: "smartWalletOnly",
},
chains: [polygon],
}),
]}
/>
</>
);
}
That's all we need for our Coinbase Smart Wallet integration! ๐ To see it in action, run pnpm run dev
and visit http://localhost:3000/ in your browser and try it out:
Submitting Transactions from Coinbase Smart Wallet
Next, let's showcase a simple smart contract interaction with this connected wallet.
For this tutorial, I've deployed a simple Edition Drop smart contract using the thirdweb dashboard. This ERC-1155 NFT smart contract (deployed here) allows users to mint NFTs for free; perfect for us to showcase Coinbase Smart Wallet.
If you want to follow the same steps, you can:
Deploy an Edition Drop smart contract.
Select the NFTs tab and lazy mint metadata for an NFT.
Set up a free, public claim phase for your NFT.
Beneath our ConnectButton
, let's add a TransactionButton
so users can submit the transaction of minting an NFT from the drop from their Coinbase Smart Wallet.
First, import some relevant functions and components we'll be using from thirdweb:
import { TransactionButton, useActiveAccount } from "thirdweb/react";
import { claimTo } from "thirdweb/extensions/erc1155";
import { getContract } from "thirdweb";
Let's also abstract out the chain and thirdweb client into variables:
// You can safely place these *outside* of the component
const thirdwebClient = createThirdwebClient({
clientId: "your-thirdweb-client-id-goes-here",
});
const chainToUse = polygon;
Get the address of the connected Coinbase Smart Wallet using useActiveAccount
:
// Place this *within* the component
const account = useActiveAccount();
Then, render the TransactionButton
component beneath the existing ConnectButton
component. We can use the getContract
function to connect to our smart contract, and call the claimTo
function to claim/mint an NFT from the drop:
<TransactionButton
transaction={() =>
claimTo({
contract: getContract({
client: thirdwebClient,
chain: chainToUse,
address: "0x-your-smart-contract-address-goes-here",
}),
quantity: BigInt(1), // Mint 1 NFT
to: account?.address, // To the connected Coinbase Smart Wallet address
tokenId: BigInt(0), // Of NFT with token ID of 0
})
}
payModal={false} // Disable the FIAT on-ramp dialogue (optional)
>
Mint NFT
</TransactionButton>
Let's test out this transaction button on http://localhost:3000/ now:
๐ฑ Oh no! Our users don't have any funds in their wallets to pay for these gas fees... if only there was a way to cover our user's gas fees somehow! ๐
Sponsoring User Gas Fees with a Paymaster
Paymasters are a feature of ERC-4337 account abstraction, which is how Coinbase Smart Wallet works under the hood (a topic for another blog post).
They allow the gas fee of a transaction to be "sponsored" (paid for) by a different wallet than the one submitting the transaction; typically, the developer of the application sponsors the gas fees of user transactions.
The thirdweb SDK provides specific EIP-5792 hooks for us to accomplish this sponsorship. Let's first import the one we're going to use, useSendCalls
:
import { useSendCalls } from "thirdweb/wallets/eip5792";
Then, let's refactor the claiming code we wrote previously into a new, separate function, so we can include some paymaster logic:
async function sendSponsoredTransaction() {
// Our existing claim code placed here in a claimTx variable
const claimTx = claimTo({
contract: getContract({
client: thirdwebClient,
chain: chainToUse,
address: "0x-your-smart-contract-address-goes-here",
}),
quantity: BigInt(1),
to: account?.address,
tokenId: BigInt(0),
});
// End existing code
return await sendCalls({
calls: [claimTx], // We can even put multiple transactions here
capabilities: {
// We cover the gas fees of the transaction for the user!
paymasterService: {
// Docs: https://portal.thirdweb.com/connect/account-abstraction/infrastructure
url: `https://${chainToUse.id}.bundler.thirdweb.com/${thirdwebClient.clientId}`,
},
},
});
}
Finally, modify the TransactionButton
from earlier to call the sendSponderedTransaction
function, instead of directly calling the claimTo
function, like so:
<TransactionButton transaction={() => sendSponsoredTransaction()}>
Mint NFT
</TransactionButton>
Sponsoring Transactions on Mainnet
On testnets such as Base Sepolia (baseSepolia
in the thirdweb chains package), it's free to cover the gas fees of users with the thirdweb SDK.
To sponsor transactions on mainnet environments, however, real funds are being used. Therefore, you need to provide a credit card on the billing tab of the thirdweb dashboard to pay for these fees. Note: you don't need to upgrade to the growth tier.
You can read more details on thirdweb's bundler documentation.
Configuring Sponsorship Rules
When dealing with real funds (if you're using mainnet), you want to ensure you are only covering the fees of specific transactions that you want to sponsor, not just any transaction!
Thankfully, thirdweb makes this easy to configure from the dashboard within the account abstraction configuration section. This allows you to specify exactly what chains, smart contracts, and wallets you want to cover the gas fees for.
For example, I configured my sponsorship rules to:
Only sponsor transactions on the Polygon chain.
Only sponsor transactions interacting with my NFT smart contract.
Alright! We're finally done! Let's see the final demo in action:
Wrapping Up
That's it! We've built a simple application where anybody can mint an NFT for free; without setting up a wallet, writing down seed phrases, or paying any gas fees!
Got questions or feedback? Reach out to me on Twitter @jarrodwattsdev