Development

Coinbase Smart Wallet: account abstraction on Base

Integrate Coinbase Smart Wallet and Base App for gasless transactions, passkey auth, and 10-second onboarding. The consumer wallet stack for Base.

12 minUpdated 2026-02-28

What happens when you tell someone to "Install MetaMask" before they can use your app? 95% leave. Of the 5% who install it, half bail at "write down these 12 words."

Coinbase Smart Wallet replaces that entire flow with a fingerprint tap. Users get a wallet in 10 seconds. No extension. No seed phrase. No gas popup. Your app pays the $0.001 transaction fee so users never think about ETH.

Base App has replaced Coinbase Wallet as the consumer entry point -- a mobile app with social features, mini apps, and trading, all powered by Smart Wallet underneath. If you're building for the 26M+ monthly active users on Base, this is the integration that determines your conversion rate.

What is account abstraction?

Traditional Ethereum wallets (MetaMask, Rabby) are externally owned accounts (EOAs). They're controlled by a private key. Every transaction requires ETH for gas. Every interaction requires a signature popup.

Account abstraction (ERC-4337) replaces this with smart contract wallets that can sponsor gas (your app pays fees so users never need ETH), batch transactions (combine approve plus swap into a single click), use passkeys (authenticate with biometrics instead of seed phrases), set spending limits (programmatic rules on what the wallet can do), and recover accounts (no more "I lost my seed phrase").

Coinbase Smart Wallet is Coinbase's ERC-4337 implementation, deeply integrated with Base and powering the Base App experience.

Smart Wallet vs. EOA: when to use each

This decision depends on your users, not your preference.

Use Smart Wallet when your users are not crypto-native (social apps, games, commerce), when onboarding friction is your biggest growth killer, when you can afford to sponsor gas (roughly $0.001 per transaction on Base), or when you want maximum conversion from "visit site" to "first action."

Use MetaMask/EOA when your users are DeFi power users who already have wallets, when you need deep multi-chain support today, when users want full self-custody without trusting any third party, or when you're building for the existing crypto audience.

Use both: most production apps should support both. Let users choose. Smart Wallet for new users, EOA connection for existing crypto users. With 26M+ monthly active users on Base, you're increasingly building for the Smart Wallet audience.

How it works (architecture)

User taps "Sign Up." A passkey is created (Face ID or fingerprint). A smart contract wallet deploys on Base. User gets an address (looks like any other 0x address).

User takes an action (mint, swap, send). Your app creates the transaction. A Paymaster sponsors gas (optional). A Bundler submits the UserOperation to Base. The smart contract wallet executes the transaction. User sees "Done" -- never saw gas, never signed anything scary.

Key components: the Smart Contract Wallet is the user's onchain account (a contract, not an EOA). The Paymaster pays gas on behalf of users (Coinbase provides one, or use your own). The Bundler batches UserOperations and submits them to the network. The Passkey is a WebAuthn credential stored on the user's device (not a server).

Integration guide

Path 1: OnchainKit (fastest)

OnchainKit is Coinbase's official React component library for Base. It handles wallet connection, identity, and transactions with pre-built components. This is the recommended path for most builders.

Install

bash
npm install @coinbase/onchainkit wagmi viem@2.x @tanstack/react-query

Configure the provider

tsx
'use client';

import { OnchainKitProvider } from '@coinbase/onchainkit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { base } from 'wagmi/chains';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { coinbaseWallet } from 'wagmi/connectors';

const config = createConfig({
  chains: [base],
  connectors: [
    coinbaseWallet({
      appName: 'My Base App',
      preference: 'smartWalletOnly',
    }),
  ],
  transports: {
    [base.id]: http(),
  },
});

const queryClient = new QueryClient();

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <OnchainKitProvider
          apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
          chain={base}
        >
          {children}
        </OnchainKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}

Add the wallet connect button

tsx
import {
  ConnectWallet,
  Wallet,
  WalletDropdown,
  WalletDropdownDisconnect,
} from '@coinbase/onchainkit/wallet';
import {
  Address,
  Avatar,
  Name,
  Identity,
} from '@coinbase/onchainkit/identity';

export function WalletConnect() {
  return (
    <Wallet>
      <ConnectWallet>
        <Avatar />
        <Name />
      </ConnectWallet>
      <WalletDropdown>
        <Identity hasCopyAddressOnClick>
          <Avatar />
          <Name />
          <Address />
        </Identity>
        <WalletDropdownDisconnect />
      </WalletDropdown>
    </Wallet>
  );
}

Users click the button, authenticate with a passkey, and get a wallet. No extension install. No seed phrase.

Send a gasless transaction

tsx
import { TransactionButton } from '@coinbase/onchainkit/transaction';
import { base } from 'wagmi/chains';

const mintCall = {
  to: '0xYOUR_CONTRACT_ADDRESS' as `0x${string}`,
  data: '0x...' as `0x${string}`,
  value: 0n,
};

export function MintButton() {
  return (
    <TransactionButton
      chainId={base.id}
      calls={[mintCall]}
      text="Mint NFT"
      onSuccess={(txHash) => console.log('Minted!', txHash)}
      onError={(error) => console.error('Error:', error)}
    />
  );
}

Path 2: wagmi plus viem (more control)

If you need more control over the UX or are integrating into an existing app:

tsx
import { createConfig, http } from 'wagmi';
import { base } from 'wagmi/chains';
import { coinbaseWallet } from 'wagmi/connectors';

export const config = createConfig({
  chains: [base],
  connectors: [
    coinbaseWallet({
      appName: 'My Base App',
      preference: 'smartWalletOnly',
    }),
  ],
  transports: {
    [base.id]: http(),
  },
});
tsx
import { useConnect, useAccount, useDisconnect } from 'wagmi';

export function ConnectButton() {
  const { connect, connectors } = useConnect();
  const { address, isConnected } = useAccount();
  const { disconnect } = useDisconnect();

  if (isConnected) {
    return (
      <div>
        <p>Connected: {address}</p>
        <button onClick={() => disconnect()}>Disconnect</button>
      </div>
    );
  }

  return (
    <button onClick={() => connect({ connector: connectors[0] })}>
      Connect Wallet
    </button>
  );
}

Sponsoring gas with a Paymaster

To make transactions gasless for users, you need a Paymaster. Coinbase provides one through the Coinbase Developer Platform:

  1. Sign up at portal.cdp.coinbase.com
  2. Create a project and enable the Paymaster
  3. Configure which contracts and methods to sponsor
  4. Set spending limits (max $10/user/day, for example)

Smart Wallet handles the paymaster interaction automatically when configured at the connector level.

Passkey authentication

Passkeys are the magic that makes Smart Wallet feel native.

When a user first connects, a WebAuthn credential is created and stored on their device (Secure Enclave on Apple, TPM on Android/Windows). Future logins use biometrics (Face ID, fingerprint) or device PIN. Transaction signatures happen on-device using the passkey -- no private key ever leaves the device. Passkeys sync across devices via iCloud Keychain or Google Password Manager.

What this means for your UX: no "connect wallet" popup, just a biometric prompt. No "sign this message" popup -- transactions are signed seamlessly. No "I lost my seed phrase" support tickets -- passkeys are recoverable. Cross-device support works on phone, laptop, and tablet.

Passkeys work in all modern browsers. On mobile, they work in both native browsers and in-app webviews. The main gap: very old Android devices without biometric hardware.

Gas sponsorship: $20 per 10,000 transactions

How much does it cost to make your app free for users? Less than you think.

An ERC-20 transfer: $0.001. An NFT mint: $0.003. A DEX swap: $0.005. At $0.002 average, sponsoring gas for 1,000 users doing 10 transactions each costs $20. That's less than one Facebook ad click.

When not to sponsor: DeFi power users expect to pay gas (sponsored transactions can look suspicious to them). For high-value transactions, set limits to prevent abuse. For open mints, cap sponsored transactions per wallet to block bots.

Base App and MiniKit: build mini apps

Base App (called "Base" on App Store/Play Store) is the consumer entry point. Built on Farcaster, it mixes social features, mini apps, and trading. The big opportunity for builders: MiniKit.

What is MiniKit?

MiniKit is the SDK for building mini apps that run inside Base App and other Farcaster clients. Mini apps run within Farcaster Frames and are cross-client compatible -- they work in Base App, Warpcast, and other Farcaster clients.

Getting started

bash
npx create-onchain --mini

This scaffolds a mini app project with MiniKit pre-configured.

Key hooks

MiniKit provides hooks for the Base App environment:

  • useMiniKit -- core hook for mini app context
  • useAddFrame -- let users save your mini app
  • useAuthenticate -- authenticate users via Farcaster
  • useComposeCast -- compose Farcaster casts from your app
tsx
import { useMiniKit, useAuthenticate } from '@coinbase/onchainkit/minikit';

function MyMiniApp() {
  const { context } = useMiniKit();
  const { authenticate, user } = useAuthenticate();

  return (
    <div>
      <p>Welcome to my mini app</p>
      {!user && <button onClick={authenticate}>Sign In</button>}
      {user && <p>Hello, {user.displayName}</p>}
    </div>
  );
}

Full docs: docs.base.org/onchainkit/latest/components/minikit/overview

Why this matters

Mini apps are the distribution play. Instead of convincing users to visit your website and connect a wallet, your app lives inside Base App where millions of users already are. Think WeChat mini programs, but onchain. If your app makes sense as a lightweight experience (games, social features, quick transactions), MiniKit is the fastest path to Base App's user base.

Base App users expect mobile-first experiences. Design for small screens and touch interactions. Social context matters -- users have Farcaster profiles, so leverage social identity rather than asking for wallet connections.

Production checklist

Before shipping Smart Wallet integration to mainnet:

  • Test on Base Sepolia with real passkey flow (not just local dev)
  • Configure Paymaster spending limits per user per day
  • Handle errors gracefully -- passkey creation can fail (permissions, old browsers)
  • Add EOA fallback -- set preference to 'all' to support MetaMask users too
  • Test on mobile -- passkey UX differs between iOS and Android
  • Set up monitoring with Sonarbot to track wallet creation events and failed transactions
  • Add rate limiting to prevent gas sponsorship abuse
  • Test recovery flow -- what happens when a user gets a new device

Common issues

"Passkey creation failed": usually a permissions issue. Ensure your site is served over HTTPS (passkeys require secure context). On localhost, use https://localhost with a self-signed cert during development.

"Transaction reverted": check that your Paymaster is configured to sponsor the specific contract and method being called. Paymaster configuration is allowlist-based.

"Wallet not connecting on mobile": Smart Wallet uses a popup flow on mobile. Ensure your app doesn't block popups. Test in the actual mobile browser, not just desktop responsive mode.

"Users see two wallet options": if you set preference to 'all', users choose between Smart Wallet and Coinbase Wallet extension. Set preference to 'smartWalletOnly' for pure consumer apps where you don't want to confuse new users.

What Smart Wallet unlocks beyond login

Account abstraction isn't just a nicer login. It's a new permission model:

Session keys: approve a game session once, play without signing every move. Spending limits: give a kid a wallet with guardrails. Social recovery: trusted contacts recover an account, no seed phrase backup. Auto-payments: subscription billing, onchain. Programmable permissions: wallets that enforce business logic.

Why does this matter now? Because x402 needs wallets that can pay for API calls autonomously. Because Virtuals agents need wallets to transact on ACP. Because Bankr users need wallets that work inside X. Smart Wallet is the account layer underneath all of it.

Next steps

  1. Deploy your contract on Base if you haven't already
  2. Try the OnchainKit starter: npx create-onchain@latest scaffolds a Next.js app with Smart Wallet pre-configured
  3. Read the Coinbase Smart Wallet docs for the full API reference
  4. Explore Base App for distribution to the consumer audience

The apps that win are the ones nobody realizes are onchain. Smart Wallet and Base App make that possible.