flutter_web3_webview 1.1.0
flutter_web3_webview: ^1.1.0 copied to clipboard
A Flutter WebView widget that bridges in-app web pages to a Web3 wallet over EIP-1193 (EVM) and the Solana wallet standard.
1.1.0 #
Provider requests gain an identity and can be cancelled. A wallet that switches account, changes chain or tears down a document can now terminate requests already queued behind a pending approval, instead of letting them reach the signer under state they were never authorized against. Every change below is additive — existing hosts compile and behave as before.
Request identity and cancellation #
- NEW: The in-page bridge mints an id per request (
fxw<random>-<counter>) and the Dart queue tracks it, so a host can correlate a request with its in-page promise and address it by id.JsCallBackDatagains an optional namedid;method/paramskeep their positions and defaults. A payload without an id (a DApp callingcallHandlerdirectly, or an older injected bundle) runs under a syntheticlocal:<n>id and stays cancellable. An id the page replays while it is still in flight — and the empty string — is rejected in favour of a synthetic one, and the synthetic counter skips ids the page has already claimed, so live requests always carry distinct ids andcancel(id)cannot be misdirected. - NEW:
Web3RequestController— host-side handle onto the queue. Pass one toWeb3Webview(requestController: ...)to inspect what is in flight (requests/activeId/pendingLength) and cancel by id (cancel/cancelAll). It exposes mechanism only; when to cancel stays a wallet policy decision. Safe no-op while unattached. - NEW: Cancellation is cooperative, deliberately. A request that has not
started is dropped and fails with
4900without ever entering the host callback. A request already executing is only flagged — never force-completed, because completing it would let the queue advance while a signing or broadcast call is still running. Callbacks observe the flag viaWeb3RequestContext.throwIfCancelled(), which travels through a Zone, so no callback signature changed. Consumers must place checkpoints before signing, not after: a callback that never checks runs to completion. - NEW:
4900(disconnected) rather than4001for wallet-initiated cancellation —4001means the user rejected, which is a different fact. - NEW: Queue depth is bounded by
Web3Webview(maxPendingRequests:), default 32, rejecting overflow with-32005. A fail-closed finite value rather than unbounded, so a page cannot flood the bridge. - NEW: Each queued request is tagged with its chain family
(
Web3RequestFamily.evm/.solana), derived from the same routing table the dispatcher uses. Hosts filtering by chain readWeb3RequestInfo.familyinstead of re-parsing method names, so the classification cannot drift from the dispatcher's.
API surface #
- NEW:
Web3RpcError.unauthorized()(4100),Web3RpcError.requestUnavailable()(-32002) andWeb3RpcError.internal()(-32603), joiningcancelled()(4900) andlimitExceeded()(-32005). Wallet hosts were maintaining their own copy of this error type because the wallet-facing codes were missing; the sentinel and JSON wire format the injected bridge parses are unchanged. - NEW: Export
SerialEventQueueand theSerialEventtypedef. They are the parameter types of the already-exportedWeb3RequestController.attach/detach, so a host binding its own queue previously had to importpackage:flutter_web3_webview/src/...and silenceimplementation_imports.
Build #
provider.min.jsrebuilt with the dependency set the repo currently resolves (328,835 → 319,868 bytes). Sources unchanged; the diff is entirely minifier identifier renaming, isolated into its own commit so later bundle diffs show only their own delta.- Provider spec directories get editor-only TypeScript projects (
noEmit,types: ["bun"]) so the language service can resolvebun:test; the build projects keep their exclusions.moduleResolutionrenamednode→node10at the provider root, removing theignoreDeprecationsentries it had forced. Bundle byte-identical.
1.0.0 #
First stable release. The injected Web3 provider is now built from vendored
TypeScript source (provider/) instead of a lost pre-compiled artifact, and
the EVM / Solana request pipeline has been hardened end-to-end.
Provider #
- NEW:
lib/js/provider.min.jsis generated from the vendoredprovider/source viabun run build:flutter(321 KB, down from the legacy ~1.46 MB bundle). Dropping the unreachableMobileAdapterfromEthereumProvider/SolanaProvidercuts the@metamask/eth-sig-utildependency chain and fixes a latent issue where the adapter renamed EVM methods (eth_sendTransaction → signTransaction, etc.) that the Dart dispatcher doesn't recognise. DApp-facing surface is unchanged (verified against the legacy bundle). - NEW: Serialize Solana
signTransactioninside the provider. Concurrent calls (directly or viasignAllTransactions) run one at a time through an instance-level promise queue, so a DApp can't race the wallet's single approval UI; a rejected signature does not wedge the queue. This replaces the host-app userscript that previously monkey-patched the behaviour onto the provider at runtime.
Fixes #
- SECURITY: Deny WebView permission requests by default unless the caller provides an explicit permission handler.
- Handle
wallet_addEthereumChainseparately fromwallet_switchEthereumChainvia a newwalletAddEthereumChaincallback: per EIP-3085 it registers the chain and resolves withnullwithout switching the active chain or emittingchainChanged. With no add handler it rejects with4200(unsupported method) rather than falling back to a switch, so an add request never silently changes the active network. - Return
nullfrom a successfulwallet_switchEthereumChainper EIP-3326 (it previously resolved with the chain id, which strict DApps treat as a protocol mismatch). - Stop advertising the Solana wallet-standard
signAndSendTransactionandsignInfeatures: the provider has no default broadcast RPC and SIWS isn't bridged, so advertising them led DApps into a guaranteed runtime failure (signAndSendTransactionthrew on an uninitialised connection,signInalways threwMethod not implemented.). DApps now fall back tosignTransaction/connect+signMessage. - Fix the legacy synchronous
_send:net_version/eth_chainIdno longer return the accounts array, andgetNetworkVersion's method name no longer carries a stray trailing space. The pass-through provider doesn't cache the chain id, so these synchronous calls now throw4200pointing callers at the asyncrequestAPI. - Always emit the EIP-6963
announceProviderevent, even whenwindow.ethereumalready exists — the previous early-return suppressed the announcement and broke multi-provider coexistence. The injected script now guards re-initialisation onfxwallet.ethereumand only claimswindow.ethereumwhen it is free. - Default the EIP-6963 announcement metadata to valid values — a built-in
data-URI
iconand a reverse-DNSrdns(both overridable viaWeb3EthSettings) — instead of empty strings that strict DApps reject. - Surface EIP-1193
4001(user rejected) instead of the invalid4092code when a chain switch is declined, and rejectwallet_switchEthereumChainwith4902for any chain id that is missing or is not a0x-prefixed hex string (previously'1','0xzz',' 0x1 'and similar values still reached the wallet callback). - Surface structured EIP-1193 errors to DApps. The Dart side throws
Web3RpcError; the injected provider bridge parses itsWeb3RpcError:sentinel out of the wrapped rejection string and re-throws a realProviderRpcErrorcarryingcode/message/data, so DApps can branch onerror.code(e.g.4902→wallet_addEthereumChain). - Add
Web3EthSettings.overwriteMetamask(defaultfalse). Previouslywindow.ethereum.isMetaMaskwas permanentlyfalsebecause the value was injected under a config field the provider never read — breaking DApps that gate signing on it (e.g. the MetaMask test dapp). - Back
JsTransactionObjectfields with the underlying raw map so setting a typed field tonullactually clears the value (was leaking the original DApp value throughtoJson()), while preserving DApp-provided fields likenonce/maxFeePerGas/ numericgas. - JSON-encode wallet metadata before injecting it into JavaScript.
- Share provider asset loading across concurrent initialization calls.
- Serialize user-confirmed EVM and Solana requests and safely encode chain change events.
- Respect
isWeb3when injecting provider scripts and forward Ajax ready-state callbacks.
0.1.0 #
- NEW: Initial Release.
0.1.1 #
- UPDATE: Inject provider at document start.
0.1.2 #
- UPDATE: Init provider js before use.
- UPDATE: Update README.md for use.
0.1.3 #
- FIX: Return full data for personal sign.
0.1.4 #
- UPDATE: Add event queueing logic.
0.1.5 #
- FIX: Optimized logic for error catching in events.