# Get Started with Coinbase Smart Wallet

In this tutorial, I'll walk you through the process of setting up [Coinbase Smart Wallet](https://www.coinbase.com/en-au/wallet/smart-wallet) inside a front-end application. By the end of the tutorial, we'll build a simple Next.js application where users can:

1. Connect to your application via Coinbase Smart Wallet.
    
2. Perform transactions from their newly created wallet.
    
3. 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:

![Coinbase Smart Wallet demo](https://cdn.hashnode.com/res/hashnode/image/upload/v1717642277559/d297f93c-9045-49b8-a85a-301307cea509.gif align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">🤠</div>
<div data-node-type="callout-text">Try the live demo: <a target="_blank" rel="noopener noreferrer nofollow" href="https://polygon-coinbase-smart-wallet.vercel.app/" style="pointer-events: none">https://polygon-coinbase-smart-wallet.vercel.app/</a></div>
</div>

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.

%[https://github.com/jarrodwatts/polygon-coinbase-smart-wallet] 

For those starting from scratch, create a simple Next.js app using `npx create next-app`:

```bash
pnpm create next-app@latest coinbase-smart-wallet-demo --typescript --tailwind --eslint
```

Next, install the [thirdweb React SDK](https://portal.thirdweb.com/typescript/v5) which includes the [`ConnectButton`](https://portal.thirdweb.com/typescript/v5/react/components/ConnectButton) component:

```bash
# 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](https://portal.thirdweb.com/account/api-keys) To get one:

1. Head to the **Settings** tab on the [thirdweb dashboard](https://thirdweb.com/dashboard/settings/api-keys).
    
2. Click **\+ Create API Key**.
    
3. Give your key a name and set the allowed domains.
    
4. Click **Next** and copy your app's **Client ID**.
    

![thirdweb API key setup demo](https://cdn.hashnode.com/res/hashnode/image/upload/v1717634294110/64c7741c-70fa-47ee-8dc2-21521cd4b9cb.png align="center")

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**](https://nextjs.org/docs/pages/building-your-application/configuring/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:

1. Wrapping our application in the `ThirdwebProvider`.
    
2. Adding the `ConnectButton` component.
    
3. Showcasing a simple test transaction with a `TransactionButton` component.
    

### Wrapping the App in the ThirdwebProvider

The thirdweb SDK uses a [provider pattern](https://react.dev/reference/react/createContext#provider), meaning we wrap our application with a `ThirdwebProvider` component to use thirdweb SDK features throughout our code.

First, wrap your application in the [`ThirdwebProvider`](https://portal.thirdweb.com/typescript/v5/react/ThirdwebProvider) component like so:

```typescript
// 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`](https://portal.thirdweb.com/typescript/v5/react/components/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:

1. Importing what chain we want to use from the `thirdweb/chains` package.
    
2. Rendering the `ConnectButton` from the thirdweb SDK.
    
    * Providing your thirdweb client ID to the `createThirdwebClient` function.
        
    * Calling the `createWallet` function with `com.coinbase.wallet` (Coinbase Wallet).
        
    * Setting `smartWalletOnly` to disable the Coinbase Wallet Browser Extension.
        

```typescript
// 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],
          }),
        ]}
      />
    </>
  );
}
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Ensure you replace the placeholder value with <strong><em>your </em></strong>thirdweb client ID!</div>
</div>

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/](http://localhost:3000/) in your browser and try it out:

![Coinbase Smart Wallet demo](https://cdn.hashnode.com/res/hashnode/image/upload/v1717642277559/d297f93c-9045-49b8-a85a-301307cea509.gif align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Depending on what device you are using (Windows, Mac, Android, etc.) the options to save your passkey will be different.</div>
</div>

### 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](https://thirdweb.com/thirdweb.eth/DropERC1155) using the thirdweb dashboard. This [ERC-1155](https://docs.openzeppelin.com/contracts/3.x/erc1155) NFT smart contract ([deployed here](https://thirdweb.com/polygon/0x04bE3B7a1a034297331A661c5b5E838264Ba0E58)) 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:

1. Deploy an [Edition Drop smart contract](https://thirdweb.com/thirdweb.eth/DropERC1155).
    
2. Select the **NFTs** tab and [lazy mint](https://portal.thirdweb.com/contracts/explore/pre-built-contracts/edition-drop#lazy-minting-nfts) metadata for an NFT.
    
3. Set up a free, public [**claim phase**](https://portal.thirdweb.com/contracts/explore/pre-built-contracts/edition-drop#setting-claim-phases) for your NFT.
    

Beneath our `ConnectButton`, let's add a [`TransactionButton`](https://portal.thirdweb.com/references/typescript/v5/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:

```typescript
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:

```typescript
// 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`:

```typescript
// 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:

```typescript
<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>
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">🤓</div>
<div data-node-type="callout-text">You can get your smart contract address from the thirdweb dashboard. Ensure you replace the placeholder value in the above code snippet.</div>
</div>

Let's test out this transaction button on [http://localhost:3000/](http://localhost:3000/) now:

![Account abstraction without a paymaster](https://cdn.hashnode.com/res/hashnode/image/upload/v1717654836272/7ddf3912-dec3-4efd-8346-45aaaced4162.gif align="center")

😱 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](https://www.erc4337.io/docs/paymasters/introduction) are a feature of [**ERC-4337 account abstraction**](https://blog.jarrodwatts.com/what-is-account-abstraction-and-how-does-eip-4337-work)**,** 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](https://blog.thirdweb.com/changelog/easy-coinbase-smart-wallet-integration-with-eip-5792-hooks/) for us to accomplish this sponsorship. Let's first import the one we're going to use, [`useSendCalls`](https://portal.thirdweb.com/references/typescript/v5/eip5792/useSendCalls):

```typescript
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:

```typescript
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:

```typescript
<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](https://thirdweb.com/dashboard/settings/billing) 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](https://portal.thirdweb.com/connect/account-abstraction/infrastructure).

### 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](https://thirdweb.com/dashboard/connect/account-abstraction). 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.
    

![thirdweb Account abstraction sponsorship rules](https://cdn.hashnode.com/res/hashnode/image/upload/v1717657167204/1ad2184b-2702-4b7f-a9c9-cf940659059d.png align="center")

Alright! We're finally done! Let's see the final demo in action:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1717659617166/ba75a08e-ff10-407a-8cf0-5e3a8ae74fa4.gif align="center")

## 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](https://x.com/jarrodWattsDev)
