Overview
The EVMWallet class extends the base Wallet with EVM-specific functionality including:
Custom transaction execution
Message signing
EIP-712 typed data signing
Smart contract interactions
Viem integration
Create an EVM Wallet Instance
Cast a base Wallet to EVMWallet for EVM-specific operations:
import { EVMWallet } from "@crossmint/wallets-sdk" ;
// Assuming you have a wallet instance
const evmWallet = EVMWallet . from ( wallet );
The EVMWallet.from() method will throw an error if the wallet is not on an EVM chain.
Send Custom Transactions
Execute custom transactions on EVM chains.
Method Signature
evmWallet . sendTransaction ( params : EVMTransactionInput ): Promise < Transaction >
Send Raw Transaction
Send a serialized transaction:
const tx = await evmWallet . sendTransaction ({
transaction: "0x..." , // Serialized transaction hex
});
console . log ( tx . hash );
console . log ( tx . explorerLink );
Send with Call Data
Send a transaction with explicit call data:
const tx = await evmWallet . sendTransaction ({
to: "0xContractAddress..." ,
value: 0 n , // Value in wei (bigint)
data: "0x..." , // Encoded function call
});
Send with ABI
Use contract ABI for type-safe contract interactions:
const ERC20_ABI = [
{
name: "transfer" ,
type: "function" ,
inputs: [
{ name: "to" , type: "address" },
{ name: "amount" , type: "uint256" },
],
outputs: [{ name: "" , type: "bool" }],
stateMutability: "nonpayable" ,
},
];
const tx = await evmWallet . sendTransaction ({
to: "0xTokenContractAddress..." ,
abi: ERC20_ABI ,
functionName: "transfer" ,
args: [ "0xRecipient..." , 1000000 n ], // 1 USDC (6 decimals)
value: 0 n ,
});
Prepare-Only Mode
Create a transaction without executing:
const preparedTx = await evmWallet . sendTransaction ({
to: "0xContractAddress..." ,
data: "0x..." ,
options: {
experimental_prepareOnly: true ,
},
});
console . log ( preparedTx . transactionId );
// Approve later
const completedTx = await wallet . approve ({
transactionId: preparedTx . transactionId ,
});
With Custom Signer
const tx = await evmWallet . sendTransaction ({
to: "0xContractAddress..." ,
data: "0x..." ,
options: {
experimental_signer: "external-wallet:0x..." ,
},
});
Parameters
Recipient address (contract or EOA)
Value to send in wei (default: 0n)
Contract ABI for encoding function calls
Function name to call (requires abi)
Function arguments (requires abi and functionName)
Serialized transaction (alternative to above fields)
Sign Messages
Sign arbitrary messages with the wallet’s private key.
Method Signature
evmWallet . signMessage ( params : SignMessageInput ): Promise < Signature >
Basic Usage
const signResult = await evmWallet . signMessage ({
message: "Hello, blockchain!" ,
});
console . log ( signResult . signature ); // "0x..."
console . log ( signResult . signatureId ); // Signature ID for tracking
Prepare-Only Mode
const preparedSig = await evmWallet . signMessage ({
message: "Hello, blockchain!" ,
options: {
experimental_prepareOnly: true ,
},
});
console . log ( preparedSig . signatureId );
// Approve later
const completedSig = await wallet . approve ({
signatureId: preparedSig . signatureId ,
});
console . log ( completedSig . signature );
Sign Typed Data (EIP-712)
Sign structured data following the EIP-712 standard.
Method Signature
evmWallet . signTypedData ( params : SignTypedDataInput ): Promise < Signature >
Usage
const signResult = await evmWallet . signTypedData ({
domain: {
name: "My DApp" ,
version: "1" ,
chainId: 137 n , // Polygon
verifyingContract: "0xContractAddress..." ,
},
types: {
Person: [
{ name: "name" , type: "string" },
{ name: "wallet" , type: "address" },
],
Mail: [
{ name: "from" , type: "Person" },
{ name: "to" , type: "Person" },
{ name: "contents" , type: "string" },
],
},
primaryType: "Mail" ,
message: {
from: {
name: "Alice" ,
wallet: "0xAlice..." ,
},
to: {
name: "Bob" ,
wallet: "0xBob..." ,
},
contents: "Hello, Bob!" ,
},
chain: "polygon" ,
});
console . log ( signResult . signature );
Permit Example
Sign an ERC20 permit for gasless approvals:
const permitSignature = await evmWallet . signTypedData ({
domain: {
name: "USD Coin" ,
version: "2" ,
chainId: 137 n ,
verifyingContract: "0xUSDCContractAddress..." ,
},
types: {
Permit: [
{ name: "owner" , type: "address" },
{ name: "spender" , type: "address" },
{ name: "value" , type: "uint256" },
{ name: "nonce" , type: "uint256" },
{ name: "deadline" , type: "uint256" },
],
},
primaryType: "Permit" ,
message: {
owner: wallet . address ,
spender: "0xSpenderAddress..." ,
value: 1000000 n ,
nonce: 0 n ,
deadline: BigInt ( Math . floor ( Date . now () / 1000 ) + 3600 ),
},
chain: "polygon" ,
});
Parameters
EIP-712 domain information
types
Record<string, Array<{name: string, type: string}>>
required
Type definitions for the structured data
The primary type being signed
message
Record<string, any>
required
The data to sign
The EVM chain (e.g., “polygon”, “ethereum”)
Create signature without executing
Viem Integration
Get a Viem public client for advanced blockchain interactions.
Method Signature
evmWallet . getViemClient ( params ?: { transport? : HttpTransport }): PublicClient
Usage
import { http } from "viem" ;
// Get client with default transport
const viemClient = evmWallet . getViemClient ();
// Or provide custom transport
const customClient = evmWallet . getViemClient ({
transport: http ( "https://polygon-rpc.com" ),
});
// Use Viem client for read operations
const blockNumber = await viemClient . getBlockNumber ();
const balance = await viemClient . getBalance ({ address: wallet . address });
Complete Example: NFT Minting
Here’s a full example of minting an NFT using the EVM wallet:
import { CrossmintWallets , createCrossmint , EVMWallet } from "@crossmint/wallets-sdk" ;
// Initialize
const crossmint = createCrossmint ({ apiKey: "..." });
const crossmintWallets = CrossmintWallets . from ( crossmint );
// Get wallet
const wallet = await crossmintWallets . getOrCreateWallet ({
chain: "polygon" ,
signer: { type: "email" , email: "[email protected] " , onAuthRequired: async ( ... ) => { ... } },
});
// Cast to EVM wallet
const evmWallet = EVMWallet . from ( wallet );
// Mint NFT
const NFT_CONTRACT_ABI = [
{
name: "mint" ,
type: "function" ,
inputs: [{ name: "to" , type: "address" }],
outputs: [],
stateMutability: "payable" ,
},
];
const mintTx = await evmWallet . sendTransaction ({
to: "0xNFTContractAddress..." ,
abi: NFT_CONTRACT_ABI ,
functionName: "mint" ,
args: [ wallet . address ],
value: 0 n , // Mint price in wei
});
console . log ( `NFT minted! Transaction: ${ mintTx . explorerLink } ` );
Supported EVM Chains
The SDK supports all major EVM chains including:
Ethereum (mainnet, sepolia)
Polygon (mainnet, amoy)
Base (mainnet, sepolia)
Arbitrum (mainnet, sepolia)
Optimism (mainnet, sepolia)
Avalanche (mainnet, fuji)
BNB Chain
And many more…
Next Steps
Wallet Operations Learn about common wallet operations
Delegated Signers Add multiple signers to a wallet
Solana Wallets Learn about Solana-specific operations
Stellar Wallets Learn about Stellar-specific operations