crossmint_flutter 0.1.2 copy "crossmint_flutter: ^0.1.2" to clipboard
crossmint_flutter: ^0.1.2 copied to clipboard

Flutter SDK for Crossmint wallets, authentication, signers, embedded checkout, and verifiable credentials. Headless-first — you own the UI.

Crossmint Flutter SDK

The Flutter SDK for integrating Crossmint wallets, authentication, checkout, and verifiable credentials into your mobile app
Explore the docs »

View Example App · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Package Overview
  3. Getting Started
  4. Embedded Checkout
  5. Demo Applications
  6. Building the SDK Locally
  7. Documentation
  8. Known Limitations
  9. Contact

About The Project #

The Crossmint Flutter SDK brings the full power of the Crossmint platform to Flutter mobile apps. It is the Flutter counterpart to the Crossmint SDK for React and React Native.

The SDK is headless-first: you own the app UI, while the SDK provides client surfaces, runtime wallet helpers, auth callback wiring, a hidden signer runtime, and native device-signer integration. Optional UI components are available for common flows like authentication forms and OTP prompts.

Why Crossmint? #

  • Quick Integration: Get up and running in minutes with a single package dependency
  • Developer-First: Build end-to-end blockchain solutions without deep Web3 expertise
  • Secure: Enterprise-grade security with Secure Enclave / Android Keystore device signers
  • Fiat-First: Enable users to participate in Web3 without cryptocurrency via embedded checkout
  • Free to Start: Start developing at no cost

Core Features #

  • Embedded wallets: Create and manage EVM, Solana, and Stellar wallets
  • Authentication: Email OTP, OAuth (Google, Twitter), wallet-based sign-in, and session management
  • Signers: Email, phone, device, external wallet, passkey, and server signers
  • Embedded checkout: Credit card and crypto payments via a drop-in WebView widget
  • Verifiable credentials: Issue, present, and verify on-chain credentials

Package Overview #

Most apps should depend only on the main SDK package:

  • crossmint_flutter: The main Flutter SDK — auth, wallets, signers, checkout, and credentials.

The SDK is composed of several internal packages that you typically do not need to depend on directly:

  • crossmint_core: Pure Dart base abstractions (no Flutter or external dependencies)
  • crossmint_auth: Authentication domain logic
  • crossmint_wallets: Wallet domain logic
  • crossmint_verifiable_credentials: Verifiable credentials helpers
  • crossmint_device_signer: Native plugin for on-device key storage (Secure Enclave / Android Keystore)

Getting Started #

Prerequisites #

  • Flutter mobile app targeting iOS and/or Android
  • Flutter 3.41+ and Dart 3.11+
  • A Crossmint client key (get one here)
  • An app callback scheme for OAuth flows on mobile

Installation #

Add the SDK to your project:

flutter pub add crossmint_flutter

Quickstart #

Initialize the SDK, restore any existing session, and start the OAuth callback router early in app startup:

import 'package:flutter/widgets.dart';
import 'package:crossmint_flutter/crossmint_client.dart';
import 'package:crossmint_flutter/crossmint_flutter_auth.dart';
import 'package:crossmint_flutter/crossmint_flutter_controllers.dart';

late final CrossmintClient client;
late final CrossmintWalletController walletController;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  client = CrossmintClient(
    config: const CrossmintClientConfig(
      apiKey: String.fromEnvironment('CROSSMINT_API_KEY'),
      appScheme: String.fromEnvironment('CROSSMINT_APP_SCHEME'),
    ),
  );

  await client.initialize();
  await client.auth.restoreSession();

  final authRouter = CrossmintAuthCallbackRouter(auth: client.auth);
  await authRouter.start();

  walletController = client.createWalletController(
    const CrossmintWalletControllerConfig(
      showOtpSignerPrompt: true,
    ),
  );

  runApp(MyApp(client: client, walletController: walletController));
}

Wrap your app tree in CrossmintWalletHost so the hidden signer WebView bridge has a place to run:

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.client, required this.walletController});

  final CrossmintClient client;
  final CrossmintWalletController walletController;

  @override
  Widget build(BuildContext context) {
    return CrossmintWalletHost(
      client: client,
      walletController: walletController,
      child: /* your app tree */,
    );
  }
}

Required for non-custodial signers. Email and phone signers run inside a hidden WebView that the SDK manages for you. CrossmintWalletHost (headless, re-exported from crossmint_flutter_controllers.dart) — or CrossmintWalletProvider from crossmint_flutter_ui.dart if you want the opt-in default UI — must be mounted in the widget tree. Without one, wallet.useSigner(CrossmintEmailSignerConfig(...)) throws CrossmintSignerException(code: nonCustodialBridgeHostNotMounted). Passkey signers sign via onSignWithPasskey callbacks and do not require a host.

Once a wallet is loaded (e.g. via walletController.getWallet(...) or walletController.createWallet(...)), interact with it using the CrossmintWallets facade:

final wallets = CrossmintWallets.from(
  client,
  onAuthRequired: (signerType, signerLocator, needsAuth, sendOtp, verifyOtp, reject) async {
    // Show your OTP prompt UI, then call verifyOtp(code) or reject().
    await sendOtp();
    final code = await showMyOtpDialog();
    await verifyOtp(code);
  },
);
final wallet = await wallets.getWallet(chain: 'base-sepolia');
await wallet.useSigner(CrossmintEmailSignerConfig(email: 'user@example.com'));
await wallet.sendToken('0xRecipient', 'usdc', '1.0');

For more details, see the Crossmint documentation.

Embedded Checkout #

The SDK includes CrossmintEmbeddedCheckout, a drop-in WebView widget for credit card and crypto payments. It supports fiat and crypto payment methods, custom theming, and can delegate crypto signing to a runtime wallet:

import 'package:crossmint_flutter/crossmint_flutter_ui.dart';
import 'package:crossmint_flutter/crossmint_flutter_wallets.dart';

final config = CrossmintCheckoutConfig(
  order: CrossmintCheckoutNewOrder.typed(
    lineItems: [
      CrossmintCheckoutLineItem.collection(
        collectionLocator: 'crossmint:your-collection-id',
        callData: const {'quantity': 1},
      ),
    ],
  ),
  payment: CrossmintCheckoutPayment(
    crypto: CrossmintCheckoutCryptoPayment(
      enabled: true,
      payer: CrossmintEvmWalletCheckoutPayer(
        wallet: wallet,
        supportedChains: const ['base-sepolia'],
      ),
    ),
    defaultMethodType: CrossmintCheckoutDefaultMethod.crypto,
  ),
);

// In your widget tree:
CrossmintEmbeddedCheckout(
  apiKey: 'ck_staging_...',
  config: config,
  onOrderUpdated: (order) => debugPrint('Order: ${order.orderId}'),
);

Fiat-only checkout #

For a pure credit-card / Apple Pay / Google Pay flow, omit the crypto payer and pass an email recipient so Crossmint mints into a managed wallet. Swap in CrossmintCheckoutWalletRecipient when minting directly to a user-owned external wallet address instead:

final config = CrossmintCheckoutConfig(
  order: CrossmintCheckoutNewOrder.typed(
    lineItems: [
      CrossmintCheckoutLineItem.collection(
        collectionLocator: 'crossmint:your-collection-id',
      ),
    ],
    recipient: const CrossmintCheckoutEmailRecipient(email: 'user@example.com'),
  ),
  payment: const CrossmintCheckoutPayment(
    fiat: CrossmintCheckoutFiatPayment(enabled: true, defaultCurrency: 'USD'),
    defaultMethodType: CrossmintCheckoutDefaultMethod.fiat,
  ),
);

Physical goods #

For a merchandise-style line item, use CrossmintCheckoutPhysicalRecipient with a shipping address:

final config = CrossmintCheckoutConfig(
  order: CrossmintCheckoutNewOrder.typed(
    lineItems: [
      CrossmintCheckoutLineItem.product(productLocator: 'crossmint:tshirt'),
    ],
    recipient: CrossmintCheckoutPhysicalRecipient(
      email: 'user@example.com',
      physicalAddress: const CrossmintCheckoutPhysicalAddress(
        name: 'Jane Doe',
        line1: '123 Market St',
        city: 'San Francisco',
        state: 'CA',
        postalCode: '94103',
        country: 'US',
      ),
    ),
  ),
  payment: const CrossmintCheckoutPayment(
    fiat: CrossmintCheckoutFiatPayment(enabled: true),
  ),
);

Observing diagnostics #

onDiagnostic surfaces navigation blocks, malformed hosted messages, and WebView resource errors — wire it to your logger in staging / production:

CrossmintEmbeddedCheckout(
  apiKey: 'ck_staging_...',
  config: config,
  onDiagnostic: (diag) {
    debugPrint('[${diag.severity.name}] ${diag.code}: ${diag.message}');
  },
);

Demo Applications #

  • Wallets Playground — the main example app with auth, wallets, signer management, and transaction flows. Supports multiple scenarios via environment config. See the playground feature checklist.
  • Checkout Playground — a standalone app for interactively testing the embedded checkout widget with real-time configuration: payment methods, theming, product metadata, and more.

Building the SDK Locally #

  1. Clone the repository:
git clone https://github.com/Paella-Labs/crossmint-flutter-sdk.git
  1. Install dependencies:
cd crossmint-flutter-sdk
flutter pub get
  1. Run checks:
./scripts/check_pr_gate.sh

For dependency and publish validation:

./scripts/check_dependency_hygiene.sh

Documentation #

Known Limitations #

  • iOS physical-device test automation is limited by Flutter #184254 — physical iOS validation requires manual QA.
  • Solana device signers are intentionally unsupported to match current Crossmint wallet behavior.
  • Passkey signers require explicit callbacks (Stage 1). Native platform passkey support (Stage 2) is pending.
  • Some Crossmint API families may require project entitlements.

Contact #

To get in touch with the Crossmint team, visit our contact page or find us on X.

(back to top)