V1 is a major release with breaking changes. Read through the relevant sections before upgrading your packages.
Terminology changes
V1 renames several concepts. Use this table as a find-and-replace checklist across your codebase.| Old term | New term | Notes |
|---|---|---|
adminSigner | Recovery signer | Recovery signers are high-friction (OTP-based). They can also sign transactions as a fallback when no operational signer is available. |
delegatedSigner | Signer (operational) | Day-to-day signers: device, passkey, server, external-wallet. |
getOrCreateWallet() | createWallet() + getWallet() | Separate calls. getWallet() throws WalletNotAvailableError if no wallet exists. |
addDelegatedSigner() | addSigner() | Signature also changed — accepts config objects, not just locator strings. |
experimental_activity() | transfers(params) | Name and signature changed. tokens and status params are optional. |
experimental_ prefix | Removed | experimental_prepareOnly → prepareOnly, experimental_signer → signer, experimental_approval → approval, experimental_nfts() → nfts(), experimental_transactions() → transactions(), experimental_transaction(id) → transaction(id). |
customAuth / experimental_setCustomAuth | setJwt() | setJwt(jwt) replaces the old experimental_setCustomAuth({ jwt, email, externalWalletSigner }). |
useWalletEmailSigner | useWalletOtpSigner | Now works for both email and phone OTP signers. |
createOnLogin.signer | createOnLogin.recovery | The signer field in createOnLogin is now recovery. |
createOnLogin.delegatedSigners | createOnLogin.signers | Array of operational signers to register at wallet creation. |
Activity type | Transfers type | Find-and-replace import. |
Client-side migration (React / React Native)
1. Update packages
Update all@crossmint packages to V1 versions:
2. Update createOnLogin in your provider
The signer field is now recovery, and delegatedSigners is now signers.
Device signers are now the default operational signer. If you do not specify
signers, a device signer is created automatically on EVM chains. Solana does not support device signers yet — the recovery signer is used as a fallback for signing.3. Replace getOrCreateWallet with getWallet + createWallet
getOrCreateWallet has been removed. Use getWallet to retrieve an existing wallet. If it throws WalletNotAvailableError, call createWallet.
4. Replace customAuth with setJwt
If you use a third-party auth provider (BYOA), replace experimental_setCustomAuth with setJwt.
5. Remove experimental_ prefixes
All experimental_ prefixes have been removed from wallet methods and options.
6. Replace useWalletEmailSigner with useWalletOtpSigner
The useWalletEmailSigner hook has been replaced by useWalletOtpSigner, which works for both email and phone OTP flows.
7. Replace addDelegatedSigner with addSigner
The method name and signature have changed. addSigner now accepts signer config objects in addition to locator strings.
8. Remove Farcaster and Dynamic login references
Farcaster sign-in and Dynamic wallet login have been removed entirely. If you used either, migrate to an alternative auth method.- Remove
"farcaster"fromloginMethodsinCrossmintAuthProvider. - Remove
"web3"fromloginMethods. - Remove any
FarcasterSignIn,Web3AuthFlow, orDynamicWalletProviderimports.
9. Understand device signers
Device signers are a new signer type backed by the device’s hardware security module (Secure Enclave on mobile, IndexedDB on web). They are the default operational signer for EVM wallets — no OTP is required for day-to-day signing. Key points:- No code change is needed if you want the default device signer behavior.
- Call
wallet.needsRecovery()to check if the device signer needs to be re-established (e.g. after the user switches devices). - Call
wallet.recover()to trigger recovery using the recovery signer. - Solana does not support device signers yet. The recovery signer is used as a fallback.
10. Use useSigner() for non-device signers
If you need to sign with a non-device signer (e.g. passkey, external wallet, server), call wallet.useSigner() first.
useSigner() only accepts signer config objects — locator strings (e.g. "external-wallet:0x...") are no longer accepted.11. Update external wallet signer to use onSign
V1 replaces chain-specific signing props (provider, viemAccount, onSignTransaction, onSignStellarTransaction) with a single unified onSign callback. When using an external-wallet signer (via useSigner), both address and onSign are required.
Registration vs. usage: When registering an external-wallet signer (in
createWallet({ signers: [...] }) or addSigner()), only address is needed — no onSign. The onSign callback is only required when actively signing via useSigner().Server-side migration (Node.js)
1. Update packages
2. Replace getOrCreateWallet with createWallet / getWallet
3. Update signer configuration
The oldsigner field (admin signer) is now recovery, and delegatedSigners is now signers.
4. Migrate from API key signer to server signer
If you were using the API key as a signer for server-side operations, migrate to the new server signer. Server signers use deterministic key derivation from a secret you control.5. Remove experimental_ prefixes
Same as client-side — remove all experimental_ prefixes from method names and option fields.
REST API migration
The REST API changes in V1 are additive — there are no breaking changes to existing endpoints. The main addition is server signer support.Switch to the 2025-06-09 API version
Server signers require the 2025-06-09 API version. Update your base URL:
Create a wallet with a server signer
Previously, server-managed signing used theexternal-wallet type. V1 introduces a dedicated server signer type.
The REST API accepts
address (not secret) for server signers. Derive the address from your secret in your backend before passing it to the API.Submit approvals with a server signer
Use theserver:<address> locator format when submitting approvals.
REST ↔ SDK signer type mapping
Use this table to map between REST API signer types and SDK signer config objects.| REST API signer type | REST locator format | SDK signer config |
|---|---|---|
evm-keypair / solana-keypair | external-wallet:<address> | { type: "external-wallet", address, provider } |
server | server:<address> | { type: "server", secret: "..." } |
evm-passkey | passkey:<credentialId> | { type: "passkey" } |
| N/A (client-only) | device:<publicKey> | { type: "device" } |
evm-email-otp | email:<email> | { type: "email", email: "..." } |
evm-phone-otp | phone:<number> | { type: "phone", phone: "..." } |
Checklist
Use this checklist to verify your migration is complete:- Updated all
@crossmintpackages to V1 versions - Replaced
getOrCreateWalletwithcreateWallet/getWallet - Updated
createOnLogin:signer→recovery,delegatedSigners→signers - Replaced
experimental_setCustomAuthwithsetJwt(if using BYOA) - Removed all
experimental_prefixes from methods and options - Replaced
useWalletEmailSignerwithuseWalletOtpSigner - Replaced
addDelegatedSignerwithaddSigner - Removed Farcaster / Dynamic login references (if applicable)
- Updated REST API calls to use
serversigner type (if applicable) - Searched codebase for old terms:
adminSigner,getOrCreateWallet,delegatedSigner,experimental_
Next steps
Error handling
Handle WalletNotAvailableError and other common errors
Add a signer
Register operational signers on your wallet

