diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f38b512..29fb2311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.0.0 + +- Production version! +- Minor fixes on session proposal and wallet redirection after connection +- Minor bug fixes + ## 3.0.0-beta19 - Chain switching enhancements diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index ab9d4e76..4ad644c4 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -7,8 +7,13 @@ import 'package:walletconnect_flutter_dapp/utils/dart_defines.dart'; import 'package:walletconnect_flutter_dapp/utils/string_constants.dart'; class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.swapTheme}); - final void Function() swapTheme; + const MyHomePage({ + super.key, + required this.swapTheme, + required this.changeTheme, + }); + final VoidCallback swapTheme; + final VoidCallback changeTheme; @override State createState() => _MyHomePageState(); @@ -32,8 +37,8 @@ class _MyHomePageState extends State { projectId: DartDefines.projectId, logLevel: LogLevel.error, metadata: const PairingMetadata( - name: 'Web3Modal Flutter Example', - description: 'Web3Modal Flutter Example', + name: StringConstants.w3mPageTitleV3, + description: StringConstants.w3mPageTitleV3, url: 'https://www.walletconnect.com/', icons: ['https://web3modal.com/images/rpc-illustration.png'], redirect: Redirect( @@ -41,12 +46,6 @@ class _MyHomePageState extends State { universal: 'https://www.walletconnect.com', ), ), - optionalNamespaces: { - 'eip155': const W3MNamespace( - methods: EthConstants.allMethods, - events: EthConstants.allEvents, - ), - }, ); await _w3mService.init(); @@ -87,6 +86,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { + final isSquare = Web3ModalTheme.radiusesOf(context).isSquare(); return Scaffold( backgroundColor: Web3ModalTheme.colorsOf(context).background300, appBar: AppBar( @@ -95,6 +95,12 @@ class _MyHomePageState extends State { backgroundColor: Web3ModalTheme.colorsOf(context).background100, foregroundColor: Web3ModalTheme.colorsOf(context).foreground100, actions: [ + IconButton( + icon: isSquare + ? const Icon(Icons.yard_outlined) + : const Icon(Icons.yard), + onPressed: widget.changeTheme, + ), IconButton( icon: Web3ModalTheme.maybeOf(context)?.isDarkMode ?? false ? const Icon(Icons.light_mode) @@ -161,9 +167,7 @@ class _ConnectedView extends StatelessWidget { const SizedBox.square(dimension: 12.0), W3MAccountButton(service: w3mService), SessionWidget( - session: w3mService.web3App!.sessions.getAll().first, - web3App: w3mService.web3App!, - selectedChain: w3mService.selectedChain!, + w3mService: w3mService, launchRedirect: () { w3mService.launchConnectedWallet(); }, @@ -179,13 +183,6 @@ final _exampleCustomChain = W3MChainInfo( namespace: 'eip155:42220', chainId: '42220', tokenName: 'CELO', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:42220'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://forno.celo.org/', blockExplorer: W3MBlockExplorer( name: 'Celo Explorer', diff --git a/example/lib/main.dart b/example/lib/main.dart index aa2fadec..9142385c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:walletconnect_flutter_dapp/home_page.dart'; +import 'package:walletconnect_flutter_dapp/utils/string_constants.dart'; import 'package:web3modal_flutter/web3modal_flutter.dart'; void main() { @@ -15,18 +16,7 @@ class MyApp extends StatefulWidget { class _MyAppState extends State with WidgetsBindingObserver { bool _isDarkMode = false; - // ignore: unused_field - final _themeData = Web3ModalThemeData( - lightColors: Web3ModalColors.lightMode.copyWith( - accent100: Colors.red, - background125: Colors.yellow.shade300, - ), - darkColors: Web3ModalColors.darkMode.copyWith( - accent100: Colors.green, - background125: Colors.brown, - ), - radiuses: Web3ModalRadiuses.square, - ); + Web3ModalThemeData? _themeData; @override void initState() { @@ -64,12 +54,14 @@ class _MyAppState extends State with WidgetsBindingObserver { Widget build(BuildContext context) { return Web3ModalTheme( isDarkMode: _isDarkMode, - // Uncomment to see how modal theme is changed - // themeData: _themeData, + themeData: _themeData, child: MaterialApp( debugShowCheckedModeBanner: false, - title: 'Flutter Demo', - home: MyHomePage(swapTheme: () => _swapTheme()), + title: StringConstants.w3mPageTitleV3, + home: MyHomePage( + swapTheme: () => _swapTheme(), + changeTheme: () => _changeTheme(), + ), ), ); } @@ -79,4 +71,22 @@ class _MyAppState extends State with WidgetsBindingObserver { _isDarkMode = !_isDarkMode; }); } + + void _changeTheme() { + setState(() { + _themeData = (_themeData == null) + ? Web3ModalThemeData( + lightColors: Web3ModalColors.lightMode.copyWith( + accent100: Colors.red, + background125: Colors.yellow.shade300, + ), + darkColors: Web3ModalColors.darkMode.copyWith( + accent100: Colors.green, + background125: Colors.brown, + ), + radiuses: Web3ModalRadiuses.square, + ) + : null; + }); + } } diff --git a/example/lib/utils/crypto/eip155.dart b/example/lib/utils/crypto/eip155.dart index e800d1b0..eda520d8 100644 --- a/example/lib/utils/crypto/eip155.dart +++ b/example/lib/utils/crypto/eip155.dart @@ -69,14 +69,9 @@ class EIP155 { static final Map methods = { EIP155UIMethods.personalSign: 'personal_sign', - // EIP155Methods.ethSign: 'eth_sign', - // EIP155Methods.ethSignTransaction: 'eth_signTransaction', - // EIP155UIMethods.ethSignTypedData: 'eth_signTypedData', EIP155UIMethods.ethSignTypedDataV4: 'eth_signTypedData_v4', EIP155UIMethods.testContractCall: 'test_contractCall', EIP155UIMethods.ethSendTransaction: 'eth_sendTransaction', - // EIP155Methods.walletSwitchEthereumChain: 'wallet_switchEthereumChain', - // EIP155Methods.walletAddEthereumChain: 'wallet_addEthereumChain' }; static final Map events = { @@ -85,7 +80,7 @@ class EIP155 { }; static Future callMethod({ - required IWeb3App web3App, + required W3MService w3mService, required String topic, required EIP155UIMethods method, required String chainId, @@ -95,7 +90,7 @@ class EIP155 { switch (method) { case EIP155UIMethods.personalSign: return personalSign( - web3App: web3App, + w3mService: w3mService, topic: topic, chainId: chainId, address: address, @@ -103,7 +98,7 @@ class EIP155 { ); case EIP155UIMethods.ethSignTypedDataV4: return ethSignTypedDataV4( - web3App: web3App, + w3mService: w3mService, topic: topic, chainId: chainId, address: address, @@ -111,7 +106,7 @@ class EIP155 { ); case EIP155UIMethods.testContractCall: return testContractCall( - web3App: web3App, + w3mService: w3mService, topic: topic, chainId: chainId, address: address, @@ -119,56 +114,27 @@ class EIP155 { case EIP155UIMethods.ethSendTransaction: return ethSendTransaction( - web3App: web3App, + w3mService: w3mService, topic: topic, chainId: chainId, transaction: EthereumTransaction( from: address, to: address, value: '0x01', + data: '0x', // to make it work with some wallets ), ); - // case EIP155UIMethods.ethSign: - // return ethSign( - // web3App: web3App, - // topic: topic, - // chainId: chainId, - // address: address, - // data: testSignData, - // ); - // case EIP155UIMethods.ethSignTransaction: - // return ethSignTransaction( - // web3App: web3App, - // topic: topic, - // chainId: chainId, - // transaction: EthereumTransaction( - // from: address, - // to: address, - // value: '0x01', - // ), - // ); - // case EIP155UIMethods.walletAddEthereumChain: - // case EIP155UIMethods.walletSwitchEthereumChain: - // return walletSwitchChain( - // web3App: web3App, - // topic: topic, - // chainId: chainId, - // chainInfo: ChainData.chains.firstWhere( - // (element) => element.chainId == chainId, - // orElse: () => ChainData.chains.first, - // ), - // ); } } static Future personalSign({ - required IWeb3App web3App, + required W3MService w3mService, required String topic, required String chainId, required String address, required String data, }) async { - return await web3App.request( + return await w3mService.web3App!.request( topic: topic, chainId: chainId, request: SessionRequestParams( @@ -179,13 +145,13 @@ class EIP155 { } static Future ethSignTypedDataV4({ - required IWeb3App web3App, + required W3MService w3mService, required String topic, required String chainId, required String address, required String data, }) async { - return await web3App.request( + return await w3mService.web3App!.request( topic: topic, chainId: chainId, request: SessionRequestParams( @@ -196,45 +162,46 @@ class EIP155 { } static Future testContractCall({ - required IWeb3App web3App, + required W3MService w3mService, required String topic, required String chainId, required String address, }) async { - final W3MChainInfo ethChain = W3MChainPresets.chains['1']!; - - final DeployedContract contract = DeployedContract( + final ethChain = W3MChainPresets.chains['1']!; + final contract = DeployedContract( ContractAbi.fromJson( jsonEncode(ContractDetails.readContractAbi), 'Tether (USDT)'), EthereumAddress.fromHex(ContractDetails.contractAddress), ); - final ContractFunction balanceFunction = contract.function('balanceOf'); + final balanceFunction = contract.function('balanceOf'); - final Transaction t = Transaction.callContract( + final transaction = Transaction.callContract( contract: contract, function: balanceFunction, parameters: [EthereumAddress.fromHex(ContractDetails.balanceAddress)], ); - return await web3App.request( + return await w3mService.web3App!.request( topic: topic, chainId: ethChain.namespace, request: SessionRequestParams( - method: 'eth_sendTransaction', + method: methods[EIP155UIMethods.ethSendTransaction]!, // Check the `web3dart_extension` file for this function - params: [t.toJson(fromAddress: ContractDetails.balanceAddress)], + params: [ + transaction.toJson(fromAddress: ContractDetails.balanceAddress), + ], ), ); } static Future ethSendTransaction({ - required IWeb3App web3App, + required W3MService w3mService, required String topic, required String chainId, required EthereumTransaction transaction, }) async { - return await web3App.request( + return await w3mService.web3App!.request( topic: topic, chainId: chainId, request: SessionRequestParams( @@ -243,81 +210,4 @@ class EIP155 { ), ); } - - // static Future walletSwitchChain({ - // required IWeb3App web3App, - // required String topic, - // required String chainId, - // required ChainMetadata chainInfo, - // }) async { - // final int chainIdInt = int.parse(chainInfo.chainId); - // final String chainHex = chainIdInt.toRadixString(16); - // try { - // return await web3App.request( - // topic: topic, - // chainId: chainId, - // request: SessionRequestParams( - // method: methods[EIP155UIMethods.walletSwitchEthereumChain]!, - // params: [ - // { - // 'chainId': '0x$chainHex', - // }, - // ], - // ), - // ); - // } catch (e) { - // return await web3App.request( - // topic: topic, - // chainId: chainId, - // request: SessionRequestParams( - // method: 'wallet_addEthereumChain', - // params: [ - // { - // 'chainId': '0x$chainHex', - // 'chainName': chainInfo.chainName, - // 'nativeCurrency': { - // 'name': chainInfo.tokenName, - // 'symbol': chainInfo.tokenName, - // 'decimals': 18, - // }, - // 'rpcUrls': [chainInfo.rpcUrl], - // }, - // ], - // ), - // ); - // } - // } - - // static Future ethSign({ - // required IWeb3App web3App, - // required String topic, - // required String chainId, - // required String address, - // required String data, - // }) async { - // return await web3App.request( - // topic: topic, - // chainId: chainId, - // request: SessionRequestParams( - // method: methods[EIP155UIMethods.ethSign]!, - // params: [address, data], - // ), - // ); - // } - - // static Future ethSignTransaction({ - // required IWeb3App web3App, - // required String topic, - // required String chainId, - // required EthereumTransaction transaction, - // }) async { - // return await web3App.request( - // topic: topic, - // chainId: chainId, - // request: SessionRequestParams( - // method: methods[EIP155UIMethods.ethSignTransaction]!, - // params: [transaction.toJson()], - // ), - // ); - // } } diff --git a/example/lib/utils/string_constants.dart b/example/lib/utils/string_constants.dart index 6a7bd419..f412ad7c 100644 --- a/example/lib/utils/string_constants.dart +++ b/example/lib/utils/string_constants.dart @@ -10,7 +10,7 @@ class StringConstants { static const String basicPageTitle = 'Basic'; static const String wcmPageTitle = 'WalletConnect Modal'; static const String w3mPageTitle = 'Web3Modal'; - static const String w3mPageTitleV3 = 'Web3Modal V3'; + static const String w3mPageTitleV3 = 'Web3Modal V3 Example'; static const String pairingsPageTitle = 'Pairings'; static const String sessionsPageTitle = 'Sessions'; static const String authPageTitle = 'Auth'; diff --git a/example/lib/widgets/session_widget.dart b/example/lib/widgets/session_widget.dart index 23eee700..78f118c7 100644 --- a/example/lib/widgets/session_widget.dart +++ b/example/lib/widgets/session_widget.dart @@ -12,15 +12,11 @@ import 'package:walletconnect_flutter_dapp/widgets/method_dialog.dart'; class SessionWidget extends StatefulWidget { const SessionWidget({ super.key, - required this.session, - required this.web3App, + required this.w3mService, required this.launchRedirect, - required this.selectedChain, }); - final SessionData session; - final IWeb3App web3App; - final W3MChainInfo selectedChain; + final W3MService w3mService; final void Function() launchRedirect; @override @@ -30,10 +26,11 @@ class SessionWidget extends StatefulWidget { class SessionWidgetState extends State { @override Widget build(BuildContext context) { + final session = widget.w3mService.web3App!.sessions.getAll().first; final List children = [ const SizedBox(height: StyleConstants.linear16), Text( - widget.session.peer.metadata.name, + session.peer.metadata.name, style: Web3ModalTheme.getDataOf(context).textStyles.title600.copyWith( color: Web3ModalTheme.colorsOf(context).foreground100, ), @@ -47,7 +44,7 @@ class SessionWidgetState extends State { ), ), Text( - widget.session.topic, + session.topic, style: Web3ModalTheme.getDataOf(context).textStyles.small400.copyWith( color: Web3ModalTheme.colorsOf(context).foreground100, ), @@ -70,16 +67,17 @@ class SessionWidgetState extends State { final List namespaceAccounts = []; // Loop through the namespaces, and get the accounts - for (final namespace in widget.session.namespaces.values) { + for (final namespace in session.namespaces.values) { namespaceAccounts.addAll(namespace.accounts); } + final selectedChain = widget.w3mService.selectedChain!; final containsChain = namespaceAccounts.indexWhere( - (nsa) => nsa.split(':')[1] == widget.selectedChain.chainId, + (nsa) => nsa.split(':')[1] == selectedChain.chainId, ); if (containsChain > -1) { final namespace = namespaceAccounts.firstWhere( - (nsa) => nsa.split(':')[1] == widget.selectedChain.chainId, + (nsa) => nsa.split(':')[1] == selectedChain.chainId, ); children.add(_buildAccountWidget(namespace)); } @@ -206,8 +204,9 @@ class SessionWidgetState extends State { } Widget _buildChainApprovedMethodsTiles() { + final session = widget.w3mService.web3App!.sessions.getAll().first; String methods = ''; - final approvedMethods = widget.session.namespaces['eip155']?.methods ?? []; + final approvedMethods = session.namespaces['eip155']?.methods ?? []; for (final method in approvedMethods) { methods += '$method, '; } @@ -225,8 +224,6 @@ class SessionWidgetState extends State { for (final String event in getChainEvents(chainMetadata.type)) { values.add( Container( - // alignment: Alignment.center, - // height: StyleConstants.linear40, margin: const EdgeInsets.symmetric( vertical: StyleConstants.linear8, horizontal: StyleConstants.linear8, @@ -263,23 +260,16 @@ class SessionWidgetState extends State { ChainMetadata chainMetadata, String address, ) { + final session = widget.w3mService.web3App!.sessions.getAll().first; switch (type) { case ChainType.eip155: return EIP155.callMethod( - web3App: widget.web3App, - topic: widget.session.topic, + w3mService: widget.w3mService, + topic: session.topic, method: method.toEip155Method()!, chainId: chainMetadata.w3mChainInfo.namespace, address: address.toLowerCase(), ); - // case ChainType.kadena: - // return Kadena.callMethod( - // web3App: widget.web3App, - // topic: widget.session.topic, - // method: method.toKadenaMethod()!, - // chainId: chainMetadata.chainId, - // address: address.toLowerCase(), - // ); default: return Future.value(); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 4a92d155..94ac943c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1107,7 +1107,7 @@ packages: path: ".." relative: true source: path - version: "3.0.0-beta19" + version: "3.0.0" web_socket_channel: dependency: transitive description: diff --git a/lib/constants/eth_constants.dart b/lib/constants/eth_constants.dart index 6d65149c..2bff7b92 100644 --- a/lib/constants/eth_constants.dart +++ b/lib/constants/eth_constants.dart @@ -1,4 +1,5 @@ class EthConstants { + static const namespace = 'eip155'; static const walletSwitchEthChain = 'wallet_switchEthereumChain'; static const walletAddEthChain = 'wallet_addEthereumChain'; static const requiredMethods = [ diff --git a/lib/constants/namespaces.dart b/lib/constants/namespaces.dart index 847cb6c0..9d3045a7 100644 --- a/lib/constants/namespaces.dart +++ b/lib/constants/namespaces.dart @@ -1,5 +1,7 @@ import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +@Deprecated( + 'This file is going to be deleted soon. Refer to EthConstants or W3MChainPresets') class NamespaceConstants { static const Map ethereum = { 'eip155': RequiredNamespace( diff --git a/lib/constants/string_constants.dart b/lib/constants/string_constants.dart index 37e9f056..f43f9903 100644 --- a/lib/constants/string_constants.dart +++ b/lib/constants/string_constants.dart @@ -1,7 +1,7 @@ class StringConstants { // Request Headers static const X_SDK_TYPE = 'w3m'; - static const X_SDK_VERSION = '3.0.0-beta19'; + static const X_SDK_VERSION = '3.0.0'; static const X_CORE_SDK_VERSION = 'flutter_v2.1.9'; // UI @@ -24,7 +24,8 @@ class StringConstants { static const String noResults = 'No results found'; // Storage - static const String recentWallet = 'w3m_recentWallet'; + static const String recentWalletId = 'w3m_recentWallet'; + static const String walletData = 'w3m_walletData'; static const String selectedChainId = 'w3m_selectedChainId'; // Urls diff --git a/lib/models/w3m_chain_info.dart b/lib/models/w3m_chain_info.dart index e7298059..e05dc962 100644 --- a/lib/models/w3m_chain_info.dart +++ b/lib/models/w3m_chain_info.dart @@ -11,8 +11,6 @@ class W3MChainInfo with _$W3MChainInfo { required String namespace, required String tokenName, required String rpcUrl, - @Default({}) Map requiredNamespaces, - @Default({}) Map optionalNamespaces, String? chainIcon, W3MBlockExplorer? blockExplorer, }) = _W3MChainInfo; diff --git a/lib/models/w3m_chain_info.freezed.dart b/lib/models/w3m_chain_info.freezed.dart index 8c2652a9..0b8e5ef3 100644 --- a/lib/models/w3m_chain_info.freezed.dart +++ b/lib/models/w3m_chain_info.freezed.dart @@ -21,10 +21,6 @@ mixin _$W3MChainInfo { String get namespace => throw _privateConstructorUsedError; String get tokenName => throw _privateConstructorUsedError; String get rpcUrl => throw _privateConstructorUsedError; - Map get requiredNamespaces => - throw _privateConstructorUsedError; - Map get optionalNamespaces => - throw _privateConstructorUsedError; String? get chainIcon => throw _privateConstructorUsedError; W3MBlockExplorer? get blockExplorer => throw _privateConstructorUsedError; @@ -45,8 +41,6 @@ abstract class $W3MChainInfoCopyWith<$Res> { String namespace, String tokenName, String rpcUrl, - Map requiredNamespaces, - Map optionalNamespaces, String? chainIcon, W3MBlockExplorer? blockExplorer}); @@ -71,8 +65,6 @@ class _$W3MChainInfoCopyWithImpl<$Res, $Val extends W3MChainInfo> Object? namespace = null, Object? tokenName = null, Object? rpcUrl = null, - Object? requiredNamespaces = null, - Object? optionalNamespaces = null, Object? chainIcon = freezed, Object? blockExplorer = freezed, }) { @@ -97,14 +89,6 @@ class _$W3MChainInfoCopyWithImpl<$Res, $Val extends W3MChainInfo> ? _value.rpcUrl : rpcUrl // ignore: cast_nullable_to_non_nullable as String, - requiredNamespaces: null == requiredNamespaces - ? _value.requiredNamespaces - : requiredNamespaces // ignore: cast_nullable_to_non_nullable - as Map, - optionalNamespaces: null == optionalNamespaces - ? _value.optionalNamespaces - : optionalNamespaces // ignore: cast_nullable_to_non_nullable - as Map, chainIcon: freezed == chainIcon ? _value.chainIcon : chainIcon // ignore: cast_nullable_to_non_nullable @@ -143,8 +127,6 @@ abstract class _$$_W3MChainInfoCopyWith<$Res> String namespace, String tokenName, String rpcUrl, - Map requiredNamespaces, - Map optionalNamespaces, String? chainIcon, W3MBlockExplorer? blockExplorer}); @@ -168,8 +150,6 @@ class __$$_W3MChainInfoCopyWithImpl<$Res> Object? namespace = null, Object? tokenName = null, Object? rpcUrl = null, - Object? requiredNamespaces = null, - Object? optionalNamespaces = null, Object? chainIcon = freezed, Object? blockExplorer = freezed, }) { @@ -194,14 +174,6 @@ class __$$_W3MChainInfoCopyWithImpl<$Res> ? _value.rpcUrl : rpcUrl // ignore: cast_nullable_to_non_nullable as String, - requiredNamespaces: null == requiredNamespaces - ? _value._requiredNamespaces - : requiredNamespaces // ignore: cast_nullable_to_non_nullable - as Map, - optionalNamespaces: null == optionalNamespaces - ? _value._optionalNamespaces - : optionalNamespaces // ignore: cast_nullable_to_non_nullable - as Map, chainIcon: freezed == chainIcon ? _value.chainIcon : chainIcon // ignore: cast_nullable_to_non_nullable @@ -223,12 +195,8 @@ class _$_W3MChainInfo implements _W3MChainInfo { required this.namespace, required this.tokenName, required this.rpcUrl, - final Map requiredNamespaces = const {}, - final Map optionalNamespaces = const {}, this.chainIcon, - this.blockExplorer}) - : _requiredNamespaces = requiredNamespaces, - _optionalNamespaces = optionalNamespaces; + this.blockExplorer}); @override final String chainName; @@ -240,26 +208,6 @@ class _$_W3MChainInfo implements _W3MChainInfo { final String tokenName; @override final String rpcUrl; - final Map _requiredNamespaces; - @override - @JsonKey() - Map get requiredNamespaces { - if (_requiredNamespaces is EqualUnmodifiableMapView) - return _requiredNamespaces; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_requiredNamespaces); - } - - final Map _optionalNamespaces; - @override - @JsonKey() - Map get optionalNamespaces { - if (_optionalNamespaces is EqualUnmodifiableMapView) - return _optionalNamespaces; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_optionalNamespaces); - } - @override final String? chainIcon; @override @@ -267,7 +215,7 @@ class _$_W3MChainInfo implements _W3MChainInfo { @override String toString() { - return 'W3MChainInfo(chainName: $chainName, chainId: $chainId, namespace: $namespace, tokenName: $tokenName, rpcUrl: $rpcUrl, requiredNamespaces: $requiredNamespaces, optionalNamespaces: $optionalNamespaces, chainIcon: $chainIcon, blockExplorer: $blockExplorer)'; + return 'W3MChainInfo(chainName: $chainName, chainId: $chainId, namespace: $namespace, tokenName: $tokenName, rpcUrl: $rpcUrl, chainIcon: $chainIcon, blockExplorer: $blockExplorer)'; } @override @@ -283,10 +231,6 @@ class _$_W3MChainInfo implements _W3MChainInfo { (identical(other.tokenName, tokenName) || other.tokenName == tokenName) && (identical(other.rpcUrl, rpcUrl) || other.rpcUrl == rpcUrl) && - const DeepCollectionEquality() - .equals(other._requiredNamespaces, _requiredNamespaces) && - const DeepCollectionEquality() - .equals(other._optionalNamespaces, _optionalNamespaces) && (identical(other.chainIcon, chainIcon) || other.chainIcon == chainIcon) && (identical(other.blockExplorer, blockExplorer) || @@ -294,17 +238,8 @@ class _$_W3MChainInfo implements _W3MChainInfo { } @override - int get hashCode => Object.hash( - runtimeType, - chainName, - chainId, - namespace, - tokenName, - rpcUrl, - const DeepCollectionEquality().hash(_requiredNamespaces), - const DeepCollectionEquality().hash(_optionalNamespaces), - chainIcon, - blockExplorer); + int get hashCode => Object.hash(runtimeType, chainName, chainId, namespace, + tokenName, rpcUrl, chainIcon, blockExplorer); @JsonKey(ignore: true) @override @@ -320,8 +255,6 @@ abstract class _W3MChainInfo implements W3MChainInfo { required final String namespace, required final String tokenName, required final String rpcUrl, - final Map requiredNamespaces, - final Map optionalNamespaces, final String? chainIcon, final W3MBlockExplorer? blockExplorer}) = _$_W3MChainInfo; @@ -336,10 +269,6 @@ abstract class _W3MChainInfo implements W3MChainInfo { @override String get rpcUrl; @override - Map get requiredNamespaces; - @override - Map get optionalNamespaces; - @override String? get chainIcon; @override W3MBlockExplorer? get blockExplorer; diff --git a/lib/services/blockchain_api_service/blockchain_api_utils.dart b/lib/services/blockchain_api_service/blockchain_api_utils.dart index 76f303d6..881706d2 100644 --- a/lib/services/blockchain_api_service/blockchain_api_utils.dart +++ b/lib/services/blockchain_api_service/blockchain_api_utils.dart @@ -1,12 +1,11 @@ import 'dart:convert'; import 'package:http/http.dart' as http; +import 'package:web3modal_flutter/constants/eth_constants.dart'; import 'package:web3modal_flutter/services/blockchain_api_service/blockchain_identity.dart'; import 'package:web3modal_flutter/services/blockchain_api_service/i_blockchain_api_utils.dart'; class BlockchainApiUtils extends IBlockchainApiUtils { - static const namespace = 'eip155'; - @override final String blockchainApiUriRoot; @@ -20,14 +19,11 @@ class BlockchainApiUtils extends IBlockchainApiUtils { @override Future getIdentity(String address, int chainId) async { - final String scope = '$namespace:$chainId'; - final String endpoint = - '$blockchainApiUriRoot/v1/identity/$address?chainId=$scope&projectId=$projectId'; - - final response = await http.get( - Uri.parse(endpoint), - ); + final scope = '${EthConstants.namespace}:$chainId'; + final endpoint = '$blockchainApiUriRoot/v1/identity/$address' + '?chainId=$scope&projectId=$projectId'; + final response = await http.get(Uri.parse(endpoint)); if (response.statusCode == 200) { return BlockchainIdentity.fromJson( jsonDecode(response.body), diff --git a/lib/services/explorer_service/explorer_service.dart b/lib/services/explorer_service/explorer_service.dart index 25210e43..cf51f35a 100644 --- a/lib/services/explorer_service/explorer_service.dart +++ b/lib/services/explorer_service/explorer_service.dart @@ -30,34 +30,34 @@ class ExplorerService implements IExplorerService { late RequestParams _requestParams; @override - ValueNotifier initialized = ValueNotifier(false); - - String _recentWalletId = ''; - @override - String get recentWalletId => _recentWalletId; + final String projectId; @override - final String projectId; + ValueNotifier initialized = ValueNotifier(false); @override ValueNotifier totalListings = ValueNotifier(0); List _listings = []; - @override ValueNotifier> listings = ValueNotifier([]); - Set _installedWalletIds = {}; + final _debouncer = Debouncer(milliseconds: 300); + + String? _currentSearchValue; + @override + String get searchValue => _currentSearchValue ?? ''; @override ValueNotifier isSearching = ValueNotifier(false); + Set _installedWalletIds = {}; + @override Set? featuredWalletIds; @override Set? includedWalletIds; - String? get _includedWalletsParam { final includedIds = (includedWalletIds ?? {}); return includedIds.isNotEmpty ? includedIds.join(',') : null; @@ -65,15 +65,13 @@ class ExplorerService implements IExplorerService { @override Set? excludedWalletIds; - String? get _excludedWalletsParam { final excludedIds = (excludedWalletIds ?? {}) ..addAll(_installedWalletIds); return excludedIds.isNotEmpty ? excludedIds.join(',') : null; } - int _prevCount = 0; - + int _currentWalletsCount = 0; bool _canPaginate = true; @override bool get canPaginate => _canPaginate; @@ -127,9 +125,17 @@ class ExplorerService implements IExplorerService { } Future _getRecentWalletAndOrder() async { - final recentWalletId = - storageService.instance.getString(StringConstants.recentWallet); - await updateRecentPosition(recentWalletId); + W3MWalletInfo? walletInfo; + final walletString = storageService.instance.getString( + StringConstants.walletData, + ); + final recentWalletId = storageService.instance.getString( + StringConstants.recentWalletId, + ); + if ((walletString ?? '').isNotEmpty) { + walletInfo = W3MWalletInfo.fromJson(jsonDecode(walletString!)); + } + await _updateRecentWalletId(walletInfo, walletId: recentWalletId); } @override @@ -142,10 +148,10 @@ class ExplorerService implements IExplorerService { ); _listings = [..._listings, ...newListings]; listings.value = _listings; - if (newListings.length < _prevCount) { + if (newListings.length < _currentWalletsCount) { _canPaginate = false; } else { - _prevCount = newListings.length; + _currentWalletsCount = newListings.length; } } @@ -205,13 +211,11 @@ class ExplorerService implements IExplorerService { RequestParams? params, bool updateCount = true, }) async { + final p = params?.toJson() ?? {}; try { final headers = coreUtils.instance.getAPIHeaders(projectId, _referer); - final uri = Uri.parse('$_apiUrl/getWallets'); - final response = await _client.get( - uri.replace(queryParameters: params?.toJson() ?? {}), - headers: headers, - ); + final uri = Uri.parse('$_apiUrl/getWallets').replace(queryParameters: p); + final response = await _client.get(uri, headers: headers); final apiResponse = ApiResponse.fromJson( jsonDecode(response.body), (json) => Listing.fromJson(json), @@ -219,34 +223,44 @@ class ExplorerService implements IExplorerService { if (updateCount) { totalListings.value += apiResponse.count; } - W3MLoggerUtil.logger - .t('[$runtimeType] _fetchListings() $uri ${params?.toJson()}'); + W3MLoggerUtil.logger.t('[$runtimeType] _fetchListings() $uri $p'); return apiResponse.data .toList() .sortByRecommended(featuredWalletIds) .toW3MWalletInfo(); } catch (error) { - W3MLoggerUtil.logger.e( - '[$runtimeType] Error fetching wallet listings with params ${params?.toJson()}', - error: error, - ); + W3MLoggerUtil.logger + .e('[$runtimeType] Error fetch wallets params: $p', error: error); throw Exception(e); } } @override - Future updateRecentPosition(String? recentId) async { - _recentWalletId = recentId ?? ''; + Future storeConnectedWalletData(W3MWalletInfo? walletInfo) async { + if (walletInfo == null) return; + final walletDataString = jsonEncode(walletInfo.toJson()); + await storageService.instance.setString( + StringConstants.walletData, + walletDataString, + ); + await _updateRecentWalletId(walletInfo); + } + + Future _updateRecentWalletId( + W3MWalletInfo? walletInfo, { + String? walletId, + }) async { + final recentId = walletInfo?.listing.id ?? walletId ?? ''; // Set the recent await storageService.instance.setString( - StringConstants.recentWallet, - _recentWalletId, + StringConstants.recentWalletId, + recentId, ); final currentListings = List.from( _listings.map((e) => e.copyWith(recent: false)).toList(), ); final recentWallet = currentListings.firstWhereOrNull( - (e) => e.listing.id == _recentWalletId, + (e) => e.listing.id == recentId, ); if (recentWallet != null) { final rw = recentWallet.copyWith(recent: true); @@ -296,12 +310,6 @@ class ExplorerService implements IExplorerService { _debouncer.run(() => isSearching.value = false); } - String? _currentSearchValue; - @override - String get searchValue => _currentSearchValue ?? ''; - - final _debouncer = Debouncer(milliseconds: 300); - @override String getWalletImageUrl(String imageId) => '$_apiUrl/getWalletImage/$imageId'; diff --git a/lib/services/explorer_service/i_explorer_service.dart b/lib/services/explorer_service/i_explorer_service.dart index 961f7552..6e8c1b0e 100644 --- a/lib/services/explorer_service/i_explorer_service.dart +++ b/lib/services/explorer_service/i_explorer_service.dart @@ -22,9 +22,6 @@ abstract class IExplorerService { /// If excludedWalletIds is set wallets from this list are going to be excluded Set? excludedWalletIds; - /// Id of the recently used wallet app - String get recentWalletId; - /// Init service Future init(); @@ -41,7 +38,7 @@ abstract class IExplorerService { String get searchValue; /// update the recently used position to the top list - Future updateRecentPosition(String? recentId); + Future storeConnectedWalletData(W3MWalletInfo? walletInfo); String getWalletImageUrl(String imageId); diff --git a/lib/services/w3m_service/w3m_service.dart b/lib/services/w3m_service/w3m_service.dart index 7546b57f..a84b86c9 100644 --- a/lib/services/w3m_service/w3m_service.dart +++ b/lib/services/w3m_service/w3m_service.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:event/event.dart'; import 'package:flutter/material.dart'; @@ -112,6 +113,7 @@ class W3MService with ChangeNotifier implements IW3MService { IWeb3App? web3App, String? projectId, PairingMetadata? metadata, + Map? requiredNamespaces, Map? optionalNamespaces, Set? featuredWalletIds, Set? includedWalletIds, @@ -131,33 +133,9 @@ class W3MService with ChangeNotifier implements IW3MService { ); _projectId = projectId ?? _web3App!.core.projectId; - if (optionalNamespaces != null) { - // Set the optional namespaces declared by the user on W3MService object - _optionalNamespaces = optionalNamespaces.map( - (key, value) => MapEntry( - key, - RequiredNamespace( - chains: value.chains ?? - W3MChainPresets.chains.values.map((e) { - return e.namespace; - }).toList(), - methods: value.methods, - events: value.events, - ), - ), - ); - } else { - // Set the optional namespaces to everything in our chain presets - _optionalNamespaces = { - 'eip155': RequiredNamespace( - methods: EthConstants.optionalMethods, - chains: W3MChainPresets.chains.values.map((e) { - return e.namespace; - }).toList(), - events: EthConstants.optionalEvents, - ), - }; - } + _setRequiredNamespaces(requiredNamespaces); + + _setOptionalNamespaces(optionalNamespaces); explorerService.instance = ExplorerService( projectId: _projectId, @@ -217,10 +195,6 @@ class W3MService with ChangeNotifier implements IW3MService { } } - if (_optionalNamespaces.isNotEmpty) { - _setOptionalNamespaces(_optionalNamespaces); - } - // Get the chainId of the chain we are connected to. await _selectChainFromStoredId(); @@ -272,7 +246,7 @@ class W3MService with ChangeNotifier implements IW3MService { return false; } final sessionNamespaces = _currentSession!.namespaces; - final nsMethods = sessionNamespaces['eip155']?.methods ?? []; + final nsMethods = sessionNamespaces[EthConstants.namespace]?.methods ?? []; final supportsAddChain = nsMethods.contains(EthConstants.walletAddEthChain); return supportsAddChain; @@ -325,8 +299,8 @@ class W3MService with ChangeNotifier implements IW3MService { return null; } final sessionNamespaces = _currentSession!.namespaces; - final nsAccounts = sessionNamespaces['eip155']?.accounts ?? []; - final approvedChains = NamespaceUtils.getChainsFromAccounts(nsAccounts); + final accounts = sessionNamespaces[EthConstants.namespace]?.accounts ?? []; + final approvedChains = NamespaceUtils.getChainsFromAccounts(accounts); return approvedChains; } @@ -344,8 +318,6 @@ class W3MService with ChangeNotifier implements IW3MService { } void _setEthChain(W3MChainInfo chainInfo) async { - final isSwitch = _currentSelectedChain?.chainId != chainInfo.chainId; - _currentSelectedChain = chainInfo; // Get the token/chain icon _tokenImageUrl = _getTokenImage(chainInfo); @@ -359,17 +331,8 @@ class W3MService with ChangeNotifier implements IW3MService { _currentSelectedChain!.chainId, ); - _setRequiredNamespaces(_currentSelectedChain!.requiredNamespaces); - if (_optionalNamespaces.isEmpty) { - _setOptionalNamespaces(_currentSelectedChain!.optionalNamespaces); - } - W3MLoggerUtil.logger.t('[$runtimeType] setSelectedChain success'); _loadAccountData(); - - if (isSwitch) { - debugPrint('Chain Set'); - } } String _getTokenImage(W3MChainInfo chainInfo) { @@ -541,9 +504,7 @@ class W3MService with ChangeNotifier implements IW3MService { try { _currentSession = await connectResponse!.session.future; _setSessionValues(_currentSession!); - await explorerService.instance!.updateRecentPosition( - _selectedWallet?.listing.id, - ); + await explorerService.instance!.storeConnectedWalletData(_selectedWallet); } on TimeoutException { W3MLoggerUtil.logger .i('[$runtimeType] Rebuilding session, ending future'); @@ -681,23 +642,55 @@ class W3MService with ChangeNotifier implements IW3MService { _web3App!.core.heartbeat.onPulse.unsubscribe(onHeartbeatPulse); } - void _setRequiredNamespaces(Map requiredNSpaces) { - if (requiredNSpaces.isNotEmpty) { - _checkInitialized(); - W3MLoggerUtil.logger - .i('[$runtimeType] _setRequiredNamespaces $requiredNSpaces'); - _requiredNamespaces = requiredNSpaces; - _notify(); + void _setRequiredNamespaces(Map? requiredNSpaces) { + if (requiredNSpaces != null) { + // Set the required namespaces declared by the user on W3MService object + _requiredNamespaces = requiredNSpaces.map( + (key, value) => MapEntry( + key, + RequiredNamespace( + chains: value.chains ?? [W3MChainPresets.chains['1']!.namespace], + methods: value.methods, + events: value.events, + ), + ), + ); + } else { + // Set the required namespaces to everything in our chain presets + _requiredNamespaces = { + EthConstants.namespace: RequiredNamespace( + methods: EthConstants.requiredMethods, + chains: [W3MChainPresets.chains['1']!.namespace], + events: EthConstants.requiredEvents, + ), + }; } } - void _setOptionalNamespaces(Map optionalNSpaces) { - if (optionalNSpaces.isNotEmpty) { - _checkInitialized(); - W3MLoggerUtil.logger - .i('[$runtimeType] _setOptionalNamespaces: $optionalNSpaces'); - _optionalNamespaces = optionalNSpaces; - _notify(); + void _setOptionalNamespaces(Map? optionalNSpaces) { + if (optionalNSpaces != null) { + // Set the optional namespaces declared by the user on W3MService object + _optionalNamespaces = optionalNSpaces.map( + (key, value) => MapEntry( + key, + RequiredNamespace( + chains: value.chains ?? + W3MChainPresets.chains.values.map((e) => e.namespace).toList(), + methods: value.methods, + events: value.events, + ), + ), + ); + } else { + // Set the optional namespaces to everything in our chain presets + _optionalNamespaces = { + EthConstants.namespace: RequiredNamespace( + methods: EthConstants.optionalMethods, + chains: + W3MChainPresets.chains.values.map((e) => e.namespace).toList(), + events: EthConstants.optionalEvents, + ), + }; } } @@ -734,10 +727,11 @@ class W3MService with ChangeNotifier implements IW3MService { } Future _switchToEthChain(W3MChainInfo newChain) async { - final int chainIdInt = int.parse(newChain.chainId); - final String chainHex = chainIdInt.toRadixString(16); - final String chainId = 'eip155:${_currentSelectedChain!.chainId}'; - final Map params = {'chainId': '0x$chainHex'}; + final chainIdInt = int.parse(newChain.chainId); + final chainHex = chainIdInt.toRadixString(16); + final chainId = + '${EthConstants.namespace}:${_currentSelectedChain!.chainId}'; + final params = {'chainId': '0x$chainHex'}; return _web3App! .request( topic: _currentSession!.topic, @@ -808,7 +802,6 @@ class W3MService with ChangeNotifier implements IW3MService { void _cleanSession() { _currentSelectedChain = null; - _setRequiredNamespaces({}); _isConnected = false; _address = null; _currentSession = null; @@ -827,18 +820,16 @@ class W3MService with ChangeNotifier implements IW3MService { final metadata = _currentSession?.peer.metadata; final sessionRedirect = metadata?.redirect; if (sessionRedirect == null) { - final redirect = await explorerService.instance?.tryWalletRedirectByName( - metadata?.name, + final walletString = storageService.instance.getString( + StringConstants.walletData, ); - - if (redirect == null) { - return null; + if ((walletString ?? '').isNotEmpty) { + final walletInfo = W3MWalletInfo.fromJson(jsonDecode(walletString!)); + return explorerService.instance!.getWalletRedirect(walletInfo.listing); } - return WalletRedirect( - mobile: redirect.mobile, - desktop: redirect.desktop, - web: redirect.web, + return await explorerService.instance?.tryWalletRedirectByName( + metadata?.name, ); } diff --git a/lib/utils/core/core_utils.dart b/lib/utils/core/core_utils.dart index d5acf368..8cc09c76 100644 --- a/lib/utils/core/core_utils.dart +++ b/lib/utils/core/core_utils.dart @@ -70,6 +70,16 @@ class CoreUtils extends ICoreUtils { return Uri.parse('${plainAppUrl}wc?uri=$encodedWcUrl'); } + @override + String formatChainBalance(double? chainBalance, {int precision = 1}) { + if (chainBalance == null) { + return '_._'; + } + return chainBalance + .toStringAsPrecision(precision) + .replaceAll(RegExp(r'([.]*0+)(?!.*\d)'), ''); + } + @override String getUserAgent() { String userAgent = '${StringConstants.X_SDK_TYPE}' diff --git a/lib/utils/core/i_core_utils.dart b/lib/utils/core/i_core_utils.dart index a4e9e3a4..4055db62 100644 --- a/lib/utils/core/i_core_utils.dart +++ b/lib/utils/core/i_core_utils.dart @@ -19,6 +19,8 @@ abstract class ICoreUtils { /// https://metamask.app.link/ is a universal URL Uri? formatWebUrl(String? appUrl, String wcUri); + String formatChainBalance(double? chainBalance, {int precision = 1}); + /// Returns the user agent string. Used with the explorer and other API endpoints. String getUserAgent(); diff --git a/lib/utils/util.dart b/lib/utils/util.dart index 3741abe9..0b638584 100644 --- a/lib/utils/util.dart +++ b/lib/utils/util.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +import 'package:web3modal_flutter/constants/eth_constants.dart'; class Util { static String shorten(String value, {bool short = false}) { @@ -71,15 +72,15 @@ class Util { } static Set getChainsFromNamespace(Map ns) { - return ns['eip155']?.chains?.toSet() ?? {}; + return ns[EthConstants.namespace]?.chains?.toSet() ?? {}; } static Set getMethodsFromNamespace( Map ns) { - return ns['eip155']?.methods.toSet() ?? {}; + return ns[EthConstants.namespace]?.methods.toSet() ?? {}; } static Set getEventsFromNamespace(Map ns) { - return ns['eip155']?.events.toSet() ?? {}; + return ns[EthConstants.namespace]?.events.toSet() ?? {}; } } diff --git a/lib/utils/w3m_chains_presets.dart b/lib/utils/w3m_chains_presets.dart index a989f78d..3a356fcd 100644 --- a/lib/utils/w3m_chains_presets.dart +++ b/lib/utils/w3m_chains_presets.dart @@ -1,6 +1,4 @@ -import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:web3modal_flutter/models/w3m_chain_info.dart'; -import 'package:web3modal_flutter/constants/eth_constants.dart'; class W3MChainPresets { /// All RPC urls were found here: https://rpc.info/ @@ -11,13 +9,6 @@ class W3MChainPresets { chainId: '1', chainIcon: chainImagesId['1'], tokenName: 'ETH', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:1'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://eth.drpc.org', blockExplorer: W3MBlockExplorer( name: 'Etherscan', @@ -30,13 +21,6 @@ class W3MChainPresets { chainId: '42161', chainIcon: chainImagesId['42161'], tokenName: 'ARB', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:42161'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://arbitrum.blockpi.network/v1/rpc/public', blockExplorer: W3MBlockExplorer( name: 'Arbiscan', @@ -49,13 +33,6 @@ class W3MChainPresets { chainId: '137', chainIcon: chainImagesId['137'], tokenName: 'MATIC', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:137'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://polygon.drpc.org', blockExplorer: W3MBlockExplorer( name: 'Explorer', @@ -68,13 +45,6 @@ class W3MChainPresets { chainId: '43114', chainIcon: chainImagesId['43114'], tokenName: 'AVAX', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:43114'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://api.avax.network/ext/bc/C/rpc', blockExplorer: W3MBlockExplorer( name: 'Snowtrace', @@ -87,13 +57,6 @@ class W3MChainPresets { chainId: '56', chainIcon: chainImagesId['56'], tokenName: 'BNB', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:56'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://bsc-dataseed.binance.org/', blockExplorer: W3MBlockExplorer( name: 'BSC Scan', @@ -106,13 +69,6 @@ class W3MChainPresets { chainId: '10', chainIcon: chainImagesId['10'], tokenName: 'OP', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:10'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://mainnet.optimism.io/', ), '250': W3MChainInfo( @@ -121,13 +77,6 @@ class W3MChainPresets { chainId: '250', chainIcon: chainImagesId['250'], tokenName: 'FTM', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:250'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://rpc.ftm.tools/', blockExplorer: W3MBlockExplorer( name: 'FTM Scan', @@ -140,13 +89,6 @@ class W3MChainPresets { chainId: '9001', chainIcon: chainImagesId['9001'], tokenName: 'EVMOS', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:9001'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://evmos-evm.publicnode.com', ), '4689': W3MChainInfo( @@ -155,13 +97,6 @@ class W3MChainPresets { chainId: '4689', chainIcon: chainImagesId['4689'], tokenName: 'IOTX', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:4689'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://rpc.ankr.com/iotex', blockExplorer: W3MBlockExplorer( name: 'IOTEX Scan', @@ -174,13 +109,6 @@ class W3MChainPresets { chainId: '1088', chainIcon: chainImagesId['1088'], tokenName: 'METIS', - optionalNamespaces: { - 'eip155': const RequiredNamespace( - methods: EthConstants.allMethods, - chains: ['eip155:1088'], - events: EthConstants.allEvents, - ), - }, rpcUrl: 'https://metis-mainnet.public.blastapi.io', blockExplorer: W3MBlockExplorer( name: 'Andromeda Explorer', diff --git a/lib/widgets/buttons/balance_button.dart b/lib/widgets/buttons/balance_button.dart index e71feb2f..a3a9a3e4 100644 --- a/lib/widgets/buttons/balance_button.dart +++ b/lib/widgets/buttons/balance_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/services/w3m_service/i_w3m_service.dart'; import 'package:web3modal_flutter/theme/w3m_theme.dart'; +import 'package:web3modal_flutter/utils/core/core_utils_singleton.dart'; import 'package:web3modal_flutter/widgets/buttons/base_button.dart'; import 'package:web3modal_flutter/widgets/icons/rounded_icon.dart'; @@ -23,8 +24,8 @@ class BalanceButton extends StatefulWidget { } class _BalanceButtonState extends State { - String? _tokenImage; String _balance = BalanceButton.balanceDefault; + String? _tokenImage; String? _tokenName; @override @@ -43,14 +44,11 @@ class _BalanceButtonState extends State { void _w3mServiceUpdated() { setState(() { _tokenImage = widget.service.tokenImageUrl; - _balance = widget.service.chainBalance == null - ? BalanceButton.balanceDefault - : widget.service.chainBalance!.toStringAsPrecision(4); - RegExp regex = RegExp(r'([.]*0+)(?!.*\d)'); - _balance = _balance.replaceAll(regex, ''); - _tokenName = widget.service.selectedChain == null - ? null - : widget.service.selectedChain!.tokenName; + _balance = coreUtils.instance.formatChainBalance( + widget.service.chainBalance, + precision: 4, + ); + _tokenName = widget.service.selectedChain?.tokenName; }); } diff --git a/lib/widgets/text/w3m_balance.dart b/lib/widgets/text/w3m_balance.dart index 4310c83d..9f5afcaa 100644 --- a/lib/widgets/text/w3m_balance.dart +++ b/lib/widgets/text/w3m_balance.dart @@ -1,13 +1,12 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/services/w3m_service/i_w3m_service.dart'; import 'package:web3modal_flutter/theme/w3m_theme.dart'; -import 'package:web3modal_flutter/widgets/web3modal_provider.dart'; +import 'package:web3modal_flutter/utils/core/core_utils_singleton.dart'; import 'package:web3modal_flutter/widgets/buttons/balance_button.dart'; +import 'package:web3modal_flutter/widgets/web3modal_provider.dart'; import 'package:web3modal_flutter/widgets/buttons/base_button.dart'; class W3MBalanceText extends StatefulWidget { - static const balanceDefault = '_._'; - const W3MBalanceText({ super.key, this.size = BaseButtonSize.regular, @@ -45,14 +44,11 @@ class _W3MBalanceTextState extends State { void _w3mServiceUpdated() { if (_service == null) return; setState(() { - _balance = _service!.chainBalance == null - ? BalanceButton.balanceDefault - : _service!.chainBalance!.toStringAsPrecision(4); - RegExp regex = RegExp(r'([.]*0+)(?!.*\d)'); - _balance = _balance.replaceAll(regex, ''); - _tokenName = _service!.selectedChain == null - ? null - : _service!.selectedChain!.tokenName; + _balance = coreUtils.instance.formatChainBalance( + _service!.chainBalance, + precision: 4, + ); + _tokenName = _service?.selectedChain?.tokenName; }); } diff --git a/lib/widgets/w3m_account_button.dart b/lib/widgets/w3m_account_button.dart index ff6731c4..939da17f 100644 --- a/lib/widgets/w3m_account_button.dart +++ b/lib/widgets/w3m_account_button.dart @@ -2,9 +2,10 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/pages/account_page.dart'; import 'package:web3modal_flutter/services/w3m_service/i_w3m_service.dart'; import 'package:web3modal_flutter/theme/w3m_theme.dart'; +import 'package:web3modal_flutter/utils/core/core_utils_singleton.dart'; import 'package:web3modal_flutter/utils/util.dart'; -import 'package:web3modal_flutter/widgets/buttons/base_button.dart'; import 'package:web3modal_flutter/widgets/buttons/balance_button.dart'; +import 'package:web3modal_flutter/widgets/buttons/base_button.dart'; import 'package:web3modal_flutter/widgets/avatars/w3m_account_avatar.dart'; import 'package:web3modal_flutter/widgets/icons/rounded_icon.dart'; @@ -47,11 +48,9 @@ class _W3MAccountButtonState extends State { setState(() { _address = widget.service.address ?? ''; _tokenImage = widget.service.tokenImageUrl; - _balance = BalanceButton.balanceDefault; - if (widget.service.chainBalance != null) { - _balance = widget.service.chainBalance!.toStringAsPrecision(4); - _balance = _balance.replaceAll(RegExp(r'([.]*0+)(?!.*\d)'), ''); - } + _balance = coreUtils.instance.formatChainBalance( + widget.service.chainBalance, + ); _tokenName = widget.service.selectedChain?.tokenName; }); } diff --git a/pubspec.yaml b/pubspec.yaml index 644e4201..06a28f8d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: web3modal_flutter description: "WalletConnect Web3Modal: Simple, intuitive wallet login. With this drop-in UI SDK, enable any wallet's users to seamlessly log in to your app and enjoy a unified experience" -version: 3.0.0-beta19 +version: 3.0.0 repository: https://github.com/WalletConnect/Web3ModalFlutter environment: diff --git a/test/mock_classes.mocks.dart b/test/mock_classes.mocks.dart index 638d0d50..df37efea 100644 --- a/test/mock_classes.mocks.dart +++ b/test/mock_classes.mocks.dart @@ -280,6 +280,11 @@ class MockExplorerService extends _i1.Mock implements _i13.ExplorerService { _i1.throwOnMissingStub(this); } + @override + String get projectId => (super.noSuchMethod( + Invocation.getter(#projectId), + returnValue: '', + ) as String); @override _i2.ValueNotifier get initialized => (super.noSuchMethod( Invocation.getter(#initialized), @@ -297,11 +302,6 @@ class MockExplorerService extends _i1.Mock implements _i13.ExplorerService { returnValueForMissingStub: null, ); @override - String get projectId => (super.noSuchMethod( - Invocation.getter(#projectId), - returnValue: '', - ) as String); - @override _i2.ValueNotifier get totalListings => (super.noSuchMethod( Invocation.getter(#totalListings), returnValue: _FakeValueNotifier_0( @@ -377,8 +377,8 @@ class MockExplorerService extends _i1.Mock implements _i13.ExplorerService { returnValueForMissingStub: null, ); @override - String get recentWalletId => (super.noSuchMethod( - Invocation.getter(#recentWalletId), + String get searchValue => (super.noSuchMethod( + Invocation.getter(#searchValue), returnValue: '', ) as String); @override @@ -387,11 +387,6 @@ class MockExplorerService extends _i1.Mock implements _i13.ExplorerService { returnValue: false, ) as bool); @override - String get searchValue => (super.noSuchMethod( - Invocation.getter(#searchValue), - returnValue: '', - ) as String); - @override _i15.Future init() => (super.noSuchMethod( Invocation.method( #init, @@ -410,11 +405,11 @@ class MockExplorerService extends _i1.Mock implements _i13.ExplorerService { returnValueForMissingStub: _i15.Future.value(), ) as _i15.Future); @override - _i15.Future updateRecentPosition(String? recentId) => + _i15.Future storeConnectedWalletData(_i14.W3MWalletInfo? walletInfo) => (super.noSuchMethod( Invocation.method( - #updateRecentPosition, - [recentId], + #storeConnectedWalletData, + [walletInfo], ), returnValue: _i15.Future.value(), returnValueForMissingStub: _i15.Future.value(),