crossmint_flutter 0.5.0
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.recoveryMethodsreads every entry ofconfig.recoveryMethods(falling back to the singleconfig.adminSigner);recoverystays the first entry. Multiple methods are accepted on Solana and Stellar only. On EVM a one-entryrecoveryMethodslist is sent asconfig.adminSigner, and a longer one throws before the API call. - Create a multi-method wallet with
CrossmintWalletCreateRequest.withRecoveryMethods(orCrossmintCreateOnLoginConfig.withRecoveryMethods), or from the runtime facade withCrossmintWallets.createWalletWithRecoveryMethods. The default constructors andcreateWalletkeep their singlerecoveryparameter, so no request holds both. This matches the pairedcreateWalletmethods 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 newCrossmintRuntimeWalletBase.useRecoveryMethod(...)selects it without changing the active signer, likewallet.useRecoveryMethodin the TypeScript SDK. The method must be one ofrecoveryMethods, and server methods are rejected. When nothing is selected, the SDK picks one in order: the active signer when it is a recovery method, therecoverySigner:passed at construction, then the sole method. When several methods exist and none can be inferred it throws aCrossmintWalletExceptionthat namesuseRecoveryMethod. A single-method wallet omits theapproverfield 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
CrossmintWalletControllerwallet factory method (createEvmWallet,createSolanaWallet,createStellarWalletand eachcreate*WalletWith*Signervariant) now takes an optionalrecoverySigner:and defaults it tocreateOnLogin.recovery, the method the app named as primary. Without it, a wallet created throughCrossmintCreateOnLoginConfig.withRecoveryMethodscould not recover at all: selection found no method, so everysend()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 bareCrossmintEmailSignerConfig()takes the signed-in user's email, and is withheld only until the controller knows it. An explicitrecoverySigner: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>, andCrossmintApiKeySignerConfig()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
approversent to the API now carries the locator the wallet reported, not the one the caller matched with. A bareapi-keyis 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 and0xd8dA...from another. Membership tests now compare throughcrossmintSignerLocatorKey, which case-folds anexternal-walletorserverlocator 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: theapproversent 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.comwhatever case the app configured. A locator was derived from the caller's own spelling, soCrossmintEmailSignerConfig(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 theapproversent 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.combecomesgmail.com, and a Gmail local part loses its dots. An explicitlocatoris still used exactly as given. - Fixed: a recovery method identified only by
id(a passkey) or carrying nolocator(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 withuseSigner(...)no longer leftaddSignerandremoveSignerdemanding 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 fromensureLoaded()after upgrading. - Fixed:
CrossmintWalletController.createWalletno longer dropsownerwhen rebuilding the create request; it also now threads the newrecoveryMethodsthrough. - Requires
crossmint_wallets ^0.2.0andcrossmint_core ^0.1.7.
0.4.0 #
- Added WhatsApp as an OTP delivery channel for phone signers. Pass
channel: CrossmintOtpDeliveryChannel.whatsapptoCrossmintPhoneSignerConfig, toCrossmintWalletController.createEvmWalletWithNonCustodialSigner,createSolanaWalletWithNonCustodialSignerandcreateStellarWalletWithNonCustodialSigner, or toCrossmintClient.createEvmNonCustodialSigner,createSolanaNonCustodialSignerandcreateStellarNonCustodialSigner. 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.recoveryconfig that sets achannelnow also applies to a wallet that was loaded, not created.createEvmWallet,createSolanaWalletandcreateStellarWalleton 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
AA24bundler error. The SDK now throws aCrossmintSignerExceptionwithCrossmintErrorCode.passkeyUserVerificationMissingbefore submitting. Request the assertion inonSignWithPasskeywithuserVerification: "required". - Requires
crossmint_core^0.1.6andcrossmint_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 reportsonReady,onComplete,onCancelandonError, 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 fromcrossmint_flutter_ui.dart. - Added
CrossmintCheckoutController.identityVerificationCredentials, which parses the current order'spayment.preparation.kycand returnsnullwhen the order needs no verification, names an unknown provider, or carries no usable inquiry id. - Added
CrossmintCheckoutConfig.identityVerificationHandling. Setting it toCrossmintIdentityVerificationHandling.externaltells the hosted checkout to stop rendering the verification step, so the app must mountCrossmintIdentityVerificationitself 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,CrossmintIdentityVerificationErrorReasonandCrossmintIdentityVerificationError, each with anunknownfallback, so an unrecognised status still reachesonCompleterather than being dropped. CrossmintPaymentMethodManagementnow reloads when its URL changes. It previously had no update handling, so changingjwt,apiKeyorappearanceon 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.
CrossmintEmbeddedCheckoutno 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; theonDiagnosticcallback still fires for every HTTP error, so diagnostics are unchanged.- Runtime camera and microphone permission requests are still not handled:
AndroidWebViewController.setOnPlatformPermissionRequestis not wired up in any widget, so provider live-capture may still be blocked at runtime pending device testing.
0.2.2 #
- Upgraded
app_linksto^7.0.0andflutter_secure_storageto^10.0.0. - These bumps raise upstream platform floors:
flutter_secure_storage10 requires AndroidminSdk23, iOS 12, and Flutter 3.19.0;app_links7 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 thesdk: ^3.11.4constraint requires); theenvironmentblock now declares this explicitly. flutter_secure_storage10 replaces the deprecated Jetpack Crypto backend on Android with new default ciphers and migrates existing entries automatically; it also defaultsresetOnErrortotrue. Hosts that pin customAndroidOptionsshould 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(andpermissionless), dropping the AndroidminSdkfloor from 30 to 24. The experimentalPermissionlessPasskeySignerFactoryis removed; the default passkey factory now yieldswalletUnsupportedPasskeySignerunless a host supplies its own. The supported callback-based passkey path (onCreatePasskey/onSignWithPasskey) is unaffected. - Bumped sub-package floors to
crossmint_core ^0.1.4andcrossmint_wallets ^0.1.3.
0.2.0 #
- Breaking: the minimum iOS deployment target is now 15. This SDK depends
on
crossmint_device_signer0.2.0, whose sharedCrossmintDeviceSignernative 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
CrossmintDeviceSignerpackages — 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)+IgnorePointerwrapper, not theOffstagewidget — 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:
addSignernow swaps the runtime wallet's_signerto the recovery signer before approving the pending registration, then restores the previous signer in afinally. 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, callingaddSigner(device2)while signing withdevice1threwsignerApprovalSignerMissingbecause the pending approval'semail:...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 explicituseSigner(recovery)beforeaddSignerno 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
onAuthRequiredcallback paths. Documents theCrossmintWalletdata-model vs runtime-wallet split and the four signer-bundled wallet factory helpers (createEvmWalletWithDeviceSigner/…WithNonCustodialSigner/…WithExternalWalletSigner/…WithPasskeySigner). Calls out thatCrossmintWalletControllerConfig.showOtpSignerPromptis inert plumbing today and points atcrossmintDefaultOtpPromptBuilderinstead. Flags theCrossmintEmailSignerConfig()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 coveringCrossmintCheckoutAppearance(variables / rules / fonts), andonOrderCreationFailedalongsideonDiagnostic. Corrects theonOrderUpdatedexample — the callback receivesMap<String, Object?>, so field access usesorder['orderId']rather thanorder.orderId. - Docs: New Platform Setup section covering the Android
AndroidManifest.xmlintent-filter and iOSInfo.plistCFBundleURLTypesentries required for OAuth deep links and theCrossmintAuthCallbackRouterto 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, everyCrossmintWalletApprovalSignerimplementation (device, non-custodial email/phone, external, API-key, exportable, passkey), theCrossmintAuthClientinterface, and theCrossmintExceptionhierarchy. - 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 theCrossmintCheckoutPayer/CrossmintEvmWalletCheckoutPayerbridge. - Added library-level dartdoc headers to every public barrel file under
lib/and the sub-packages underpackages/. - Declared supported platforms (iOS, Android) in
pubspec.yamlso pub.dev no longer reports "unknown platforms" on the package page. - Rewrote
example/README.mdto lead with a minimal copy-paste quickstart (provider + gate + send token + embedded checkout) with the full playground documentation retained below. - Expanded the main
README.mdembedded checkout section with fiat-only, physical-goods, andonDiagnosticsnippets.
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 bareemail:/phone:locator string, closing a parity gap withaddSignerand 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:
- 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. - Software fallback had no low-S canonicalisation — ERC-4337 / SWIG
verifiers reject high-S signatures to avoid malleability. The
signer now replaces
swithn - swhens > n/2, matching{lowS: true}in the RN signer. - Signature encoding is now decimal (base-10)
r/severywhere (software fallback + native Android Keystore + native iOS Secure Enclave). Software previously emitted hex viaBigInt.toRadixString(16); the native plugins emitted hex with a0xprefix. The wallets API parsesr/sas 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/reuseWithEmptyConfigscenarios. Fixes #23 and the follow-up #31. - Software fallback (
-
Added early diagnostic for non-custodial (email/phone) signers when no
CrossmintWalletHost/CrossmintWalletProvideris 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 throwsCrossmintSignerException(code: nonCustodialBridgeHostNotMounted)atuseSignertime with an actionable message. The check is applied to bothwallet.useSigner(...)and theCrossmintWalletController.create{Evm,Solana,Stellar}WalletWithNonCustodialSignerfactory helpers. Fixes #22. -
Added
CrossmintWalletHostandHiddenSignerBridgeHosttopackage:crossmint_flutter/crossmint_flutter_controllers.dart. Both widgets arewidgets.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. Thecrossmint_flutter_ui.dartre-exports continue to work unchanged. README Quickstart updated with the wrapping example and the non-custodial-signer host requirement. -
Added
CrossmintErrorCode.nonCustodialBridgeHostNotMountedtocrossmint_core. -
Added a public
HiddenSignerBridgeRuntimeController.hasEverBeenHostedgetter that flipstruethe first time aHiddenSignerBridgeHostattaches a port and staystrueon 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 lacksconfig.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/publicKeyYand 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. ThrowsCrossmintSignerExceptionon mismatch or when only one ofpublicKeyX/publicKeyYis provided. Refreshes the wallet snapshot once on any local miss (addSignerdoes not keepwallet.raw.config.delegatedSignersin sync, so a stale snapshot may list a different device signer whilegetWallet(...)already includes the requested one). Fixes #29.
0.1.0 #
- Fixed
CrossmintNonCustodialSignerdeduplicating concurrentensureAuthenticated()callers so a single in-flight auth attempt no longer surfaces twoonAuthRequiredprompts for the same auth event. - Fixed
CrossmintSignerBridgeClientcross-talk between concurrent calls that share a response event (e.g. tworequest:signin flight). Requests are now serialized per response event so unrelated event pairs (e.g. aget-statuswhile asignis pending) still run in parallel. Source-compatible source break:CrossmintSignerBridgeClientis no longerconst-constructible (no in-tree callers usedconst, but downstream code that did will need to drop theconstkeyword). - Fixed
CrossmintWalletProviderLifecycle.disposeDependencies()to keep disposing the auth router and client when the wallet controller's disposer throws. Failures are reported viaFlutterErrorinstead of skipping the remaining cleanup. - Added
CrossmintDeserializationExceptionand typed parser helpers (requireString,optionalString,requireInt,requireBool,requireMap,requireMapList) incrossmint_core.CrossmintUser.fromJsonis migrated as the first caller; remaining model fromJson sites will follow in a separate PR. - Added
CrossmintErrorCodeenum tocrossmint_core— typed, machine-readable error codes for programmaticswitch/caseexception handling. All exception subclasses now carry an optionalcodefield (defaults tounknown). Codes cover auth, wallet, signer, credential, order, and token domains. - Added
CrossmintPollingConfigandcrossmintPoll()utility tocrossmint_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 adoptingfreezedorjson_serializablecodegen, with clear re-evaluation triggers. - Added
CrossmintChainenum tocrossmint_core— typed, environment-aware chain validation covering all 24 mainnet chains, 20 testnet chains, Solana, and Stellar. IncludesfromApiValue()/tryFromApiValue()for safe parsing andvalidateForEnvironment()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; callingsignMessage()orsignTransaction()locally throws a descriptive error. - Added
CrossmintPasskeySignerConfigmodel andcrossmintGuardAgainstPasskeySigners()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
CrossmintApiKeySignerConfigandCrossmintPasskeySignerConfigto theCrossmintSignerConfigsealed hierarchy incrossmint_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
bs58package. The_decodeBase58()and_encodeBase58()helpers incrossmint_non_custodial_signer.dartnow delegate tobase58.decode()andbase58.encode(). - Upgraded chain-type detection helpers (
crossmintIsSolanaChain(),crossmintIsStellarChain(),_isSolanaChain()) to prefer enum-based matching viaCrossmintChain.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.orderIdresponse shape returned byPOST /api/2022-06-09/orders. - Fixed
scripts/dart_defines_from_env.shso JSON-valued Dart defines work with direct command substitution in the documentedflutter 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 driveand 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_flutterand 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.