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

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

0.5.0 #

  • A wallet can now hold several recovery methods. CrossmintRuntimeWalletBase.recoveryMethods reads every entry of config.recoveryMethods (falling back to the single config.adminSigner); recovery stays the first entry. Multiple methods are accepted on Solana and Stellar only. On EVM a one-entry recoveryMethods list is sent as config.adminSigner, and a longer one throws before the API call.
  • Create a multi-method wallet with CrossmintWalletCreateRequest.withRecoveryMethods (or CrossmintCreateOnLoginConfig.withRecoveryMethods), or from the runtime facade with CrossmintWallets.createWalletWithRecoveryMethods. The default constructors and createWallet keep their single recovery parameter, so no request holds both. This matches the paired createWallet methods in the Swift and Kotlin SDKs.
  • On a wallet with two or more recovery methods, every admin operation (addSigner, removeSigner, and resuming a pending recovery approval) must name which method authorizes it. The new CrossmintRuntimeWalletBase.useRecoveryMethod(...) selects it without changing the active signer, like wallet.useRecoveryMethod in the TypeScript SDK. The method must be one of recoveryMethods, and server methods are rejected. When nothing is selected, the SDK picks one in order: the active signer when it is a recovery method, the recoverySigner: passed at construction, then the sole method. When several methods exist and none can be inferred it throws a CrossmintWalletException that names useRecoveryMethod. A single-method wallet omits the approver field entirely.
  • A recoverySigner: the wallet does not hold is now rejected on every wallet, not only on a multi-method one. Both membership checks used to be gated on needing an approver, so a single-method wallet accepted any config at all and then approved with a method it does not hold, which sent an OTP to an address that cannot authorize anything. A config with no locator is the one case still accepted unchecked: only resolving it would reveal its locator, and resolving eagerly would break a method that cannot sign on this device. A config the wallet does hold is honoured as before.
  • Every CrossmintWalletController wallet factory method (createEvmWallet, createSolanaWallet, createStellarWallet and each create*WalletWith*Signer variant) now takes an optional recoverySigner: and defaults it to createOnLogin.recovery, the method the app named as primary. Without it, a wallet created through CrossmintCreateOnLoginConfig.withRecoveryMethods could not recover at all: selection found no method, so every send() threw. The default applies only to a wallet that holds it: the loaded wallet is not always the one this config created, and the forwarded method outranks the wallet's own, so a method the wallet does not hold is withheld rather than used to approve, and the wallet's own recovery method is used. A bare CrossmintEmailSignerConfig() takes the signed-in user's email, and is withheld only until the controller knows it. An explicit recoverySigner: is always honoured.
  • A pending admin approval the backend addressed to a specific recovery method is now resumed with that same method instead of re-running selection, which could otherwise pick a different one on a multi-method wallet.
  • Selecting a server-side recovery method — one Flutter cannot create itself, but can inherit from a wallet built elsewhere — now fails immediately with "Server recovery methods cannot approve from a mobile client. Select a different recovery method." instead of the generic active-signer error.
  • Fixed: a recovery passkey is now found anywhere in a wallet's recovery-methods list, not only when it is the sole or primary one. A wallet can hold more than one, so a credential id now selects among them and an ambiguous selection throws instead of silently taking the first.
  • Fixed: an api-key recovery method is matched by type. The backend reports one as api-key:<address>, and CrossmintApiKeySignerConfig() carries no address to build that from, so a wallet rejected its own admin signer. Matching on the type is what the TypeScript descriptor does too, and a wallet holds one custodial api-key signer.
  • The approver sent to the API now carries the locator the wallet reported, not the one the caller matched with. A bare api-key is not a locator the backend's schema accepts, and an address in the other valid casing is a different string, so the value travelling to the API is always one the backend itself produced.
  • Fixed: an EVM recovery address is matched whichever casing it carries. The backend stores the casing a wallet was created with and compares EVM addresses checksum-insensitively, so the same signer can reach the SDK as 0xd8da... from one source and 0xd8dA... from another. Membership tests now compare through crossmintSignerLocatorKey, which case-folds an external-wallet or server locator holding a 40-character hex address and leaves every other identifier alone, since Solana base58, Stellar base32, passkey and device identifiers carry meaning in their case. The key is only a comparison key: the approver sent to the API keeps the caller's own bytes, which the backend accepts for either casing.
  • Fixed: an email recovery method is now matched however the app spelled it. The backend normalizes an address before it stores a signer, so a wallet reports email:ops.team@acme.com whatever case the app configured. A locator was derived from the caller's own spelling, so CrossmintEmailSignerConfig(email: 'Ops.Team@Acme.COM') matched no method: on a wallet with several recovery methods, naming it threw "is not one of this wallet's recovery methods", and the approver sent for it would have been rejected by EVM and Solana. Derivation now applies the same rule as the backend and the TypeScript SDK: the address is lowercased, googlemail.com becomes gmail.com, and a Gmail local part loses its dots. An explicit locator is still used exactly as given.
  • Fixed: a recovery method identified only by id (a passkey) or carrying no locator (an api-key method) is now recognised as a recovery method. Its locator is derived the same way a caller-supplied config's is, so activating such a method with useSigner(...) no longer left addSigner and removeSigner demanding an approver the caller had already named.
  • Email population no longer rewrites an address the app set. Before, one blank email entry made every email signer in the request eligible, so recovery: CrossmintEmailSignerConfig(email: 'ops@acme.com') alongside any blank entry was rewritten to the signed-in user's address. It is now left alone. Because the admin signer decides the wallet address, an app that relied on the old rewrite will resolve a different wallet from ensureLoaded() after upgrading.
  • Fixed: CrossmintWalletController.createWallet no longer drops owner when rebuilding the create request; it also now threads the new recoveryMethods through.
  • Requires crossmint_wallets ^0.2.0 and crossmint_core ^0.1.7.

0.4.0 #

  • Added WhatsApp as an OTP delivery channel for phone signers. Pass channel: CrossmintOtpDeliveryChannel.whatsapp to CrossmintPhoneSignerConfig, to CrossmintWalletController.createEvmWalletWithNonCustodialSigner, createSolanaWalletWithNonCustodialSigner and createStellarWalletWithNonCustodialSigner, or to CrossmintClient.createEvmNonCustodialSigner, createSolanaNonCustodialSigner and createStellarNonCustodialSigner. Null keeps the service default, SMS. The signer service does not store the choice, so supply it each time the phone signer is selected. Countries with no registered WhatsApp sender fall back to SMS. The channel is client-only: it is not sent to the wallet API and is absent from a fetched wallet's recovery config.
  • A phone createOnLogin.recovery config that sets a channel now also applies to a wallet that was loaded, not created. createEvmWallet, createSolanaWallet and createStellarWallet on the controller use it as the recovery signer when its phone number matches the wallet's recovery signer, so recovery OTPs go over the requested channel. Any other config is not used there, and the wallet's own recovery signer applies.
  • Passkey approvals now reject assertions made without user verification. The on-chain WebAuthn verifier rejects them anyway, which surfaced as an opaque AA24 bundler error. The SDK now throws a CrossmintSignerException with CrossmintErrorCode.passkeyUserVerificationMissing before submitting. Request the assertion in onSignWithPasskey with userVerification: "required".
  • Requires crossmint_core ^0.1.6 and crossmint_wallets ^0.1.5, which carry the new types above.

0.3.0 #

  • Added CrossmintIdentityVerification, a WebView widget that renders Crossmint's hosted identity verification step on your own route instead of inside embedded checkout. It reports onReady, onComplete, onCancel and onError, sizes itself from the hosted page, restricts main-frame navigation to Crossmint hosts while still allowing the provider's capture iframe, and clears its loading overlay with a non-retriable error if the page fails to load. Exported from crossmint_flutter_ui.dart.
  • Added CrossmintCheckoutController.identityVerificationCredentials, which parses the current order's payment.preparation.kyc and returns null when the order needs no verification, names an unknown provider, or carries no usable inquiry id.
  • Added CrossmintCheckoutConfig.identityVerificationHandling. Setting it to CrossmintIdentityVerificationHandling.external tells the hosted checkout to stop rendering the verification step, so the app must mount CrossmintIdentityVerification itself or the buyer cannot finish. The flag is ignored by Crossmint deployments that predate it, which fall back to rendering verification inside checkout.
  • Verification outcomes and failures are typed as CrossmintIdentityVerificationStatus, CrossmintIdentityVerificationErrorReason and CrossmintIdentityVerificationError, each with an unknown fallback, so an unrecognised status still reaches onComplete rather than being dropped.
  • CrossmintPaymentMethodManagement now reloads when its URL changes. It previously had no update handling, so changing jwt, apiKey or appearance on a mounted widget did nothing. Those changes now reload the hosted page. Hosts that rebuild the widget with a new JWT will see a reload where they previously saw none.
  • The embedded checkout, payment method management and identity verification widgets now share one internal WebView host. Two behaviour changes fall out of it: all three re-show the loading overlay when the hosted page starts a navigation, which only embedded checkout did before, and all three enable the Android file-access and gesture-free media-playback settings that document upload needs, which only embedded checkout did before. These do not grant camera access — see the next entry.
  • CrossmintEmbeddedCheckout no longer clears its loading overlay on a sub-resource HTTP error. It previously cleared on any HTTP error, so a failed font or beacon inside the hosted page hid the spinner while the main document was still loading. The overlay now clears only when the failing request is the page itself; the onDiagnostic callback still fires for every HTTP error, so diagnostics are unchanged.
  • Runtime camera and microphone permission requests are still not handled: AndroidWebViewController.setOnPlatformPermissionRequest is not wired up in any widget, so provider live-capture may still be blocked at runtime pending device testing.

0.2.2 #

  • Upgraded app_links to ^7.0.0 and flutter_secure_storage to ^10.0.0.
  • These bumps raise upstream platform floors: flutter_secure_storage 10 requires Android minSdk 23, iOS 12, and Flutter 3.19.0; app_links 7 requires iOS 13 and Flutter 3.38.1. The SDK already targets iOS 15. The effective Flutter floor is 3.41.6 (the first Flutter shipping Dart 3.11.4, which the sdk: ^3.11.4 constraint requires); the environment block now declares this explicitly.
  • flutter_secure_storage 10 replaces the deprecated Jetpack Crypto backend on Android with new default ciphers and migrates existing entries automatically; it also defaults resetOnError to true. Hosts that pin custom AndroidOptions should review the package's v10 migration notes before upgrading.

0.2.1 #

  • Solana device signers are no longer rejected client-side. Support is provider-dependent (Swig/Crossmint support device signers, Squads does not) and validated server-side. When a provider rejects a device signer, the runtime transparently falls back to the recovery signer.
  • A default device signer is still not eagerly attached to Solana wallet creation, since the backing provider is only known server-side. Explicitly requested device signers now flow through to the server.
  • Once a wallet's provider is known not to support device signers, selecting a device signer is rejected before any local key is generated.
  • Decoupled permissionless_passkeys (and permissionless), dropping the Android minSdk floor from 30 to 24. The experimental PermissionlessPasskeySignerFactory is removed; the default passkey factory now yields walletUnsupportedPasskeySigner unless a host supplies its own. The supported callback-based passkey path (onCreatePasskey / onSignWithPasskey) is unaffected.
  • Bumped sub-package floors to crossmint_core ^0.1.4 and crossmint_wallets ^0.1.3.

0.2.0 #

  • Breaking: the minimum iOS deployment target is now 15. This SDK depends on crossmint_device_signer 0.2.0, whose shared CrossmintDeviceSigner native pod requires iOS 15. Because the dependency is direct, the floor applies to every consumer's iOS build at CocoaPods resolution time — not only apps that call the device signer at runtime.
  • Device signer: the hidden device-signer plugin adapter and software key-storage now delegate to the shared native CrossmintDeviceSigner packages — the same native code the React Native SDK uses — for cross-SDK parity. No Dart API change.
  • Docs: dartdoc / API-reference style pass across the public surface (EVM payer override methods, checkout line-item factories, button properties, inlined enum values, lowercased dartdoc references) for the pub.dev landing page.
  • Docs: corrected the hidden signer WebView dartdoc — it is hidden via a 1×1 Opacity(0.01) + IgnorePointer wrapper, not the Offstage widget — and added a comment explaining why (a zero-area or unpainted WKWebView is reported as not visible on iOS, throttling JS timers and risking WebContent process termination). Mirrors crossmint-sdk React Native PR #1878.

0.1.4 #

  • Fix: addSigner now swaps the runtime wallet's _signer to the recovery signer before approving the pending registration, then restores the previous signer in a finally. Registering a signer is an admin-level op — the backend addresses the pending approval to the wallet's recovery signer, not to whichever signer is currently active. Before this change, calling addSigner(device2) while signing with device1 threw signerApprovalSignerMissing because the pending approval's email:... locator did not match the device signer. Matches the TS SDK (packages/wallets/src/wallets/wallet.ts). Callers that previously worked around this with an explicit useSigner(recovery) before addSigner no longer need to.

0.1.3 #

  • Docs: README refresh. Quickstart restructured into four numbered steps (initialize client → sign user in → mount wallet host → load or create wallet), with a new "OTP prompt handling" reference subsection covering both the controller-driven and onAuthRequired callback paths. Documents the CrossmintWallet data-model vs runtime-wallet split and the four signer-bundled wallet factory helpers (createEvmWalletWithDeviceSigner / …WithNonCustodialSigner / …WithExternalWalletSigner / …WithPasskeySigner). Calls out that CrossmintWalletControllerConfig.showOtpSignerPrompt is inert plumbing today and points at crossmintDefaultOtpPromptBuilder instead. Flags the CrossmintEmailSignerConfig() recovery-signer assumption that the signed-in user has an email.
  • Docs: Embedded Checkout section expanded with a widget-parameter reference table, a recipient-type guide (CrossmintCheckoutEmailRecipient / …WalletRecipient / …PhysicalRecipient), a theming subsection covering CrossmintCheckoutAppearance (variables / rules / fonts), and onOrderCreationFailed alongside onDiagnostic. Corrects the onOrderUpdated example — the callback receives Map<String, Object?>, so field access uses order['orderId'] rather than order.orderId.
  • Docs: New Platform Setup section covering the Android AndroidManifest.xml intent-filter and iOS Info.plist CFBundleURLTypes entries required for OAuth deep links and the CrossmintAuthCallbackRouter to work.
  • No code changes. Root package version bumped to 0.1.3 so consumers see the updated README on pub.dev; sub-packages unchanged.

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.