Skip to main content

Introduction

The user wallet is the root of every agent stablecoin flow. It is non-custodial and owned by the end user, with an email (or passkey) recovery signer that stays in the user’s control. Your agent is later authorized to use the wallet as a signer with explicit spending limits, and that access can be revoked at any time. Subsequent logins from the same user return the same wallet — creation is idempotent.

Prerequisites

  • A staging Crossmint client API key from the Crossmint Console. In staging, all scopes are enabled by default.
  • The user must be authenticated. If you have not set up authentication, see the Agents overview first.

Steps

1

Install the SDK

npm install @crossmint/client-sdk-react-ui
2

Wrap your app with the Crossmint providers

Set up CrossmintProvider, CrossmintAuthProvider, and CrossmintWalletProvider at the root of your app. Pass createOnLogin to CrossmintWalletProvider so the SDK creates the user’s wallet automatically as soon as they sign in, with an email-recovery.
"use client";

import {
    CrossmintAuthProvider,
    CrossmintProvider,
    CrossmintWalletProvider,
} from "@crossmint/client-sdk-react-ui";

export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <CrossmintProvider apiKey={process.env.NEXT_PUBLIC_CROSSMINT_CLIENT_API_KEY}>
            <CrossmintAuthProvider loginMethods={["email", "google"]}>
                <CrossmintWalletProvider
                    createOnLogin={{
                        chain: "base-sepolia",
                        recovery: { type: "email" },
                    }}
                >
                    {children}
                </CrossmintWalletProvider>
            </CrossmintAuthProvider>
        </CrossmintProvider>
    );
}
3

Read the wallet from any component

Use useWallet() anywhere below the provider to access the wallet. The hook exposes a status field you can use to render a loading state during creation.
"use client";

import { useWallet } from "@crossmint/client-sdk-react-ui";

export function WalletSection() {
    const { wallet, status } = useWallet();

    if (status === "in-progress" || status === "not-loaded") {
        return <p>Creating wallet…</p>;
    }

    return <code>{wallet?.address}</code>;
}
When status is loaded, wallet.address is the user’s wallet address and the wallet is ready for delegation.

Manual Creation (Non-React or Server-Side)

If you are not using the React SDK — for example, creating the wallet server-side from a custom auth backend — use the wallets SDK directly:
import { createCrossmint, CrossmintWallets } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({
    apiKey: process.env.CROSSMINT_SERVER_SIDE_API_KEY,
});
const wallets = CrossmintWallets.from(crossmint);

const wallet = await wallets.createWallet({
    chain: "base-sepolia",
    owner: `userId:${userId}`,
    signer: { type: "email", email: userEmail },
});
owner scopes the wallet to your authenticated user. Pass the same identifier on subsequent getWallet calls to resolve it.

Common Gotchas

Wallet creation is idempotent — repeated calls return the same wallet. You do not need to guard against double-creation in your UI.
The signer chosen at creation time is the wallet’s root. Agents are added on top as scoped delegates and can be revoked, but the root recovery signer is permanent.
On the React SDK, the user is identified by the auth provider’s session. On the server, you must explicitly scope ownership with owner: userId:<id> so the wallet resolves correctly on later getWallet calls.

What Is Next

With the user’s wallet created, the next step is to add your agent as a signer so it can sign on the user’s behalf. Continue to Authorize the Agent. For a full app you can clone and test end-to-end, see the Stablecoin Wallet Quickstart.