ChangeNotifier-based controllers instead of React hooks. Controllers can be used directly (headless) or accessed through the widget tree via providers.
CrossmintClient
The top-level facade for the Crossmint SDK. Provides access to auth, wallets, and all sub-clients.Properties
The configuration this client was built with.
Authentication sub-client — email OTP, OAuth, wallet sign-in, session persistence, JWT refresh.
Wallet sub-client — create, list, and read Crossmint-hosted wallets (EVM, Solana, Stellar) and their signers.
Verifiable credentials sub-client — issue, query, and verify credentials.
Orders sub-client — checkout orders and mint/purchase flows.
Tokens sub-client — metadata and balances for tokens held by wallets.
Users sub-client — user profile lookups and updates.
The effective app ID — explicit [CrossmintClientConfig.appId] if set, otherwise the value auto-resolved from platform metadata during [initialize]. May be
null until [initialize] has completed.Whether [initialize] has completed successfully.
Whether [dispose] has been called. Once disposed, the client cannot be reused — construct a new one.
The shared hidden signer bridge controller, lazily constructed on first access. Powers non-custodial email/phone signing inside a hidden WebView.
The auth storage adapter resolved during construction — either the one passed via [CrossmintClientConfig.authStorage] or the default
flutter_secure_storage-backed implementation.The HTTP transport resolved during construction. Shared by every sub-client; injects the live JWT via a closure so token refresh works without rebuilding dependencies.
Methods
Creates a [CrossmintWalletController] bound to this client.
Builds a new [HiddenSignerBridgeRuntimeController] instance — used internally by [hiddenSignerBridgeController]. Override the bridge
config to point at a custom signer URL (e.g. for testing).Builds a new [CrossmintExportSignerBridgeRuntimeController] instance. Used internally by [exportSignerBridgeController].
createEvmNonCustodialSigner(bridge, signerType, signerLocator, address, onAuthRequired)
CrossmintEvmNonCustodialSigner
Builds a non-custodial EVM signer bound to an existing [HiddenSignerBridge]. Produces secp256k1 signatures inside the WebView without exposing keys to Dart.
createSolanaNonCustodialSigner(bridge, signerType, signerLocator, address, onAuthRequired)
CrossmintSolanaNonCustodialSigner
Builds a non-custodial Solana signer bound to an existing [HiddenSignerBridge]. Produces ed25519 signatures inside the WebView.
createStellarNonCustodialSigner(bridge, signerType, signerLocator, address, onAuthRequired)
CrossmintStellarNonCustodialSigner
Builds a non-custodial Stellar signer bound to an existing [HiddenSignerBridge]. Produces ed25519 signatures inside the WebView.
createEvmWallet(wallet, recoverySigner, signer, additionalSigners, deviceSignerKeyStorage, onAuthRequired)
CrossmintEvmWallet
Wraps a server-issued [CrossmintWallet] in a runtime [CrossmintEvmWallet].
createSolanaWallet(wallet, recoverySigner, signer, additionalSigners, deviceSignerKeyStorage, onAuthRequired)
CrossmintSolanaWallet
Wraps a server-issued [CrossmintWallet] in a runtime [CrossmintSolanaWallet].
createStellarWallet(wallet, recoverySigner, signer, additionalSigners, deviceSignerKeyStorage, onAuthRequired)
CrossmintStellarWallet
Wraps a server-issued [CrossmintWallet] in a runtime [CrossmintStellarWallet].
Builds a hardware-backed device signer for an existing server signer.
Builds an external-wallet EVM signer that delegates to a user-supplied [CrossmintExternalWalletSignCallback]. Use for wallets owned by the user (e.g. MetaMask, Rainbow) where the SDK only needs to request signatures.
createSolanaExternalWalletSigner(address, signerLocator, onSign)
CrossmintSolanaExternalWalletSigner
Builds an external-wallet Solana signer that delegates to a user-supplied [CrossmintExternalWalletSignCallback].
createStellarExternalWalletSigner(address, signerLocator, onSign)
CrossmintStellarExternalWalletSigner
Builds an external-wallet Stellar signer that delegates to a user-supplied [CrossmintExternalWalletSignCallback].
Builds a passkey approval signer. The caller provides
onSign — a callback that performs the WebAuthn / platform-native passkey assertion and returns a [CrossmintPasskeySignResult]. Native platform passkey support is pending (Stage 2); today every passkey signer requires an explicit callback or CrossmintSignerException(code: passkeyCallbackMissing) is thrown during signing.Releases the signer bridges and auth client, then marks the client as disposed. Safe to call multiple times. After disposal, construct a new [CrossmintClient] rather than reusing this one.
Validates configuration and prepares the client for use.
Usage
CrossmintAuthClient
Manages authentication state and login flows. Exposes state viaValueListenable and Stream for reactive UI updates.
Properties
The current auth state snapshot.
Reactive handle on [state] — suitable for [ValueListenableBuilder].
Stream of auth-state changes. Emits on every state mutation.
Methods
Reads any persisted session from [CrossmintAuthStorage] and applies it to the client. Safe to call once per app launch — prefer using the result of
CrossmintClient.initialize which calls this internally.Opens the Crossmint-hosted OAuth flow for [provider] (Google, Twitter, etc.). The response comes back through [CrossmintAuthCallbackRouter] — make sure it is started before calling this.
Requests the Crossmint API to send an email OTP to [email]. Returns a challenge that [confirmEmailOtp] completes.
Submits an email OTP challenge — pass the
emailId from the challenge and the token the user entered. Returns true on success.Completes an OAuth flow from a deep-link callback URI. Normally invoked by [CrossmintAuthCallbackRouter]; call directly only for custom routing.
Completes an OAuth flow from a one-time secret (SSR / server-mediated callbacks). Returns
true on success.Starts wallet-based authentication. Returns a challenge that the wallet must sign. [type] is
'evm' or 'solana'.Completes wallet-based authentication with the signed challenge.
Returns the current session (JWT + metadata), or
null if not signed in. Does not hit the network — reads from in-memory state.Returns the authenticated user’s profile. Caches the result; pass
forceRefresh: true to bypass the cache and refetch.Signs the user out — clears persisted storage, cached session/user, and POSTs to the Crossmint (or custom) logout endpoint.
Sets a custom JWT for “Bring Your Own Auth” (BYOA) flows.
Usage
CrossmintWalletController
Manages wallet lifecycle — creation, loading, signing, and OTP flows. ExtendsChangeNotifier for reactive UI updates.
Properties
The underlying client — exposed for code that needs direct access to sub-clients (auth, orders, credentials, etc.).
The configuration this controller was built with.
OTP controller for non-custodial email/phone signer challenges.
Read-only observation surface for the underlying wallet state. Advanced consumers can subscribe to wallet / status changes directly via this [Listenable] while still routing all mutations through the controller’s public API (
getWallet, createWallet, refresh, clear, …).The currently-loaded wallet, or
null if none is loaded.Current wallet lifecycle status.
The auth-required callback the controller wires into every signer it builds. Exposed so apps building signers manually can share the same OTP-handling path.
Shortcut to [CrossmintWalletOtpController.pendingChallenge].
Shortcut to [CrossmintWalletOtpController.challengeListenable].
Returns the currently-loaded wallet or throws [CrossmintWalletException] when none is loaded.
Methods
Looks up an existing wallet and stores the result in controller state. Returns
null when no wallet matches. Listeners fire on state changes.Deprecated: use [getWallet] instead.
Creates a new wallet and stores it in controller state. Validates passkey signers up-front via [crossmintValidatePasskeySigners] and fires [CrossmintWalletLifecycleCallbacks.onWalletCreationStart] if set.
Ensures a wallet is loaded, creating one if configured to do so.
Re-fetches the currently-loaded wallet from the API. Returns
null when nothing is loaded.Drops the loaded wallet and any pending OTP challenge. Call during sign-out.
Shortcut to [CrossmintWalletOtpController.sendOtp].
Shortcut to [CrossmintWalletOtpController.verifyOtp].
Shortcut to [CrossmintWalletOtpController.reject].
Wraps the currently-loaded wallet as a runtime [CrossmintEvmWallet]. Throws [CrossmintWalletException] if no wallet is loaded.
Wraps the currently-loaded wallet as a runtime [CrossmintSolanaWallet]. On Solana, device signer support depends on the wallet type and is validated server-side. A default device signer is not auto-injected for Solana; it is registered reactively and falls back to the recovery signer when the server rejects it.
Wraps the currently-loaded wallet as a runtime [CrossmintStellarWallet].
Builds a runtime EVM wallet backed by a hardware-backed device signer. Use for low-friction, day-to-day signing with keys in Secure Enclave / Android Keystore.
createEvmWalletWithNonCustodialSigner(signerType, signerLocator, address, bridge)
CrossmintEvmWallet
Builds a runtime EVM wallet backed by a non-custodial email/phone signer. Requires [CrossmintWalletHost] (or
CrossmintWalletProvider) mounted in the widget tree.createSolanaWalletWithNonCustodialSigner(signerType, signerLocator, address, bridge)
CrossmintSolanaWallet
Builds a runtime Solana wallet backed by a non-custodial email/phone signer. Requires a mounted wallet host.
createStellarWalletWithNonCustodialSigner(signerType, signerLocator, address, bridge)
CrossmintStellarWallet
Builds a runtime Stellar wallet backed by a non-custodial email/phone signer. Requires a mounted wallet host.
Builds a runtime Stellar wallet backed by a hardware device signer.
Builds a runtime EVM wallet backed by a user-owned external wallet (e.g. MetaMask). The caller supplies [onSign] to perform signatures.
Builds a runtime Solana wallet backed by a user-owned external wallet.
Builds a runtime Stellar wallet backed by a user-owned external wallet.
Builds a runtime EVM wallet backed by a passkey signer.
Builds a runtime Solana wallet backed by a passkey signer. See [createEvmWalletWithPasskeySigner] for passkey selection semantics.
Builds a runtime Stellar wallet backed by a passkey signer. See [createEvmWalletWithPasskeySigner] for passkey selection semantics.
The controller also provides chain-specific convenience factories that build
the signer for you:
createEvmWalletWithDeviceSigner,
createEvmWalletWithPasskeySigner,
createEvmWalletWithExternalWalletSigner,
createEvmWalletWithNonCustodialSigner, and their Solana / Stellar
counterparts.Usage
CrossmintWallets
Stateless convenience facade for wallet operations. Mirrors theCrossmintWallets entry point used by the TS, Kotlin, and Swift SDKs. For reactive state management (e.g. listening to wallet changes in a widget tree), use CrossmintWalletController instead.
Unlike the controller, the facade does not auto-resolve signer configs. Callers must provide fully-resolved configs (e.g. include the email address in CrossmintEmailSignerConfig, or pre-create a device signer via createDeviceSigner()).
Constructor
Creates a
CrossmintWallets facade backed by client.Methods
Retrieves an existing wallet and returns a typed runtime wallet.
Creates a new wallet and returns a typed runtime wallet.
Creates a device signer descriptor.
Creates a passkey signer configuration.
Usage
Wallet Methods
The runtime wallet instances returned by the controller provide methods for token transfers, balances, signing, and more.Properties
| Property | Type | Description |
|---|---|---|
wallet.client | CrossmintClient | Top-level Crossmint client shared by all wallet operations. |
wallet.wallet | CrossmintWallet | Server-issued wallet snapshot backing this runtime instance. |
wallet.deviceSignerKeyStorage | DeviceSignerKeyStorage? | Storage backend for hardware-backed device signer keys. |
wallet.onAuthRequired | CrossmintSignerAuthRequiredCallback? | Callback invoked when a signer operation requires user authentication. |
wallet.defaultChain | String | Chain identifier used when the wallet snapshot has no explicit chain. |
wallet.chain | String | Blockchain this wallet operates on (falls back to [defaultChain]). |
wallet.address | String | On-chain address of the wallet. |
wallet.owner | String? | Owner identifier associated with the wallet, if any. |
wallet.recovery | CrossmintSignerConfig? | Recovery (admin) signer config parsed from the wallet’s backend state. |
wallet.locator | String | Unique wallet locator used for API calls. |
wallet.signer | CrossmintWalletApprovalSigner? | Currently active approval signer, or null if none is selected. |
wallet.additionalSigners | List<CrossmintWalletApprovalSigner> | Secondary signers available alongside the primary [signer]. |
wallet.needsRecovery | bool | Whether the wallet needs recovery (signer registration) before the next transaction. |
wallet.canExportPrivateKey | bool | Whether the active signer supports private-key export. |
Methods
| Method | Description |
|---|---|
wallet.useSigner(signer) | Sets the active signer for this wallet. Accepts a signer config object; the locator is inferred internally. Works for device, non-custodial, external-wallet, and passkey signers. |
wallet.balances(tokens) | Returns the wallet balances — always includes USDC and the native token. Pass additional [tokens] to request extra token balances. |
wallet.transactions() | Lists transaction summaries for this wallet. |
wallet.transaction(transactionId) | Retrieves details for a specific transaction by ID. |
wallet.approve(request) | Approves a pending transaction or signature request. |
wallet.nfts(page, perPage) | Returns the wallet’s NFTs (paginated). |
wallet.fund(request) | Initiates a funding (on-ramp) request for this wallet. |
wallet.transfers(page, perPage, tokens, status) | Reads transfer history for this wallet (unstable API). |
wallet.send(request) | Sends a token transfer and waits for confirmation. |
wallet.sendToken(to, token, amount) | Convenience wrapper around [send] for simple token transfers. |
wallet.signers() | Lists all signers registered on this wallet with their current status. |
wallet.removeSigner(signerLocator) | Removes a signer from the wallet by its locator. |
wallet.signerIsRegistered(signerLocator) | Checks whether a signer with the given locator is registered. |
wallet.isSignerApproved(signerLocator) | Checks whether a registered signer is approved and usable. |
wallet.addSigner(signer) | Registers a new signer on the wallet and approves the registration. |
wallet.preAuthIfNeeded() | Awaits any in-flight recovery; if _needsRecovery is set and no recovery is in-flight, starts one and awaits it. Concurrent callers coalesce onto the same future so a single recovery runs per wallet. |
wallet.recover() | Runs device-signer recovery: resumes any pending operation or registers a new device signer using the recovery signer. Returns early if the device signer is already approved on-chain. |
wallet.exportPrivateKey(bridge) | Exports the wallet’s private key via the export signer bridge. |
wallet.approveTransactionAndWait(transactionId) | Approves a pending transaction and polls until it reaches a terminal state. |
wallet.transactionApprovalPayload(transaction, pendingApproval, signer) | Extracts the signable payload from a pending transaction approval. |
wallet.completeApprovedTransaction(transaction) | Polls a transaction until it reaches a terminal state and attaches explorer links. |
wallet.waitForTransaction(transactionId) | Polls a transaction by ID until it succeeds or fails. |
wallet.walletSnapshotForSigners() | Fetches a fresh wallet snapshot to inspect registered signers. |
wallet.requireActiveSigner(operation) | Returns the active signer or throws if none is selected. |
CrossmintEvmWallet—sendTransaction(),signMessage(),signTypedData()CrossmintSolanaWallet—sendTransaction()CrossmintStellarWallet—sendTransaction()
Usage
controller.currentWallet holds the loaded domain model. Signing, balance, and transaction methods live on the runtime wallet returned by controller.createEvmWallet() (or createSolanaWallet / createStellarWallet).

