Skip to main content
This page has been updated for Wallets SDK V1. If you are using the previous version, see the previous version of this page or the V1 migration guide.

Latest Node.js SDK version - npm

Typescript SDK (@crossmint/wallets-sdk) for creating and managing Crossmint Wallets on EVM, Solana, and Stellar chains.

Prerequisites

Get a Crossmint API key from the developer console. Ensure your key has the Wallet API scopes enabled.
  • Client-side (browser): Use a client API key
  • Server-side (Node.js): Use a server API key

Installation

npm install @crossmint/wallets-sdk
# or
pnpm add @crossmint/wallets-sdk
# or
yarn add @crossmint/wallets-sdk

Quick Start

Server-side (Node.js)

import { createCrossmint, CrossmintWallets } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({ apiKey: "YOUR_SERVER_API_KEY" });
const wallets = CrossmintWallets.from(crossmint);

// Create a wallet with a server signer
const wallet = await wallets.createWallet({
  chain: "base-sepolia",
  recovery: { type: "server", secret: "RECOVERY_SECRET" },
});

console.log(wallet.address);

// Send tokens
const tx = await wallet.send("0xRecipientAddress", "usdc", "10");
console.log(tx.explorerLink);

Client-side (Headless)

For client-side usage without React, you can use the SDK directly with JWT authentication:
import { createCrossmint, CrossmintWallets } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({ apiKey: "YOUR_CLIENT_API_KEY" });
crossmint.setJwt("USER_JWT");

const wallets = CrossmintWallets.from(crossmint);

const wallet = await wallets.getWallet({ chain: "base-sepolia" });
console.log(wallet.address);
For React apps, use @crossmint/client-sdk-react-ui which provides CrossmintWalletProvider, hooks, and built-in UI for OTP and passkey flows.

Creating a Wallet

Server signer

Create a wallet with a server key as the recovery signer:
import { createCrossmint, CrossmintWallets } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({ apiKey: "YOUR_SERVER_API_KEY" });
const wallets = CrossmintWallets.from(crossmint);

const wallet = await wallets.createWallet({
  chain: "base-sepolia",
  recovery: { type: "server", secret: "RECOVERY_SECRET" },
});

console.log(wallet.address);

External wallet signer

Bring your own key (MetaMask, KMS, etc.):
const wallet = await wallets.createWallet({
  chain: "base-sepolia",
  recovery: {
    type: "external-wallet",
    address: "0xYourWalletAddress",
    onSign: async (message: string) => {
      // Sign the message with your wallet/KMS and return the signature
      return await yourWallet.signMessage({ message: { raw: message as `0x${string}` } });
    },
  },
});

Device signer (browser / React Native)

Device signers use hardware-backed P256 keys for frictionless client-side signing. They must be created on the client and can be passed to the server at wallet creation time:
// Client: generate a device signer descriptor
const { createDeviceSigner } = useWallet();
const deviceSigner = await createDeviceSigner();
// Send deviceSigner to your server
// Server: create the wallet with the device signer pre-registered
const wallet = await wallets.createWallet({
  chain: "base-sepolia",
  owner: "email:user@example.com",
  recovery: { type: "email", email: "user@example.com" },
  signers: [deviceSigner],
});
Device signers are browser and React Native only — not available in Node.js. See the Server-Side Wallet with Device Signer guide for the full pattern.

Retrieving an existing wallet

// Client-side
const wallet = await wallets.getWallet({ chain: "base-sepolia" });
// Server-side — requires a wallet locator
const wallet = await wallets.getWallet("0xWalletAddress", {
  chain: "base-sepolia",
});

Core Concepts

Signers

Wallets SDK uses a two-tier signer model:
  • Recovery signer — High-security, used for wallet recovery and adding new signers. Supports email OTP, phone OTP, external wallet, or server key.
  • Operational signer — Low-friction, used for day-to-day signing. Supports server key, external wallet, passkey, and device (browser/mobile only). For server-side (Node.js) usage, use a server or external-wallet signer.
When no operational signer is available, the recovery signer automatically serves as a fallback for signing.

Usage

Balances

const balances = await wallet.balances();

console.log(balances.nativeToken.amount);
console.log(balances.usdc.amount);

Send Tokens

const tx = await wallet.send("0xRecipient", "usdc", "100");
console.log(tx.explorerLink);

Transfers

const transfers = await wallet.transfers({
  tokens: "usdc",
  status: "successful",
});

NFTs

const nfts = await wallet.nfts({ perPage: 10, page: 1 });

Chain-Specific Transactions

import { EVMWallet, SolanaWallet, StellarWallet } from "@crossmint/wallets-sdk";

// EVM — smart contract interaction
const evmWallet = EVMWallet.from(wallet);
const tx = await evmWallet.sendTransaction({
  to: "0xContractAddress",
  abi: contractAbi,
  functionName: "mint",
  args: [1],
  value: 0n,
});

// EVM — sign a message
const sig = await evmWallet.signMessage({ message: "Hello" });

// EVM — viem public client
const client = evmWallet.getViemClient();

// Solana
const solWallet = SolanaWallet.from(wallet);
const solTx = await solWallet.sendTransaction({
  serializedTransaction: "<base64-encoded-transaction>",
});

// Stellar
const stellarWallet = StellarWallet.from(wallet);
const stellarTx = await stellarWallet.sendTransaction({
  contractId: "C...",
  method: "transfer",
  args: { to: "G...", amount: "1000000" },
});

Signer Management

// Add a new signer
await wallet.addSigner({ type: "server", secret: "SECRET" });

// List signers
const signers = await wallet.signers();
console.log(signers); // [{ type: "server", locator: "server:...", status: "success" }, ...]

// Set the active signer (required after getWallet server-side)
await wallet.useSigner({ type: "server", secret: "SECRET" });

Transaction Approval (Prepare-Only Mode)

For flows that require multi-step approval:
// Create a transaction without auto-approving
const pendingTx = await wallet.send("0xRecipient", "usdc", "10", {
  prepareOnly: true,
});
console.log(pendingTx.transactionId);

// Approve later
const result = await wallet.approve({
  transactionId: pendingTx.transactionId,
});

Signer Types

TypeUse CasePlatforms
deviceHardware-backed, no OTP. Browser and React Native only — not available in Node.js.Browser, React Native
serverServer-side automated operations (AI agents, backends).Node.js
emailOTP-based recovery signer.All
phoneOTP-based recovery signer.All
passkeyWebAuthn/FIDO2 biometric signer.Browser (EVM only)
external-walletBring-your-own key (MetaMask, KMS, etc).All

React / React Native

For React applications, use @crossmint/client-sdk-react-ui which provides wallet providers, hooks (useWallet, useWalletOtpSigner), and built-in UI for OTP and passkey flows. For React Native, see @crossmint/client-sdk-react-native-ui.

Documentation

License

Apache-2.0