Crossmint’s embedded wallets allow you to create and manage blockchain wallets for your users seamlessly. Users can interact with blockchain applications without needing to understand seed phrases, private keys, or wallet extensions.
Overview
Embedded wallets provide:
Email/Social login - Users sign in with familiar methods
Multi-chain support - One wallet across EVM and Solana chains
Custodial & non-custodial options - Choose the right model for your use case
No seed phrases - Better UX for non-crypto users
Installation
npm install @crossmint/wallets-sdk @crossmint/common-sdk-base
Quick Start
Initialize the Crossmint SDK
import { createCrossmint } from "@crossmint/common-sdk-base" ;
import { CrossmintWallets } from "@crossmint/wallets-sdk" ;
const crossmint = createCrossmint ({
apiKey: "YOUR_API_KEY" ,
});
const wallets = CrossmintWallets . from ( crossmint );
Create or get a wallet
// Get or create a wallet for the authenticated user
const wallet = await wallets . getOrCreateWallet ({
chain: "ethereum-sepolia" ,
signer: {
type: "api-key" ,
locator: "user-id-123" , // Your user's identifier
},
});
console . log ( "Wallet address:" , wallet . address );
console . log ( "Chain:" , wallet . chain );
Check the wallet balance
const balances = await wallet . getBalance ();
console . log ( "Native balance:" , balances . native . raw );
console . log ( "Token balances:" , balances . tokens );
Creating Wallets
Client-Side Creation
Create wallets in your frontend application:
const wallet = await wallets . getOrCreateWallet ({
chain: "ethereum-sepolia" ,
signer: {
type: "api-key" ,
locator: "[email protected] " ,
},
});
Server-Side Creation
For more control, create wallets from your backend:
// Backend code with server API key
const wallet = await wallets . createWallet ({
chain: "polygon-amoy" ,
signer: {
type: "api-key" ,
locator: `user: ${ userId } ` ,
},
});
// Return wallet address to frontend
return { address: wallet . address };
Use getOrCreateWallet() to ensure you don’t create duplicate wallets for the same user.
Multi-Chain Wallets
Create wallets on different chains for the same user:
// EVM chains
const ethWallet = await wallets . getOrCreateWallet ({
chain: "ethereum-sepolia" ,
signer: { type: "api-key" , locator: "user-123" },
});
const polygonWallet = await wallets . getOrCreateWallet ({
chain: "polygon-amoy" ,
signer: { type: "api-key" , locator: "user-123" },
});
// Solana
const solanaWallet = await wallets . getOrCreateWallet ({
chain: "solana-devnet" ,
signer: { type: "api-key" , locator: "user-123" },
});
EVM Chains Ethereum, Polygon, Base, Arbitrum, Optimism, and more
Solana Solana mainnet and devnet support
Sending Transactions
EVM Transactions
import { EVMWallet } from "@crossmint/wallets-sdk" ;
const evmWallet = EVMWallet . from ( wallet );
const result = await evmWallet . sendTransaction ({
to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" ,
value: "0.01" , // in ETH
});
console . log ( "Transaction hash:" , result . hash );
console . log ( "Explorer link:" , result . explorerLink );
Solana Transactions
import { SolanaWallet } from "@crossmint/wallets-sdk" ;
import { Transaction , SystemProgram , PublicKey } from "@solana/web3.js" ;
const solanaWallet = SolanaWallet . from ( wallet );
// Create your transaction
const transaction = new Transaction (). add (
SystemProgram . transfer ({
fromPubkey: new PublicKey ( solanaWallet . address ),
toPubkey: new PublicKey ( "recipient-address" ),
lamports: 1000000 , // 0.001 SOL
})
);
// Serialize and send
const serialized = transaction . serialize (). toString ( "base64" );
const result = await solanaWallet . sendTransaction ({
serializedTransaction: serialized ,
});
console . log ( "Transaction hash:" , result . hash );
Checking Balances
Retrieve native and token balances:
const balances = await wallet . getBalance ();
// Native currency (ETH, SOL, etc.)
console . log ( "Native balance:" , {
raw: balances . native . raw ,
formatted: balances . native . formatted ,
symbol: balances . native . symbol ,
});
// Token balances
for ( const token of balances . tokens ) {
console . log ( ` ${ token . symbol } : ${ token . formatted } ` );
}
Signing Messages
Sign arbitrary messages for authentication or verification:
// EVM message signing
const evmWallet = EVMWallet . from ( wallet );
const signature = await evmWallet . signMessage ({
message: "Sign this message to authenticate" ,
});
console . log ( "Signature:" , signature . signature );
Transaction History
Retrieve transaction history for a wallet:
const transactions = await wallet . getTransactions ();
for ( const tx of transactions ) {
console . log ( "Transaction ID:" , tx . id );
console . log ( "Status:" , tx . status );
console . log ( "Hash:" , tx . onChain ?. txId );
console . log ( "Explorer:" , tx . onChain ?. explorerLink );
}
Delegated Signers
Allow third parties to sign transactions on behalf of a wallet:
const result = await wallet . addDelegatedSigner ({
signer: {
type: "api-key" ,
locator: "backend-service" ,
},
});
console . log ( "Delegated signer added:" , result . signer );
Delegated signers have full control over the wallet. Only add trusted parties as delegated signers.
Best Practices
Use meaningful locators
Use consistent, meaningful identifiers for your users: locator : `user: ${ userId } ` // Good
locator : ` ${ randomString } ` // Bad
Handle errors gracefully
try {
const wallet = await wallets . getOrCreateWallet ({
chain: "ethereum-sepolia" ,
signer: { type: "api-key" , locator: userId },
});
} catch ( error ) {
console . error ( "Failed to create wallet:" , error );
// Show user-friendly error message
}
Cache wallet addresses
Store wallet addresses in your database to avoid repeated API calls: // First time
const wallet = await wallets . getOrCreateWallet ({ ... });
await db . users . update ( userId , { walletAddress: wallet . address });
// Later
const address = await db . users . get ( userId ). walletAddress ;
React Integration
For React applications, use the UI SDK:
npm install @crossmint/client-sdk-react-ui
import { CrossmintProvider , useWallet } from "@crossmint/client-sdk-react-ui" ;
function WalletInfo () {
const { wallet , isLoading } = useWallet ();
if ( isLoading ) return < div > Loading wallet... </ div > ;
return (
< div >
< p > Address: { wallet ?. address } </ p >
< p > Chain: { wallet ?. chain } </ p >
</ div >
);
}
function App () {
return (
< CrossmintProvider apiKey = "YOUR_API_KEY" >
< WalletInfo />
</ CrossmintProvider >
);
}
Next Steps
Custom Transactions Build and send custom blockchain transactions
Multi-Chain Support Work with multiple blockchain networks