Crossmint’s SDK has different signer types with different environment requirements:
Signer Type
Environment
Use Case
Email / Passkey
Browser, React Native (WebView)
User-facing apps
API Key
Server (Node.js)
Automated / custodial flows
External Wallet
Any
Delegated signing
Email and Passkey signers require a browser environment. They use an iframe for TEE (Trusted Execution Environment) authentication. This won’t work in Node.js tests or server-side code.
Crossmint uses WebView to provide browser APIs in React Native. The SDK works the same way, but requires WebView-based components.See Crossmint’s React Native SDK for setup.
Copy
// The signing code is identical - WebView handles the browser environmentconst result = await solanaWallet.sendTransaction({ serializedTransaction: unsignedTx,});
For automated or custodial flows where your server controls signing:
API Key signers are custodial — Crossmint signs transactions automatically without user interaction. Use this for treasury management or automated operations.
Copy
import { RebelfiClient } from '@rebelfi/sdk';import { CrossmintWallets, createCrossmint, SolanaWallet } from '@crossmint/wallets-sdk';const rebelfi = new RebelfiClient({ apiKey: process.env.REBELFI_API_KEY });// Initialize Crossmint with server API keyconst crossmint = createCrossmint({ apiKey: process.env.CROSSMINT_SERVER_API_KEY, // sk_...});const crossmintWallets = CrossmintWallets.from(crossmint);async function automatedSupply( walletLocator: string, // e.g., "email:[email protected]:solana" strategyId: number, amount: string, tokenAddress: string) { // 1. Get the Crossmint wallet const wallet = await crossmintWallets.getWallet(walletLocator, { chain: 'solana', }); // 2. Create supply operation const operation = await rebelfi.operations.supply({ walletAddress: wallet.address, strategyId, amount, tokenAddress, }); // 3. Sign and broadcast (API key signer = automatic approval) const solanaWallet = SolanaWallet.from(wallet); const result = await solanaWallet.sendTransaction({ serializedTransaction: operation.transactions[0].unsignedTransaction, }); // 4. Submit hash back to RebelFi await rebelfi.transactions.submitHash({ operationId: operation.operationId, txHash: result.hash, }); return { operationId: operation.operationId, txHash: result.hash };}
Cause: Using email/passkey signer in Node.js or server environment.Solution: Use API Key signer for server-side, or run in browser/WebView environment.
Transaction expired
Cause: Too much time between creating operation and signing.Solution: Sign and submit within 60 seconds of creating the operation.
Invalid signature
Cause: Wrong wallet signing the transaction.Solution: Ensure the Crossmint wallet address matches the walletAddress passed to the operation.