Using Sub Accounts

Once you’ve set up your Wagmi config and created your Smart Wallet connection, you can use it to perform various operations like signing messages and sending transactions. In this section, we’ll cover how to send a simple transaction using your Sub Account.

What you’ll achieve

By the end of this guide, you will:

  • Know how to sign a message with your user’s Sub Account
  • Know how to send a transaction with your user’s Sub Account

Skip ahead

If you want to skip ahead and just get the final code, you can find it here:

Sub Account Starter Template Demohttps://github.com/base/demos/tree/master/smart-wallet/sub-accounts-demo

Sign a Message

To sign a message with a Sub Account, we’ll use Wagmi’s useSignMessage hook. Here’s how to implement message signing:

app/page.tsx
'use client'

import { useAccount, useConnect, useDisconnect, useSignMessage } from 'wagmi'

function App() {
  const account = useAccount()
  const { connectors, connect, status, error } = useConnect()
  const { disconnect } = useDisconnect()
  const { signMessage, data: signData } = useSignMessage()
  return (
    <>
      <div>
        <h2>Account</h2>

        <div>
          Status: {account.status}
          <br />
          Sub Account Address: {JSON.stringify(account.addresses)}
          <br />
          ChainId: {account.chainId}
        </div>

        {account.status === 'connected' && (
          <button type="button" onClick={() => disconnect()}>
            Disconnect
          </button>
        )}
      </div>

      <div>
        <h2>Connect</h2>
        {connectors
          .filter((connector) => connector.name === 'Coinbase Wallet')
          .map((connector) => (
            <button
              key={connector.uid}
              onClick={() => connect({ connector })}
              type="button"
            >
              Sign in with Smart Wallet
            </button>
          ))}
        <div>{status}</div>
        <div>{error?.message}</div>

        <div>Sign Message</div>
        <button
          type="button"
          onClick={() => signMessage({ message: 'Hello World' })}
        >
          Sign Message
        </button>
        <div>{signData}</div>
      </div>
    </>
  )
}

export default App

The signed message data will be available in the signData variable after the user approves the signature request.

Send a Transaction

To send transactions with a Sub Account, we’ll use Wagmi’s useSendTransaction hook. Remember that transactions will be limited by the Spend Permissions we configured in the setup:

app/page.tsx
'use client'

import { parseEther } from 'viem'
import { useAccount, useConnect, useDisconnect, useSendTransaction, useSignMessage } from 'wagmi'

function App() {
  const account = useAccount()
  const { connectors, connect, status, error } = useConnect()
  const { disconnect } = useDisconnect()
  const { sendTransactionAsync, data } = useSendTransaction()
  return (
    <>
      <div>
        <h2>Account</h2>

        <div>
          Status: {account.status}
          <br />
          Sub Account Address: {JSON.stringify(account.addresses)}
          <br />
          ChainId: {account.chainId}
        </div>

        {account.status === 'connected' && (
          <button type="button" onClick={() => disconnect()}>
            Disconnect
          </button>
        )}
      </div>

      <div>
        <h2>Connect</h2>
        {connectors
          .filter((connector) => connector.name === 'Coinbase Wallet')
          .map((connector) => (
            <button
              key={connector.uid}
              onClick={() => connect({ connector })}
              type="button"
            >
              Sign in with Smart Wallet
            </button>
          ))}
        <div>{status}</div>
        <div>{error?.message}</div>
        <div>Send Transaction</div>
        <button type="button" onClick={async () => sendTransactionAsync({
          to: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
          value: parseEther('0.001'),
        })}>
          Send Transaction
        </button>
        <div>{data && "Transaction sent successfully! 🎉"}</div>
        <div>{data}</div>
      </div>
    </>
  )
}

export default App

The transaction parameters include:

  • to: The recipient address
  • value: The amount of ETH to send (converted from ETH to Wei using parseEther)

The transaction data will be available in the data variable after it succeeds on the network.

Remember that transactions will only succeed if they:

  1. Don’t exceed the allowance specified in spendPermissionConfig
  2. Use the permitted token (in this case, native ETH)
  3. Fall within the configured time period

Complete Example

Here’s a complete example combining account connection, message signing, and transaction sending:

app/page.tsx
'use client'

import { parseEther } from 'viem'
import { useAccount, useConnect, useDisconnect, useSendTransaction, useSignMessage } from 'wagmi'

function App() {
  const account = useAccount()
  const { connectors, connect, status, error } = useConnect()
  const { disconnect } = useDisconnect()
  const { sendTransactionAsync, data } = useSendTransaction()
  const { signMessage, data: signData } = useSignMessage()
  return (
    <>
      <div>
        <h2>Account</h2>

        <div>
          Status: {account.status}
          <br />
          Sub Account Address: {JSON.stringify(account.addresses)}
          <br />
          ChainId: {account.chainId}
        </div>

        {account.status === 'connected' && (
          <button type="button" onClick={() => disconnect()}>
            Disconnect
          </button>
        )}
      </div>

      <div>
        <h2>Connect</h2>
        {connectors
          .filter((connector) => connector.name === 'Coinbase Wallet')
          .map((connector) => (
            <button
              key={connector.uid}
              onClick={() => connect({ connector })}
              type="button"
            >
              Sign in with Smart Wallet
            </button>
          ))}
        <div>{status}</div>
        <div>{error?.message}</div>
        <div>Send Transaction</div>
        <button type="button" onClick={async () => sendTransactionAsync({
          to: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
          value: parseEther('0.001'),
        })}>
          Send Transaction
        </button>
        <div>{data && "Transaction sent successfully! 🎉"}</div>
        <div>{data}</div>

        <div>Sign Message</div>
        <button
          type="button"
          onClick={() => signMessage({ message: 'Hello World' })}
        >
          Sign Message
        </button>
        <div>{signData}</div>
      </div>
    </>
  )
}

export default App

This example provides a complete interface for users to:

  1. Connect their Smart Wallet (Sign in with Smart Wallet button)
  2. View their Sub Account address
  3. Sign messages
  4. Send transactions
  5. Disconnect their wallet

All transactions will be automatically limited by the Spend Permissions configured in your Wagmi setup.

Additional Resources