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.

0.1.2 #

  • Expanded dartdoc coverage across the public API: CrossmintClient, CrossmintClientConfig, CrossmintWalletController, CrossmintWalletHost, CrossmintWalletProvider[Config], the EVM / Solana / Stellar runtime wallet classes, every CrossmintWalletApprovalSigner implementation (device, non-custodial email/phone, external, API-key, exportable, passkey), the CrossmintAuthClient interface, and the CrossmintException hierarchy.
  • Expanded dartdoc coverage across the embedded checkout surface: CrossmintCheckoutConfig, the recipient classes (Email, Wallet, Physical, + PhysicalAddress), the payment classes (Payment, FiatPayment, CryptoPayment), transaction result variants, diagnostic severity, line-item subclasses, and the CrossmintCheckoutPayer / CrossmintEvmWalletCheckoutPayer bridge.
  • Added library-level dartdoc headers to every public barrel file under lib/ and the sub-packages under packages/.
  • Declared supported platforms (iOS, Android) in pubspec.yaml so pub.dev no longer reports "unknown platforms" on the package page.
  • Rewrote example/README.md to lead with a minimal copy-paste quickstart (provider + gate + send token + embedded checkout) with the full playground documentation retained below.
  • Expanded the main README.md embedded checkout section with fiat-only, physical-goods, and onDiagnostic snippets.

0.1.1 #

  • Aligned delegated email/phone signer serialization at wallet creation with the EVM OpenAPI schema. The signers: [CrossmintEmailSignerConfig(...)] / CrossmintPhoneSignerConfig(...) shapes now serialize to the full {type, email|phone} object instead of the bare email: / phone: locator string, closing a parity gap with addSigner and the RN SDK. Forward-compat only — no end-user behavior change in this release: the Crossmint backend does not currently accept email or phone as delegated signer types on EVM. Tracking the backend-side addition separately. See discussion on #21 / #24.

  • Fixed device signer approvals on every platform. Three coordinated changes:

    1. Software fallback (SoftwareDeviceSignerKeyStorage, used on iOS Simulator, Android emulator, Expo Go, and dev builds without native hardware storage) was UTF-8-encoding the approval message before signing, but the backend delivers a base64-encoded digest. The software signer now base64-decodes the message before signing, matching the RN reference and the native plugins.
    2. Software fallback had no low-S canonicalisation — ERC-4337 / SWIG verifiers reject high-S signatures to avoid malleability. The signer now replaces s with n - s when s > n/2, matching {lowS: true} in the RN signer.
    3. Signature encoding is now decimal (base-10) r/s everywhere (software fallback + native Android Keystore + native iOS Secure Enclave). Software previously emitted hex via BigInt.toRadixString(16); the native plugins emitted hex with a 0x prefix. The wallets API parses r/s as non-negative decimal BigInt strings and rejects hex with HTTP 400.

    Verified end-to-end against staging via the playground's signers.device.createAndSignMessage / createAndSendTransaction / reuseWithEmptyConfig scenarios. Fixes #23 and the follow-up #31.

  • Added early diagnostic for non-custodial (email/phone) signers when no CrossmintWalletHost / CrossmintWalletProvider is mounted in the widget tree. useSigner(CrossmintEmailSignerConfig(...)) previously returned cleanly and the first failure surfaced deep inside bridge request polling (StateError: Hidden signer bridge is not connected). It now throws CrossmintSignerException(code: nonCustodialBridgeHostNotMounted) at useSigner time with an actionable message. The check is applied to both wallet.useSigner(...) and the CrossmintWalletController.create{Evm,Solana,Stellar}WalletWithNonCustodialSigner factory helpers. Fixes #22.

  • Added CrossmintWalletHost and HiddenSignerBridgeHost to package:crossmint_flutter/crossmint_flutter_controllers.dart. Both widgets are widgets.dart-only and satisfy the headless-first import invariant, so apps using their own design system no longer need to pull in the Material UI barrel to host the hidden signer bridge. The crossmint_flutter_ui.dart re-exports continue to work unchanged. README Quickstart updated with the wrapping example and the non-custodial-signer host requirement.

  • Added CrossmintErrorCode.nonCustodialBridgeHostNotMounted to crossmint_core.

  • Added a public HiddenSignerBridgeRuntimeController.hasEverBeenHosted getter that flips true the first time a HiddenSignerBridgeHost attaches a port and stays true on detach — the signal that backs the new missing-host diagnostic.

  • Fixed useSigner(CrossmintDeviceSignerConfig()) against a wallet that already has a device signer registered. The runtime used to unconditionally register a second device signer, which the backend treats as adding a new delegated signer gated behind an admin/recovery-OTP approval. It now inspects the wallet's delegated signers and reuses the registered device signer when exactly one exists and its key is present locally, avoiding the duplicate-signer OTP round-trip. Falls through to fresh registration when the wallet has no device signer, when multiple device signers create ambiguity, or when the referenced key is not available in local storage (reinstall / wiped-storage case). Refreshes the wallet snapshot once when the local snapshot lacks config.delegatedSigners (trimmed-response case). Fixes #27.

  • Fixed useSigner(CrossmintDeviceSignerConfig(publicKeyX, publicKeyY)) — previously silently dropped the caller's public-key material and registered a brand-new key. publicKeyX/publicKeyY and the device locator encode the same material (device:<base64(0x04 ‖ x ‖ y)>), so the canonical locator is now derived from the supplied public key, verified against the wallet's registered device signers, and activated. Throws CrossmintSignerException on mismatch or when only one of publicKeyX/publicKeyY is provided. Refreshes the wallet snapshot once on any local miss (addSigner does not keep wallet.raw.config.delegatedSigners in sync, so a stale snapshot may list a different device signer while getWallet(...) already includes the requested one). Fixes #29.

0.1.0 #

  • Fixed CrossmintNonCustodialSigner deduplicating concurrent ensureAuthenticated() callers so a single in-flight auth attempt no longer surfaces two onAuthRequired prompts for the same auth event.
  • Fixed CrossmintSignerBridgeClient cross-talk between concurrent calls that share a response event (e.g. two request:sign in flight). Requests are now serialized per response event so unrelated event pairs (e.g. a get-status while a sign is pending) still run in parallel. Source-compatible source break: CrossmintSignerBridgeClient is no longer const-constructible (no in-tree callers used const, but downstream code that did will need to drop the const keyword).
  • Fixed CrossmintWalletProviderLifecycle.disposeDependencies() to keep disposing the auth router and client when the wallet controller's disposer throws. Failures are reported via FlutterError instead of skipping the remaining cleanup.
  • Added CrossmintDeserializationException and typed parser helpers (requireString, optionalString, requireInt, requireBool, requireMap, requireMapList) in crossmint_core. CrossmintUser.fromJson is migrated as the first caller; remaining model fromJson sites will follow in a separate PR.
  • Added CrossmintErrorCode enum to crossmint_core — typed, machine-readable error codes for programmatic switch/case exception handling. All exception subclasses now carry an optional code field (defaults to unknown). Codes cover auth, wallet, signer, credential, order, and token domains.
  • Added CrossmintPollingConfig and crossmintPoll() utility to crossmint_core — exponential backoff with jitter replaces the previous flat 1-second polling loops in signature and transaction confirmation flows. Default: 1 s initial, 2x growth, 8 s cap, 60 attempts, random jitter in [50 %, 100 %) range.
  • Added ADR-001 documenting the decision to keep hand-written fromJson()/ toJson() methods rather than adopting freezed or json_serializable codegen, with clear re-evaluation triggers.
  • Added CrossmintChain enum to crossmint_core — typed, environment-aware chain validation covering all 24 mainnet chains, 20 testnet chains, Solana, and Stellar. Includes fromApiValue() / tryFromApiValue() for safe parsing and validateForEnvironment() for automatic mainnet→testnet conversion in non-production environments.
  • Added CrossmintApiKeySigner — a backend-only signer matching the official TypeScript SDK's API key signer. All signing is handled server-side; calling signMessage() or signTransaction() locally throws a descriptive error.
  • Added CrossmintPasskeySignerConfig model and crossmintGuardAgainstPasskeySigners() guard. Passkey/WebAuthn signers are blocked in Flutter (matching the official React Native SDK), with a clear error message guiding users to alternative signer types.
  • Added CrossmintApiKeySignerConfig and CrossmintPasskeySignerConfig to the CrossmintSignerConfig sealed hierarchy in crossmint_wallets.
  • Added fromJson() / toJson() factory methods to all core model classes: CrossmintWallet, CrossmintSignerConfig (polymorphic dispatch by type), CrossmintWalletSigner, CrossmintTransactionRecord, CrossmintSignatureRecord, CrossmintWalletBalanceSnapshot, CrossmintNftRecord, CrossmintWalletNftPage, CrossmintUser, CrossmintOrderRecord, CrossmintTokenAvailabilityRecord, and others.
  • Replaced hand-rolled base58 encoder/decoder (~65 lines) with the published bs58 package. The _decodeBase58() and _encodeBase58() helpers in crossmint_non_custodial_signer.dart now delegate to base58.decode() and base58.encode().
  • Upgraded chain-type detection helpers (crossmintIsSolanaChain(), crossmintIsStellarChain(), _isSolanaChain()) to prefer enum-based matching via CrossmintChain.tryFromApiValue() with string fallback for backward compatibility.
  • Validated iOS real-device integration tests on physical iPhone via Wi-Fi debugging, closing the last pending validation item. Hidden signer bridge and device signer plugin (Secure Enclave) both passed.
  • Documented the Xcode 26.4 / Flutter #184254 workaround (Wi-Fi debugging) for future iOS physical-device test runs.
  • Fixed headless order parsing to handle the live order.orderId response shape returned by POST /api/2022-06-09/orders.
  • Fixed scripts/dart_defines_from_env.sh so JSON-valued Dart defines work with direct command substitution in the documented flutter run/test $(...) flow.
  • Added a direct staging probe for orders / Worldstore so client-key vs server-key boundaries are documented with live evidence.
  • Added release-readiness docs for gate disposition, Android/iOS evidence, and the release-candidate checklist.
  • Clarified that externally gated scopes remain non-blocking amber when the Flutter SDK contract is already proven correct.
  • Added example-workspace package overrides so flutter drive and other example-side validation paths resolve the local package family consistently.
  • Switched the package family to publish-ready hosted dependency manifests while keeping local monorepo development on pubspec_overrides.yaml.
  • Added consumer-facing installation guidance for crossmint_flutter and cleaned up template metadata in the native device-signer plugin package.

0.0.1 #

  • Initial internal Flutter port workspace release.
  • Added the core Crossmint Flutter client surface for auth, wallets, credentials, orders, tokens, and users.
  • Added the device signer plugin, hidden signer bridge, example app, and test harnesses.
  • Known gaps at this release stage: iOS real-device automation and staging scopes gated by project/backend configuration.