From 938d1cb9aa76b3961ad23b3a7726c50c61f32a89 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Wed, 7 Aug 2024 14:30:17 +0200 Subject: [PATCH 1/8] Support EIP55 addresses and fixes on the sample wallet for wc certification --- example/wallet/ios/Podfile.lock | 7 + .../bottom_sheet/bottom_sheet_listener.dart | 7 +- .../lib/dependencies/deep_link_handler.dart | 28 +- .../dependencies/key_service/chain_key.dart | 29 +- .../key_service/i_key_service.dart | 10 +- .../dependencies/key_service/key_service.dart | 131 +-- .../lib/dependencies/web3wallet_service.dart | 71 +- example/wallet/lib/pages/settings_page.dart | 781 +++++++++++++++--- example/wallet/lib/utils/dart_defines.dart | 17 +- example/wallet/lib/widgets/custom_button.dart | 2 +- .../wc_request_widget.dart | 71 +- .../wc_session_auth_request_widget.dart | 82 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + example/wallet/pubspec.yaml | 2 +- .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + lib/apis/core/connectivity/connectivity.dart | 8 + .../connectivity/connectivity_models.dart | 9 + .../core/connectivity/i_connectivity.dart | 6 + lib/apis/sign_api/sign_engine.dart | 6 +- pubspec.yaml | 1 + test/shared/shared_test_utils.mocks.dart | 2 +- 22 files changed, 939 insertions(+), 337 deletions(-) create mode 100644 lib/apis/core/connectivity/connectivity.dart create mode 100644 lib/apis/core/connectivity/connectivity_models.dart create mode 100644 lib/apis/core/connectivity/i_connectivity.dart diff --git a/example/wallet/ios/Podfile.lock b/example/wallet/ios/Podfile.lock index 43430323..8cc5efd9 100644 --- a/example/wallet/ios/Podfile.lock +++ b/example/wallet/ios/Podfile.lock @@ -1,4 +1,7 @@ PODS: + - connectivity_plus (0.0.1): + - Flutter + - FlutterMacOS - Flutter (1.0.0) - MTBBarcodeScanner (5.0.11) - package_info_plus (0.4.5): @@ -15,6 +18,7 @@ PODS: - Flutter DEPENDENCIES: + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) - Flutter (from `Flutter`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - qr_bar_code_scanner_dialog (from `.symlinks/plugins/qr_bar_code_scanner_dialog/ios`) @@ -27,6 +31,8 @@ SPEC REPOS: - MTBBarcodeScanner EXTERNAL SOURCES: + connectivity_plus: + :path: ".symlinks/plugins/connectivity_plus/darwin" Flutter: :path: Flutter package_info_plus: @@ -41,6 +47,7 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: + connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c diff --git a/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart b/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart index cac0c2e0..75386db0 100644 --- a/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart +++ b/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart @@ -45,7 +45,12 @@ class BottomSheetListenerState extends State { builder: (context) { if (item.closeAfter > 0) { Future.delayed(Duration(seconds: item.closeAfter), () { - Navigator.pop(context); + try { + if (!mounted) return; + Navigator.pop(context); + } catch (e) { + debugPrint('[$runtimeType] close $e'); + } }); } return Container( diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index beb9d9af..b415b6bd 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -10,12 +10,18 @@ import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; class DeepLinkHandler { // - static final waiting = ValueNotifier(false); + static const _methodChannel = MethodChannel( + 'com.walletconnect.flutterwallet/methods', + ); + static const _eventChannel = EventChannel( + 'com.walletconnect.flutterwallet/events', + ); + // static final _linksController = StreamController.broadcast(); - static const _methodChannel = - MethodChannel('com.walletconnect.flutterwallet/methods'); - static const _eventChannel = - EventChannel('com.walletconnect.flutterwallet/events'); + static Stream get onLink => _linksController.stream; + // + static final waiting = ValueNotifier(false); + // static void initListener() { if (kIsWeb) return; @@ -33,12 +39,10 @@ class DeepLinkHandler { onError: _onError, ); } catch (e) { - debugPrint('[WALLET] [DeepLinkHandler] checkInitialLink $e'); + debugPrint('[SampleWallet] [DeepLinkHandler] checkInitialLink $e'); } } - static Stream get onLink => _linksController.stream; - static void goTo( String scheme, { int delay = 100, @@ -47,15 +51,13 @@ class DeepLinkHandler { bool success = true, }) async { waiting.value = false; - if (kIsWeb) return; - if (scheme.isEmpty) return; await Future.delayed(Duration(milliseconds: delay)); - debugPrint('[WALLET] [DeepLinkHandler] redirecting to $scheme'); + debugPrint('[SampleWallet] [DeepLinkHandler] redirecting to $scheme'); try { await launchUrlString(scheme, mode: LaunchMode.externalApplication); } catch (e) { debugPrint( - '[WALLET] [DeepLinkHandler] error re-opening dapp ($scheme). $e'); + '[SampleWallet] [DeepLinkHandler] error re-opening dapp ($scheme). $e'); _goBackModal( title: modalTitle, message: modalMessage, @@ -79,7 +81,7 @@ class DeepLinkHandler { static void _onError(Object error) { waiting.value = false; - debugPrint('[WALLET] [DeepLinkHandler] _onError $error'); + debugPrint('[SampleWallet] [DeepLinkHandler] _onError $error'); } static void _goBackModal({ diff --git a/example/wallet/lib/dependencies/key_service/chain_key.dart b/example/wallet/lib/dependencies/key_service/chain_key.dart index 8db7da01..1c64d9d5 100644 --- a/example/wallet/lib/dependencies/key_service/chain_key.dart +++ b/example/wallet/lib/dependencies/key_service/chain_key.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + class ChainKey { final List chains; final String privateKey; @@ -11,8 +13,29 @@ class ChainKey { required this.address, }); - @override - String toString() { - return 'ChainKey(chains: $chains, privateKey: $privateKey, publicKey: $publicKey, address: $address)'; + String get namespace { + if (chains.isNotEmpty) { + return chains.first.split(':').first; + } + return ''; } + + Map toJson() => { + 'chains': chains, + 'privateKey': privateKey, + 'publicKey': privateKey, + 'address': address, + }; + + factory ChainKey.fromJson(Map json) { + return ChainKey( + chains: (json['chains'] as List).map((e) => '$e').toList(), + privateKey: json['privateKey'], + publicKey: json['publicKey'], + address: json['address'], + ); + } + + @override + String toString() => jsonEncode(toJson()); } diff --git a/example/wallet/lib/dependencies/key_service/i_key_service.dart b/example/wallet/lib/dependencies/key_service/i_key_service.dart index aa3a122b..21d813d2 100644 --- a/example/wallet/lib/dependencies/key_service/i_key_service.dart +++ b/example/wallet/lib/dependencies/key_service/i_key_service.dart @@ -2,7 +2,7 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/chain_k abstract class IKeyService { /// Returns a list of all the keys. - Future> setKeys(); + Future> loadKeys(); /// Returns a list of all the chain ids. List getChains(); @@ -10,16 +10,14 @@ abstract class IKeyService { /// Returns a list of all the keys for a given chain id. /// If the chain is not found, returns an empty list. /// - [chain]: The chain to get the keys for. - List getKeysForChain(String chain); + List getKeysForChain(String value); /// Returns a list of all the accounts in namespace:chainId:address format. List getAllAccounts(); - Future createNewWallet(); + Future createAddressFromSeed(); Future loadDefaultWallet(); - Future restoreWallet({required String mnemonic}); - - Future deleteWallet(); + Future restoreWalletFromSeed({required String mnemonic}); } diff --git a/example/wallet/lib/dependencies/key_service/key_service.dart b/example/wallet/lib/dependencies/key_service/key_service.dart index 1a4e0ab0..91427eb5 100644 --- a/example/wallet/lib/dependencies/key_service/key_service.dart +++ b/example/wallet/lib/dependencies/key_service/key_service.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:convert/convert.dart'; import 'package:flutter/foundation.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_models.dart'; @@ -12,48 +15,49 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/bip32/bip32_base.da import 'package:walletconnect_flutter_v2_wallet/utils/dart_defines.dart'; class KeyService extends IKeyService { - final List keys = []; + List _keys = []; @override - Future> setKeys() async { - // WARNING: SharedPreferences is not the best way to store your keys! + Future> loadKeys() async { + // ⚠️ WARNING: SharedPreferences is not the best way to store your keys! This is just for example purposes! final prefs = await SharedPreferences.getInstance(); - final privateKey = prefs.getString('privateKey') ?? ''; - if (privateKey.isEmpty) { - return []; + try { + final savedKeys = prefs.getStringList('w3w_chain_keys')!; + final chainKeys = savedKeys.map((e) => ChainKey.fromJson(jsonDecode(e))); + _keys = List.from(chainKeys.toList()); + // + final extraKeys = await _extraChainKeys(); + _keys.addAll(extraKeys); + } catch (e, s) { + debugPrint('[$runtimeType] loadKeys() error: $e'); + debugPrint(s.toString()); } - final publicKey = prefs.getString('publicKey') ?? ''; - - final keyPair = CryptoKeyPair(privateKey, publicKey); - final eip155KeyPair = _eip155KeyPair(keyPair); - keys - ..clear() - ..add(eip155KeyPair); - - final extraKeys = await _extraKeyPairs(); - keys.addAll(extraKeys); - return keys; + log('[$runtimeType] _keys $_keys'); + return _keys; } @override List getChains() { final List chainIds = []; - for (final ChainKey key in keys) { + for (final ChainKey key in _keys) { chainIds.addAll(key.chains); } return chainIds; } @override - List getKeysForChain(String chain) { - return keys.where((e) => e.chains.contains(chain)).toList(); + List getKeysForChain(String value) { + if (value.contains(':')) { + return _keys.where((e) => e.chains.contains(value)).toList(); + } + return _keys.where((e) => e.namespace == value).toList(); } @override List getAllAccounts() { final List accounts = []; - for (final ChainKey key in keys) { + for (final ChainKey key in _keys) { for (final String chain in key.chains) { accounts.add('$chain:${key.address}'); } @@ -64,39 +68,58 @@ class KeyService extends IKeyService { // ** bip39/bip32 - EIP155 ** @override - Future createNewWallet() async { - final mnemonic = bip39.generateMnemonic(); - await restoreWallet(mnemonic: mnemonic); + Future loadDefaultWallet() async { + const mnemonic = + 'spoil video deputy round immense setup wasp secret maze slight bag what'; + await restoreWalletFromSeed(mnemonic: mnemonic); } @override - Future restoreWallet({required String mnemonic}) async { - final keyPair = _keyPairFromMnemonic(mnemonic); - - // WARNING: SharedPreferences is not the best way to store your keys! + Future createAddressFromSeed() async { final prefs = await SharedPreferences.getInstance(); - await prefs.setString('privateKey', keyPair.privateKey); - await prefs.setString('publicKey', keyPair.publicKey); - await prefs.setString('mnemonic', mnemonic); + final mnemonic = prefs.getString('w3w_mnemonic')!; + + final chainKeys = getKeysForChain('eip155'); + final index = chainKeys.length; + + final keyPair = _keyPairFromMnemonic(mnemonic, index: index); + final chainKey = _eip155ChainKey(keyPair); - await setKeys(); + _keys.add(chainKey); + + await _saveKeys(); + + // final mnemonic = bip39.generateMnemonic(); + // await restoreWallet(mnemonic: mnemonic); } @override - Future loadDefaultWallet() async { - const mnemonic = - 'spoil video deputy round immense setup wasp secret maze slight bag what'; - await restoreWallet(mnemonic: mnemonic); + Future restoreWalletFromSeed({required String mnemonic}) async { + // ⚠️ WARNING: SharedPreferences is not the best way to store your keys! This is just for example purposes! + final prefs = await SharedPreferences.getInstance(); + await prefs.remove('w3w_chain_keys'); + // await prefs.remove('w3w_mnemonic'); + await prefs.setString('w3w_mnemonic', mnemonic); + + final keyPair = _keyPairFromMnemonic(mnemonic); + final chainKey = _eip155ChainKey(keyPair); + + _keys = List.from([chainKey]); + + await _saveKeys(); } - @override - Future deleteWallet() async { + Future _saveKeys() async { final prefs = await SharedPreferences.getInstance(); - await prefs.clear(); - keys.clear(); + // Store only eip155 keys + final chainKeys = _keys + .where((k) => k.namespace == 'eip155') + .map((e) => jsonEncode(e.toJson())) + .toList(); + await prefs.setStringList('w3w_chain_keys', chainKeys); } - CryptoKeyPair _keyPairFromMnemonic(String mnemonic) { + CryptoKeyPair _keyPairFromMnemonic(String mnemonic, {int index = 0}) { final isValidMnemonic = bip39.validateMnemonic(mnemonic); if (!isValidMnemonic) { throw 'Invalid mnemonic'; @@ -105,13 +128,13 @@ class KeyService extends IKeyService { final seed = bip39.mnemonicToSeed(mnemonic); final root = bip32.BIP32.fromSeed(seed); - final firstChild = root.derivePath("m/44'/60'/0'/0/0"); - final private = hex.encode(firstChild.privateKey as List); - final public = hex.encode(firstChild.publicKey); + final child = root.derivePath("m/44'/60'/0'/0/$index"); + final private = hex.encode(child.privateKey as List); + final public = hex.encode(child.publicKey); return CryptoKeyPair(private, public); } - ChainKey _eip155KeyPair(CryptoKeyPair keyPair) { + ChainKey _eip155ChainKey(CryptoKeyPair keyPair) { final private = EthPrivateKey.fromHex(keyPair.privateKey); final address = private.address.hex; final evmChainKey = ChainKey( @@ -126,15 +149,11 @@ class KeyService extends IKeyService { // ** extra derivations ** - Future> _extraKeyPairs() async { + Future> _extraChainKeys() async { // HARDCODED VALUES - final kadenaChainKey = _kadenaKeyPair(); - debugPrint('[SampleWallet] kadenaChainKey ${kadenaChainKey.toString()}'); - final polkadotChainKey = _polkadotKeyPair(); - debugPrint( - '[SampleWallet] polkadotChainKey ${polkadotChainKey.toString()}'); - final solanaChainKeys = _solanaKeyPair(); - debugPrint('[SampleWallet] solanaChainKey $solanaChainKeys'); + final kadenaChainKey = _kadenaChainKey(); + final polkadotChainKey = _polkadotChainKey(); + final solanaChainKeys = _solanaChainKey(); // return [ kadenaChainKey, @@ -143,7 +162,7 @@ class KeyService extends IKeyService { ]; } - ChainKey _kadenaKeyPair() { + ChainKey _kadenaChainKey() { return ChainKey( chains: ChainData.kadenaChains.map((e) => e.chainId).toList(), privateKey: DartDefines.kadenaSecretKey, @@ -152,7 +171,7 @@ class KeyService extends IKeyService { ); } - ChainKey _polkadotKeyPair() { + ChainKey _polkadotChainKey() { return ChainKey( chains: ChainData.polkadotChains.map((e) => e.chainId).toList(), privateKey: DartDefines.polkadotMnemonic, @@ -161,7 +180,7 @@ class KeyService extends IKeyService { ); } - ChainKey _solanaKeyPair() { + ChainKey _solanaChainKey() { return ChainKey( chains: ChainData.solanaChains.map((e) => e.chainId).toList(), privateKey: DartDefines.solanaSecretKey, diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index f5f459af..2c4ded78 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -66,13 +66,11 @@ class Web3WalletService extends IWeb3WalletService { _web3Wallet!.onAuthRequest.subscribe(_onAuthRequest); - await _web3Wallet!.init(); - // Setup our accounts - List chainKeys = await GetIt.I().setKeys(); + List chainKeys = await GetIt.I().loadKeys(); if (chainKeys.isEmpty) { await GetIt.I().loadDefaultWallet(); - chainKeys = await GetIt.I().setKeys(); + chainKeys = await GetIt.I().loadKeys(); } for (final chainKey in chainKeys) { for (final chainId in chainKey.chains) { @@ -99,6 +97,21 @@ class Web3WalletService extends IWeb3WalletService { Future init() async { // Await the initialization of the web3wallet await _web3Wallet!.init(); + + final sessions = _web3Wallet!.sessions.getAll(); + final chainKeys = GetIt.I().getKeysForChain('eip155'); + for (var session in sessions) { + try { + _web3Wallet!.emitSessionEvent( + topic: session.topic, + chainId: 'eip155:1', + event: SessionEventParams( + name: 'accountsChanged', + data: [chainKeys.first.address], + ), + ); + } catch (e) {} + } } void _logListener(LogEvent event) { @@ -131,26 +144,19 @@ class Web3WalletService extends IWeb3WalletService { @override Web3Wallet get web3wallet => _web3Wallet!; + List get _loaderMethods => [ + 'wc_sessionPropose', + 'wc_sessionRequest', + 'wc_sessionAuthenticate', + ]; + void _onRelayClientMessage(MessageEvent? event) async { if (event != null) { final jsonObject = await EthUtils.decodeMessageEvent(event); - debugPrint('[SampleWallet] _onRelayClientMessage $jsonObject'); + log('[SampleWallet] _onRelayClientMessage $jsonObject'); if (jsonObject is JsonRpcRequest) { - if (jsonObject.method == 'wc_sessionPropose' || - jsonObject.method == 'wc_sessionRequest') { - DeepLinkHandler.waiting.value = true; - } - } else { - final session = _web3Wallet!.sessions.get(event.topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - final isSuccess = jsonObject.result != null; - final title = isSuccess ? null : 'Error'; - final message = isSuccess ? null : jsonObject.error?.message ?? ''; - DeepLinkHandler.goTo( - scheme, - modalTitle: title, - modalMessage: message, - success: isSuccess, + DeepLinkHandler.waiting.value = _loaderMethods.contains( + jsonObject.method, ); } } @@ -159,19 +165,18 @@ class Web3WalletService extends IWeb3WalletService { void _onSessionProposal(SessionProposalEvent? args) async { if (args != null) { log('[SampleWallet] _onSessionProposal ${jsonEncode(args.params)}'); - final WCBottomSheetResult rs = - (await _bottomSheetHandler.queueBottomSheet( - widget: WCRequestWidget( - child: WCConnectionRequestWidget( - proposalData: args.params, - verifyContext: args.verifyContext, - metadata: args.params.proposer, - ), - ), - )) ?? - WCBottomSheetResult.reject; + final result = (await _bottomSheetHandler.queueBottomSheet( + widget: WCRequestWidget( + child: WCConnectionRequestWidget( + proposalData: args.params, + verifyContext: args.verifyContext, + metadata: args.params.proposer, + ), + ), + )) ?? + WCBottomSheetResult.reject; - if (rs != WCBottomSheetResult.reject) { + if (result != WCBottomSheetResult.reject) { // generatedNamespaces is constructed based on registered methods handlers // so if you want to handle requests using onSessionRequest event then you would need to manually add that method in the approved namespaces await _web3Wallet!.approveSession( @@ -240,7 +245,7 @@ class Web3WalletService extends IWeb3WalletService { void _onSessionConnect(SessionConnect? args) { if (args != null) { - log('[SampleWallet] _onSessionConnect ${jsonEncode(args.session)}'); + log('[SampleWallet] _onSessionConnect ${jsonEncode(args.session.toJson())}'); final scheme = args.session.peer.metadata.redirect?.native ?? ''; DeepLinkHandler.goTo(scheme); } diff --git a/example/wallet/lib/pages/settings_page.dart b/example/wallet/lib/pages/settings_page.dart index f6968ede..3414d80b 100644 --- a/example/wallet/lib/pages/settings_page.dart +++ b/example/wallet/lib/pages/settings_page.dart @@ -1,3 +1,4 @@ +import 'dart:math'; import 'dart:ui'; import 'package:fl_toast/fl_toast.dart'; @@ -13,8 +14,6 @@ import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/custom_button.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/recover_from_seed.dart'; -// import 'package:package_info_plus/package_info_plus.dart'; - class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); @@ -26,147 +25,523 @@ class _SettingsPageState extends State { @override Widget build(BuildContext context) { final keysService = GetIt.I(); - final chainKeys = keysService.getKeysForChain('eip155:1'); - final web3Wallet = GetIt.I().web3wallet; - return Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Padding( - padding: EdgeInsets.only(left: 8.0, bottom: 8.0), - child: Text( - 'Account', - style: TextStyle( - color: Colors.black, - fontSize: 16.0, - fontWeight: FontWeight.w500, - ), - ), - ), - _DataContainer( - title: 'CAIP-10', - data: 'eip155:1:${chainKeys.first.address}', - ), - const SizedBox(height: 12.0), - _DataContainer( - title: 'Public key', - data: chainKeys.first.publicKey, - ), - const SizedBox(height: 12.0), - _DataContainer( - title: 'Private key', - data: chainKeys.first.privateKey, - blurred: true, - ), - const SizedBox(height: 12.0), - FutureBuilder( - future: SharedPreferences.getInstance(), - builder: (context, snapshot) { - return _DataContainer( - title: 'Seed phrase', - data: snapshot.data?.getString('mnemonic') ?? '', - blurred: true, + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _EVMAccounts( + onCreateAddress: () async { + await keysService.createAddressFromSeed(); + await keysService.loadKeys(); + // ignore: use_build_context_synchronously + Navigator.of(context).pop(); + setState(() {}); + }, + onAccountChanged: (address) async { + final web3wallet = GetIt.I().web3wallet; + final sessions = web3wallet.sessions.getAll(); + for (var session in sessions) { + await web3wallet.emitSessionEvent( + topic: session.topic, + chainId: 'eip155:1', + event: SessionEventParams( + name: 'accountsChanged', + data: [address], + ), ); - }, - ), - const SizedBox(height: 20.0), - const Divider(height: 1.0), - const Padding( - padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: 20.0), - child: Text( - 'Device', - style: TextStyle( - color: Colors.black, - fontSize: 16.0, - fontWeight: FontWeight.w500, - ), - ), - ), - FutureBuilder( - future: web3Wallet.core.crypto.getClientId(), - builder: (context, snapshot) { - return _DataContainer( - title: 'Client ID', - data: snapshot.data ?? '', + } + setState(() {}); + }, + ), + // + const SizedBox(height: 20.0), + const Divider(height: 1.0), + _SolanaAccounts(), + const SizedBox(height: 20.0), + const Divider(height: 1.0), + _PolkadotAccounts(), + const SizedBox(height: 20.0), + const Divider(height: 1.0), + _KadenaAccounts(), + const SizedBox(height: 20.0), + const Divider(height: 1.0), + _DeviceData(), + const SizedBox(height: 20.0), + const Divider(height: 1.0), + _Buttons( + onRestoreFromSeed: () async { + final mnemonic = + await GetIt.I().queueBottomSheet( + widget: RecoverFromSeed(), + ); + if (mnemonic is String) { + await keysService.restoreWalletFromSeed( + mnemonic: mnemonic, ); - }, + await keysService.loadKeys(); + await showDialog( + // ignore: use_build_context_synchronously + context: context, + builder: (BuildContext context) { + return const AlertDialog( + content: Text('Wallet from seed restored'), + ); + }, + ); + setState(() {}); + } + }, + onRestoreDefault: () async { + await keysService.loadDefaultWallet(); + await keysService.loadKeys(); + await showDialog( + // ignore: use_build_context_synchronously + context: context, + builder: (BuildContext context) { + return const AlertDialog( + content: Text('Default wallet restored'), + ); + }, + ); + setState(() {}); + }, + ), + // + ], + ), + ), + ), + ], + ); + } +} + +class _EVMAccounts extends StatefulWidget { + final VoidCallback onCreateAddress; + final Function(String) onAccountChanged; + const _EVMAccounts({ + required this.onCreateAddress, + required this.onAccountChanged, + }); + + @override + State<_EVMAccounts> createState() => _EVMAccountsState(); +} + +class _EVMAccountsState extends State<_EVMAccounts> { + int _currentPage = 0; + late final PageController _pageController; + + @override + void initState() { + super.initState(); + _pageController = PageController(); + } + + @override + Widget build(BuildContext context) { + final keysService = GetIt.I(); + final chainKeys = keysService.getKeysForChain('eip155'); + debugPrint('[$runtimeType] chainKeys ${chainKeys.length}'); + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Row( + children: [ + const SizedBox.square(dimension: 8.0), + Expanded( + child: Text( + 'EVM Accounts (${_currentPage + 1}/${chainKeys.length})', + style: const TextStyle( + color: Colors.black, + fontSize: 16.0, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 12.0), - FutureBuilder( - future: PackageInfo.fromPlatform(), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const SizedBox.shrink(); - } - final v = snapshot.data!.version; - final b = snapshot.data!.buildNumber; - const f = String.fromEnvironment('FLUTTER_APP_FLAVOR'); - return _DataContainer( - title: 'App version', - data: '$v-$f ($b) - SDK v$packageVersion', + ), + ), + IconButton( + onPressed: () async { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Create new account'), + content: const Text( + 'This will create a new address out from the same seed phrase', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Cancel'), + ), + TextButton( + onPressed: widget.onCreateAddress, + child: const Text('Proceed'), + ), + ], ); }, + ); + }, + icon: const Icon(Icons.add_box_rounded), + padding: const EdgeInsets.all(0.0), + visualDensity: VisualDensity.compact, + ), + IconButton( + onPressed: (_currentPage == 0) + ? null + : () { + _pageController.jumpToPage(_currentPage - 1); + }, + icon: const Icon(Icons.arrow_back), + padding: const EdgeInsets.all(0.0), + visualDensity: VisualDensity.compact, + ), + IconButton( + onPressed: (_currentPage == chainKeys.length - 1) + ? null + : () { + _pageController.jumpToPage(_currentPage + 1); + }, + icon: const Icon(Icons.arrow_forward), + padding: const EdgeInsets.all(0.0), + visualDensity: VisualDensity.compact, + ), + ], + ), + ), + SizedBox( + height: 300.0, + child: PageView.builder( + controller: _pageController, + physics: const NeverScrollableScrollPhysics(), + onPageChanged: (value) async { + setState(() => _currentPage = value); + final chainKey = chainKeys[_currentPage]; + widget.onAccountChanged(chainKey.address); + }, + itemBuilder: (BuildContext context, int index) { + final chainKey = chainKeys[index]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + children: [ + const SizedBox(height: 12.0), + _DataContainer( + title: 'CAIP-10', + data: 'eip155:1:${chainKey.address}', + height: 84.0, + ), + const SizedBox(height: 12.0), + _DataContainer( + title: 'Public key', + data: chainKey.publicKey, + height: 84.0, + ), + const SizedBox(height: 12.0), + _DataContainer( + title: 'Private key', + data: chainKey.privateKey, + blurred: true, + height: 84.0, + ), + const SizedBox(height: 12.0), + ], + ), + ); + }, + itemCount: chainKeys.length, + ), + ), + SizedBox( + height: 16.0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + // ignore: sdk_version_since + children: chainKeys.indexed + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 2.0), + child: CircleAvatar( + radius: e.$1 == _currentPage ? 4.0 : 3.0, + backgroundColor: + e.$1 == _currentPage ? Colors.black : Colors.black38, + ), ), - const SizedBox(height: 20.0), - const Divider(height: 1.0), - const SizedBox(height: 20.0), - Row( - children: [ - CustomButton( - onTap: () async { - final mnemonic = await GetIt.I() - .queueBottomSheet( - widget: RecoverFromSeed(), - ); - if (mnemonic is String) { - await keysService.restoreWallet(mnemonic: mnemonic); - setState(() {}); - } - }, - child: const Center( - child: Text( - 'Import account', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], + ) + .toList(), + ), + ), + const SizedBox(height: 20.0), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: FutureBuilder( + future: SharedPreferences.getInstance(), + builder: (context, snapshot) { + return _DataContainer( + title: 'Seed phrase', + data: snapshot.data?.getString('w3w_mnemonic') ?? '', + blurred: true, + ); + }, + ), + ), + ], + ); + } +} + +class _SolanaAccounts extends StatelessWidget { + @override + Widget build(BuildContext context) { + final keysService = GetIt.I(); + final chainKeys = keysService.getKeysForChain('solana'); + if (chainKeys.isEmpty) return const SizedBox.shrink(); + return Column( + children: [ + const Padding( + padding: EdgeInsets.all(12.0), + child: Row( + children: [ + SizedBox.square(dimension: 8.0), + Expanded( + child: Text( + 'Solana Account', + style: TextStyle( + color: Colors.black, + fontSize: 16.0, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 12.0), - Row( - children: [ - CustomButton( - type: CustomButtonType.invalid, - onTap: () async { - await keysService.loadDefaultWallet(); - setState(() {}); - }, - child: const Center( - child: Text( - 'Restore default', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + children: [ + _DataContainer( + title: 'Address', + data: chainKeys.first.address, + ), + const SizedBox(height: 12.0), + _DataContainer( + title: 'Secret key', + data: chainKeys.first.privateKey, + blurred: true, + ), + ], + ), + ), + ], + ); + } +} + +class _PolkadotAccounts extends StatelessWidget { + @override + Widget build(BuildContext context) { + final keysService = GetIt.I(); + final chainKeys = keysService.getKeysForChain('polkadot'); + if (chainKeys.isEmpty) return const SizedBox.shrink(); + return Column( + children: [ + const Padding( + padding: EdgeInsets.all(12.0), + child: Row( + children: [ + SizedBox.square(dimension: 8.0), + Expanded( + child: Text( + 'Polkadot Account', + style: TextStyle( + color: Colors.black, + fontSize: 16.0, + fontWeight: FontWeight.w500, ), - const SizedBox(height: 12.0), - ], + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + children: [ + _DataContainer( + title: 'Address', + data: chainKeys.first.address, + ), + const SizedBox(height: 12.0), + _DataContainer( + title: 'Mnemonic', + data: chainKeys.first.privateKey, + blurred: true, + ), + ], + ), + ), + ], + ); + } +} + +class _KadenaAccounts extends StatelessWidget { + @override + Widget build(BuildContext context) { + final keysService = GetIt.I(); + final chainKeys = keysService.getKeysForChain('kadena'); + if (chainKeys.isEmpty) return const SizedBox.shrink(); + return Column( + children: [ + const Padding( + padding: EdgeInsets.all(12.0), + child: Row( + children: [ + SizedBox.square(dimension: 8.0), + Expanded( + child: Text( + 'Kadena Account', + style: TextStyle( + color: Colors.black, + fontSize: 16.0, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + children: [ + _DataContainer( + title: 'Address', + data: chainKeys.first.address, + ), + const SizedBox(height: 12.0), + _DataContainer( + title: 'Secret key', + data: chainKeys.first.privateKey, + blurred: true, + ), + ], + ), + ) + ], + ); + } +} + +class _DeviceData extends StatelessWidget { + @override + Widget build(BuildContext context) { + final web3Wallet = GetIt.I().web3wallet; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Padding( + padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: 12.0), + child: Text( + 'Device', + style: TextStyle( + color: Colors.black, + fontSize: 16.0, + fontWeight: FontWeight.w500, ), ), ), + FutureBuilder( + future: web3Wallet.core.crypto.getClientId(), + builder: (context, snapshot) { + return _DataContainer( + title: 'Client ID', + data: snapshot.data ?? '', + ); + }, + ), + const SizedBox(height: 12.0), + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const SizedBox.shrink(); + } + final v = snapshot.data!.version; + final b = snapshot.data!.buildNumber; + const f = String.fromEnvironment('FLUTTER_APP_FLAVOR'); + return _DataContainer( + title: 'App version', + data: '$v-$f ($b) - SDK v$packageVersion', + ); + }, + ), + ], + ), + ); + } +} + +class _Buttons extends StatelessWidget { + final VoidCallback onRestoreFromSeed; + final VoidCallback onRestoreDefault; + const _Buttons({ + required this.onRestoreFromSeed, + required this.onRestoreDefault, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + children: [ + const SizedBox(height: 8.0), + Row( + children: [ + CustomButton( + type: CustomButtonType.normal, + onTap: onRestoreFromSeed, + child: const Center( + child: Text( + 'Restore wallet from seed', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + const SizedBox(height: 12.0), + Row( + children: [ + CustomButton( + type: CustomButtonType.invalid, + onTap: onRestoreDefault, + child: const Center( + child: Text( + 'Restore default wallet', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), ], ), ); @@ -178,10 +553,12 @@ class _DataContainer extends StatefulWidget { required this.title, required this.data, this.blurred = false, + this.height, }); final String title; final String data; final bool blurred; + final double? height; @override State<_DataContainer> createState() => __DataContainerState(); @@ -213,6 +590,7 @@ class __DataContainerState extends State<_DataContainer> { blurred = widget.blurred; }), child: Container( + height: widget.height, decoration: BoxDecoration( color: StyleConstants.lightGray, borderRadius: BorderRadius.circular( @@ -255,3 +633,142 @@ class __DataContainerState extends State<_DataContainer> { ); } } + +class SizeReportingWidget extends StatefulWidget { + final Widget child; + final ValueChanged onSizeChange; + + const SizeReportingWidget({ + Key? key, + required this.child, + required this.onSizeChange, + }) : super(key: key); + + @override + State createState() => _SizeReportingWidgetState(); +} + +class _SizeReportingWidgetState extends State { + Size? _oldSize; + + @override + Widget build(BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) => _notifySize()); + return widget.child; + } + + void _notifySize() { + if (!mounted) { + return; + } + final size = context.size; + if (_oldSize != size && size != null) { + _oldSize = size; + widget.onSizeChange(size); + } + } +} + +class ExpandablePageView extends StatefulWidget { + final List children; + final PageController? controller; + final Function(int)? onPageChanged; + + const ExpandablePageView({ + Key? key, + required this.children, + this.controller, + this.onPageChanged, + }) : super(key: key); + + @override + State createState() => _ExpandablePageViewState(); +} + +class _ExpandablePageViewState extends State + with TickerProviderStateMixin { + late PageController _pageController; + late List _heights; + int _currentPage = 0; + + double get _currentHeight => _heights[_currentPage]; + + @override + void initState() { + super.initState(); + _heights = widget.children.map((e) => 0.0).toList(); + _pageController = widget.controller ?? PageController() + ..addListener(() { + final newPage = _pageController.page?.round() ?? 0; + if (_currentPage != newPage) { + setState(() => _currentPage = newPage); + } + }); + } + + @override + void didUpdateWidget(covariant ExpandablePageView oldWidget) { + super.didUpdateWidget(oldWidget); + final diff = widget.children.length - oldWidget.children.length; + if (diff > 0) { + for (var i = 0; i < diff; i++) { + final lastHeight = _heights.last; + _heights.add(lastHeight); + } + } + } + + @override + void dispose() { + _pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + debugPrint('${_heights[0]} $_currentHeight'); + return TweenAnimationBuilder( + curve: Curves.easeInOutCubic, + duration: const Duration(milliseconds: 50), + tween: Tween( + begin: max(_heights[0], 200.0), + end: max(_currentHeight, 200.0), + ), + builder: (context, value, child) => SizedBox( + height: value, + child: child, + ), + child: PageView( + physics: const NeverScrollableScrollPhysics(), + controller: _pageController, + onPageChanged: widget.onPageChanged, + children: _sizeReportingChildren + .asMap() // + .map((index, child) => MapEntry(index, child)) + .values + .toList(), + ), + ); + } + + List get _sizeReportingChildren => widget.children + .asMap() // + .map( + (index, child) => MapEntry( + index, + OverflowBox( + //needed, so that parent won't impose its constraints on the children, thus skewing the measurement results. + minHeight: 0, + maxHeight: double.infinity, + alignment: Alignment.topCenter, + child: SizeReportingWidget( + onSizeChange: (size) => + setState(() => _heights[index] = size.height), + child: Align(child: child), + ), + ), + ), + ) + .values + .toList(); +} diff --git a/example/wallet/lib/utils/dart_defines.dart b/example/wallet/lib/utils/dart_defines.dart index 6d157237..6c5964e8 100644 --- a/example/wallet/lib/utils/dart_defines.dart +++ b/example/wallet/lib/utils/dart_defines.dart @@ -2,17 +2,8 @@ class DartDefines { static const String projectId = String.fromEnvironment( 'PROJECT_ID', ); - // - static const eip155PrivateKey = String.fromEnvironment( - 'EIP155_PRIVATE_KEY', - defaultValue: - '5754463bdfbd6e081ca1d6df965927feb1066a0df86d010ac4125eb4bc4c0082', - ); - static const eip155Address = String.fromEnvironment( - 'EIP155_ADDRESS', - defaultValue: '0xf3c95b1a8cabf3d5151912377aeadd84aa41c27c', - ); - // + // HARDCODED TEST KEYS + // KADENA static const kadenaSecretKey = String.fromEnvironment( 'KADENA_SECRET_KEY', defaultValue: @@ -23,7 +14,7 @@ class DartDefines { defaultValue: '3a527a1af7713cde04a4ce8b6c95b3806b7582f2423d740fc16eaa5b7a235d42', ); - // + // SOLANA static const solanaSecretKey = String.fromEnvironment( 'SOLANA_SECRET_KEY', defaultValue: @@ -33,7 +24,7 @@ class DartDefines { 'SOLANA_ADDRESS', defaultValue: 'EbdEmCpKGvEwfwV4ACmVYHFRkwvXdogJhMZeEekDFVVJ', ); - // + // POLKADOT static const polkadotMnemonic = String.fromEnvironment( 'POLKADOT_MNEMONIC', defaultValue: diff --git a/example/wallet/lib/widgets/custom_button.dart b/example/wallet/lib/widgets/custom_button.dart index f8c79f8f..a49d7111 100644 --- a/example/wallet/lib/widgets/custom_button.dart +++ b/example/wallet/lib/widgets/custom_button.dart @@ -24,7 +24,7 @@ class CustomButton extends StatelessWidget { case CustomButtonType.invalid: return StyleConstants.errorColor; default: - return Colors.blue[200]!; + return Colors.black54; } } diff --git a/example/wallet/lib/widgets/wc_request_widget.dart/wc_request_widget.dart b/example/wallet/lib/widgets/wc_request_widget.dart/wc_request_widget.dart index adbdc543..09b5aee3 100644 --- a/example/wallet/lib/widgets/wc_request_widget.dart/wc_request_widget.dart +++ b/example/wallet/lib/widgets/wc_request_widget.dart/wc_request_widget.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/bottom_sheet/i_bottom_sheet_service.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; @@ -18,44 +19,44 @@ class WCRequestWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - child, - const SizedBox( - height: StyleConstants.linear16, + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: child, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CustomButton( - onTap: onReject ?? - () => Navigator.of(context).pop(WCBottomSheetResult.reject), - type: CustomButtonType.invalid, - child: const Text( - StringConstants.reject, - style: StyleConstants.buttonText, - textAlign: TextAlign.center, - ), + ), + const SizedBox(height: StyleConstants.linear16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + onTap: onReject ?? + () => Navigator.of(context).pop(WCBottomSheetResult.reject), + type: CustomButtonType.invalid, + child: const Text( + StringConstants.reject, + style: StyleConstants.buttonText, + textAlign: TextAlign.center, ), - const SizedBox( - width: StyleConstants.linear16, + ), + const SizedBox( + width: StyleConstants.linear16, + ), + CustomButton( + onTap: onAccept ?? + () => Navigator.of(context).pop(WCBottomSheetResult.one), + type: CustomButtonType.valid, + child: const Text( + StringConstants.approve, + style: StyleConstants.buttonText, + textAlign: TextAlign.center, ), - CustomButton( - onTap: onAccept ?? - () => Navigator.of(context).pop(WCBottomSheetResult.one), - type: CustomButtonType.valid, - child: const Text( - StringConstants.approve, - style: StyleConstants.buttonText, - textAlign: TextAlign.center, - ), - ), - ], - ), - ], - ), + ), + ], + ), + ], ); } } diff --git a/example/wallet/lib/widgets/wc_request_widget.dart/wc_session_auth_request_widget.dart b/example/wallet/lib/widgets/wc_request_widget.dart/wc_session_auth_request_widget.dart index 6cd4cbf8..c857e03f 100644 --- a/example/wallet/lib/widgets/wc_request_widget.dart/wc_session_auth_request_widget.dart +++ b/example/wallet/lib/widgets/wc_request_widget.dart/wc_session_auth_request_widget.dart @@ -13,49 +13,51 @@ class WCSessionAuthRequestWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - child, - const SizedBox(height: StyleConstants.linear16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CustomButton( - onTap: () => - Navigator.of(context).pop(WCBottomSheetResult.reject), - type: CustomButtonType.invalid, - child: const Text( - 'Cancel', - style: StyleConstants.buttonText, - textAlign: TextAlign.center, - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: SingleChildScrollView( + child: child, + ), + ), + const SizedBox(height: StyleConstants.linear16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + onTap: () => + Navigator.of(context).pop(WCBottomSheetResult.reject), + type: CustomButtonType.invalid, + child: const Text( + 'Cancel', + style: StyleConstants.buttonText, + textAlign: TextAlign.center, ), - const SizedBox(width: StyleConstants.linear8), - CustomButton( - onTap: () => Navigator.of(context).pop(WCBottomSheetResult.one), - type: CustomButtonType.normal, - child: const Text( - 'Sign One', - style: StyleConstants.buttonText, - textAlign: TextAlign.center, - ), + ), + const SizedBox(width: StyleConstants.linear8), + CustomButton( + onTap: () => Navigator.of(context).pop(WCBottomSheetResult.one), + type: CustomButtonType.normal, + child: const Text( + 'Sign One', + style: StyleConstants.buttonText, + textAlign: TextAlign.center, ), - const SizedBox(width: StyleConstants.linear8), - CustomButton( - onTap: () => Navigator.of(context).pop(WCBottomSheetResult.all), - type: CustomButtonType.valid, - child: const Text( - 'Sign All', - style: StyleConstants.buttonText, - textAlign: TextAlign.center, - ), + ), + const SizedBox(width: StyleConstants.linear8), + CustomButton( + onTap: () => Navigator.of(context).pop(WCBottomSheetResult.all), + type: CustomButtonType.valid, + child: const Text( + 'Sign All', + style: StyleConstants.buttonText, + textAlign: TextAlign.center, ), - ], - ), - ], - ), + ), + ], + ), + ], ); } } diff --git a/example/wallet/macos/Flutter/GeneratedPluginRegistrant.swift b/example/wallet/macos/Flutter/GeneratedPluginRegistrant.swift index cc667fc0..a4e08b1e 100644 --- a/example/wallet/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/wallet/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,11 +5,13 @@ import FlutterMacOS import Foundation +import connectivity_plus import package_info_plus import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/example/wallet/pubspec.yaml b/example/wallet/pubspec.yaml index b8fa856a..a0ba66ca 100644 --- a/example/wallet/pubspec.yaml +++ b/example/wallet/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ">=2.18.6 <3.0.0" + sdk: ">=2.19.0 <4.0.0" dependencies: flutter: diff --git a/example/wallet/windows/flutter/generated_plugin_registrant.cc b/example/wallet/windows/flutter/generated_plugin_registrant.cc index 4f788487..5777988d 100644 --- a/example/wallet/windows/flutter/generated_plugin_registrant.cc +++ b/example/wallet/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,12 @@ #include "generated_plugin_registrant.h" +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + ConnectivityPlusWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/example/wallet/windows/flutter/generated_plugins.cmake b/example/wallet/windows/flutter/generated_plugins.cmake index 88b22e5c..31032063 100644 --- a/example/wallet/windows/flutter/generated_plugins.cmake +++ b/example/wallet/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + connectivity_plus url_launcher_windows ) diff --git a/lib/apis/core/connectivity/connectivity.dart b/lib/apis/core/connectivity/connectivity.dart new file mode 100644 index 00000000..157e3772 --- /dev/null +++ b/lib/apis/core/connectivity/connectivity.dart @@ -0,0 +1,8 @@ +import 'package:walletconnect_flutter_v2/apis/core/connectivity/connectivity_models.dart'; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/i_connectivity.dart'; +import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; + +class Connectivity implements IConnectivity { + @override + Event onConnectivityChange = Event(); +} diff --git a/lib/apis/core/connectivity/connectivity_models.dart b/lib/apis/core/connectivity/connectivity_models.dart new file mode 100644 index 00000000..a8285097 --- /dev/null +++ b/lib/apis/core/connectivity/connectivity_models.dart @@ -0,0 +1,9 @@ +import 'package:event/event.dart'; + +class ConnectivityEvent extends EventArgs { + final bool connected; + + ConnectivityEvent( + this.connected, + ); +} diff --git a/lib/apis/core/connectivity/i_connectivity.dart b/lib/apis/core/connectivity/i_connectivity.dart new file mode 100644 index 00000000..3907493b --- /dev/null +++ b/lib/apis/core/connectivity/i_connectivity.dart @@ -0,0 +1,6 @@ +import 'package:event/event.dart'; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/connectivity_models.dart'; + +abstract class IConnectivity { + abstract final Event onConnectivityChange; +} diff --git a/lib/apis/sign_api/sign_engine.dart b/lib/apis/sign_api/sign_engine.dart index ac6e2910..49582fc5 100644 --- a/lib/apis/sign_api/sign_engine.dart +++ b/lib/apis/sign_api/sign_engine.dart @@ -1866,10 +1866,11 @@ class SignEngine implements ISignEngine { ); final walletAddress = AddressUtils.getDidAddress(payload.iss); + final ethAddress = EthereumAddress.fromHex(walletAddress); final chainId = AddressUtils.getDidChainId(payload.iss); final isValid = await AuthSignature.verifySignature( - walletAddress, + ethAddress.hexEip55, reconstructed, signature, chainId, @@ -1888,6 +1889,7 @@ class SignEngine implements ISignEngine { final header = '${cacaoPayload.domain} wants you to sign in with your Ethereum account:'; final walletAddress = AddressUtils.getDidAddress(iss); + final ethAddress = EthereumAddress.fromHex(walletAddress); if (cacaoPayload.aud.isEmpty) { throw WalletConnectError(code: -1, message: 'aud is required'); @@ -1924,7 +1926,7 @@ class SignEngine implements ISignEngine { final message = [ header, - walletAddress, + ethAddress.hexEip55, '', statement, '', diff --git a/pubspec.yaml b/pubspec.yaml index 0ab97857..c425da2d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: bs58: ^1.0.2 + connectivity_plus: ^6.0.4 convert: ^3.0.1 cryptography: ^2.0.5 ed25519_edwards: ^0.3.1 diff --git a/test/shared/shared_test_utils.mocks.dart b/test/shared/shared_test_utils.mocks.dart index f0475a40..ea3b4959 100644 --- a/test/shared/shared_test_utils.mocks.dart +++ b/test/shared/shared_test_utils.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.3 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in walletconnect_flutter_v2/test/shared/shared_test_utils.dart. // Do not manually edit this file. From 901d285f671b2ca20def562e92e7dcf61e2aac3c Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 8 Aug 2024 12:29:40 +0200 Subject: [PATCH 2/8] added connectivity enhancement --- example/dapp/lib/main.dart | 15 +- example/dapp/lib/widgets/chain_button.dart | 7 +- example/dapp/macos/Podfile | 2 +- example/dapp/macos/Podfile.lock | 24 +- example/dapp/pubspec.yaml | 2 +- .../lib/dependencies/chains/evm_service.dart | 134 ++++--- .../lib/dependencies/deep_link_handler.dart | 40 +-- .../lib/dependencies/web3wallet_service.dart | 50 ++- example/wallet/lib/main.dart | 24 +- example/wallet/macos/Podfile.lock | 12 +- .../macos/Runner/DebugProfile.entitlements | 2 + .../wallet/macos/Runner/Release.entitlements | 2 + example/wallet/pubspec.yaml | 5 +- lib/apis/core/connectivity/connectivity.dart | 43 ++- .../core/connectivity/i_connectivity.dart | 6 +- lib/apis/core/core.dart | 9 + lib/apis/core/i_core.dart | 2 + lib/apis/sign_api/sign_engine.dart | 15 +- pubspec.yaml | 2 +- test/shared/shared_test_utils.mocks.dart | 331 ++++++++++-------- 20 files changed, 459 insertions(+), 268 deletions(-) diff --git a/example/dapp/lib/main.dart b/example/dapp/lib/main.dart index 6e34f698..e0cf3315 100644 --- a/example/dapp/lib/main.dart +++ b/example/dapp/lib/main.dart @@ -210,6 +210,7 @@ class _MyHomePageState extends State { title: Text(_pageDatas[_selectedIndex].title), centerTitle: true, actions: [ + const Text('Relay '), CircleAvatar( radius: 6.0, backgroundColor: _web3App!.core.relayClient.isConnected @@ -219,14 +220,20 @@ class _MyHomePageState extends State { const SizedBox(width: 16.0), ], ), + body: Center( + child: Container( + constraints: BoxConstraints( + maxWidth: Constants.smallScreen.toDouble(), + ), + child: Row( + children: navRail, + ), + ), + ), bottomNavigationBar: MediaQuery.of(context).size.width < Constants.smallScreen ? _buildBottomNavBar() : null, - body: Row( - mainAxisSize: MainAxisSize.max, - children: navRail, - ), ); } diff --git a/example/dapp/lib/widgets/chain_button.dart b/example/dapp/lib/widgets/chain_button.dart index c98b277e..e6bc9717 100644 --- a/example/dapp/lib/widgets/chain_button.dart +++ b/example/dapp/lib/widgets/chain_button.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:walletconnect_flutter_v2_dapp/models/chain_metadata.dart'; import 'package:walletconnect_flutter_v2_dapp/utils/constants.dart'; @@ -17,7 +19,10 @@ class ChainButton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: (MediaQuery.of(context).size.width / 2) - 14.0, + width: (min(Constants.smallScreen - 78.0, + MediaQuery.of(context).size.width) / + 2) - + 14.0, height: StyleConstants.linear48, margin: const EdgeInsets.symmetric( vertical: StyleConstants.linear8, diff --git a/example/dapp/macos/Podfile b/example/dapp/macos/Podfile index dade8dfa..049abe29 100644 --- a/example/dapp/macos/Podfile +++ b/example/dapp/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.11' +platform :osx, '10.14' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/dapp/macos/Podfile.lock b/example/dapp/macos/Podfile.lock index 1bd72862..1f667557 100644 --- a/example/dapp/macos/Podfile.lock +++ b/example/dapp/macos/Podfile.lock @@ -1,23 +1,35 @@ PODS: - FlutterMacOS (1.0.0) + - package_info_plus (0.0.1): + - FlutterMacOS - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - url_launcher_macos (0.0.1): + - FlutterMacOS DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) EXTERNAL SOURCES: FlutterMacOS: :path: Flutter/ephemeral + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos SPEC CHECKSUMS: - FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 - shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 -PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.11.3 +COCOAPODS: 1.15.2 diff --git a/example/dapp/pubspec.yaml b/example/dapp/pubspec.yaml index 22b8077c..2567c40c 100644 --- a/example/dapp/pubspec.yaml +++ b/example/dapp/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: url_launcher: ^6.2.2 # intl: ^0.19.0 package_info_plus: ^7.0.0 - walletconnect_modal_flutter: ^2.1.19 + walletconnect_modal_flutter: ^2.1.20 # walletconnect_flutter_v2: # path: ../.. diff --git a/example/wallet/lib/dependencies/chains/evm_service.dart b/example/wallet/lib/dependencies/chains/evm_service.dart index acd9f230..49887e53 100644 --- a/example/wallet/lib/dependencies/chains/evm_service.dart +++ b/example/wallet/lib/dependencies/chains/evm_service.dart @@ -7,6 +7,7 @@ import 'package:get_it/get_it.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/bottom_sheet/i_bottom_sheet_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/chains/common.dart'; +import 'package:walletconnect_flutter_v2_wallet/dependencies/deep_link_handler.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/i_key_service.dart'; import 'package:walletconnect_flutter_v2_wallet/models/chain_metadata.dart'; @@ -140,12 +141,19 @@ class EVMService { ); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future ethSign(String topic, dynamic parameters) async { @@ -187,12 +195,19 @@ class EVMService { ); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future ethSignTypedData(String topic, dynamic parameters) async { @@ -229,12 +244,19 @@ class EVMService { ); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future ethSignTypedDataV4(String topic, dynamic parameters) async { @@ -271,12 +293,19 @@ class EVMService { ); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future ethSignTransaction(String topic, dynamic parameters) async { @@ -331,12 +360,19 @@ class EVMService { response = response.copyWith(error: transaction as JsonRpcError); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future ethSendTransaction(String topic, dynamic parameters) async { @@ -389,12 +425,19 @@ class EVMService { response = response.copyWith(error: transaction as JsonRpcError); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, response.result ?? response.error); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, response.result ?? response.error); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } Future switchChain(String topic, dynamic parameters) async { @@ -426,12 +469,19 @@ class EVMService { ); } - await _web3Wallet.respondSessionRequest( - topic: topic, - response: response, - ); - - CommonMethods.goBackToDapp(topic, true); + try { + await _web3Wallet.respondSessionRequest( + topic: topic, + response: response, + ); + CommonMethods.goBackToDapp(topic, true); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } // Future addChain(String topic, dynamic parameters) async { diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index b415b6bd..104fea61 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -58,7 +58,7 @@ class DeepLinkHandler { } catch (e) { debugPrint( '[SampleWallet] [DeepLinkHandler] error re-opening dapp ($scheme). $e'); - _goBackModal( + goBackModal( title: modalTitle, message: modalMessage, success: success, @@ -66,25 +66,7 @@ class DeepLinkHandler { } } - static void _onLink(Object? event) { - final decodedUri = Uri.parse(Uri.decodeFull(event.toString())); - if (decodedUri.toString().startsWith('wc:')) { - return; - } - final pairingUri = decodedUri.query.replaceFirst('uri=', ''); - if (!pairingUri.toString().startsWith('wc:')) { - return; - } - waiting.value = true; - _linksController.sink.add(pairingUri); - } - - static void _onError(Object error) { - waiting.value = false; - debugPrint('[SampleWallet] [DeepLinkHandler] _onError $error'); - } - - static void _goBackModal({ + static void goBackModal({ String? title, String? message, bool success = true, @@ -117,4 +99,22 @@ class DeepLinkHandler { ), ); } + + static void _onLink(Object? event) { + final decodedUri = Uri.parse(Uri.decodeFull(event.toString())); + if (decodedUri.toString().startsWith('wc:')) { + return; + } + final pairingUri = decodedUri.query.replaceFirst('uri=', ''); + if (!pairingUri.toString().startsWith('wc:')) { + return; + } + waiting.value = true; + _linksController.sink.add(pairingUri); + } + + static void _onError(Object error) { + waiting.value = false; + debugPrint('[SampleWallet] [DeepLinkHandler] _onError $error'); + } } diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index 2c4ded78..61e35295 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -110,7 +110,7 @@ class Web3WalletService extends IWeb3WalletService { data: [chainKeys.first.address], ), ); - } catch (e) {} + } catch (_) {} } } @@ -179,13 +179,21 @@ class Web3WalletService extends IWeb3WalletService { if (result != WCBottomSheetResult.reject) { // generatedNamespaces is constructed based on registered methods handlers // so if you want to handle requests using onSessionRequest event then you would need to manually add that method in the approved namespaces - await _web3Wallet!.approveSession( - id: args.id, - namespaces: NamespaceUtils.regenerateNamespacesWithChains( - args.params.generatedNamespaces!, - ), - sessionProperties: args.params.sessionProperties, - ); + try { + await _web3Wallet!.approveSession( + id: args.id, + namespaces: NamespaceUtils.regenerateNamespacesWithChains( + args.params.generatedNamespaces!, + ), + sessionProperties: args.params.sessionProperties, + ); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } else { final error = Errors.getSdkError(Errors.USER_REJECTED); await _web3Wallet!.rejectSession(id: args.id, reason: error); @@ -193,12 +201,11 @@ class Web3WalletService extends IWeb3WalletService { topic: args.params.pairingTopic, ); - // TODO this should be triggered on _onRelayClientMessage final scheme = args.params.proposer.metadata.redirect?.native ?? ''; DeepLinkHandler.goTo( scheme, modalTitle: 'Error', - modalMessage: 'User rejected', + modalMessage: error.message, success: false, ); } @@ -301,8 +308,7 @@ class Web3WalletService extends IWeb3WalletService { WCBottomSheetResult.reject; if (rs != WCBottomSheetResult.reject) { - const chain = 'eip155:1'; - final chainKeys = GetIt.I().getKeysForChain(chain); + final chainKeys = GetIt.I().getKeysForChain('eip155:1'); final privateKey = '0x${chainKeys[0].privateKey}'; final credentials = EthPrivateKey.fromHex(privateKey); // @@ -329,12 +335,20 @@ class Web3WalletService extends IWeb3WalletService { ); } // - final _ = await _web3Wallet!.approveSessionAuthenticate( - id: args.id, - auths: cacaos, - ); - final scheme = args.requester.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme); + try { + await _web3Wallet!.approveSessionAuthenticate( + id: args.id, + auths: cacaos, + ); + final scheme = args.requester.metadata.redirect?.native ?? ''; + DeepLinkHandler.goTo(scheme); + } on WalletConnectError catch (error) { + DeepLinkHandler.goBackModal( + title: 'Error', + message: error.message, + success: false, + ); + } } else { await _web3Wallet!.rejectSessionAuthenticate( id: args.id, diff --git a/example/wallet/lib/main.dart b/example/wallet/lib/main.dart index 39cff46d..bd4accaa 100644 --- a/example/wallet/lib/main.dart +++ b/example/wallet/lib/main.dart @@ -63,7 +63,7 @@ class _MyHomePageState extends State with GetItStateMixin { GetIt.I.registerSingleton(BottomSheetService()); GetIt.I.registerSingleton(KeyService()); - final IWeb3WalletService web3WalletService = Web3WalletService(); + final web3WalletService = Web3WalletService(); await web3WalletService.create(); GetIt.I.registerSingleton(web3WalletService); @@ -109,6 +109,15 @@ class _MyHomePageState extends State with GetItStateMixin { await web3WalletService.init(); + web3WalletService.web3wallet.core.relayClient.onRelayClientConnect + .subscribe( + _setState, + ); + web3WalletService.web3wallet.core.relayClient.onRelayClientDisconnect + .subscribe( + _setState, + ); + setState(() { _pageDatas = [ PageData( @@ -137,6 +146,8 @@ class _MyHomePageState extends State with GetItStateMixin { }); } + void _setState(dynamic args) => setState(() {}); + @override Widget build(BuildContext context) { if (_initializing) { @@ -159,12 +170,23 @@ class _MyHomePageState extends State with GetItStateMixin { ), ); + final web3Wallet = GetIt.I().web3wallet; return Scaffold( appBar: AppBar( title: Text( _pageDatas[_selectedIndex].title, style: const TextStyle(color: Colors.black), ), + actions: [ + const Text('Relay '), + CircleAvatar( + radius: 6.0, + backgroundColor: web3Wallet.core.relayClient.isConnected + ? Colors.green + : Colors.red, + ), + const SizedBox(width: 16.0), + ], ), body: BottomSheetListener( child: Row( diff --git a/example/wallet/macos/Podfile.lock b/example/wallet/macos/Podfile.lock index 3755bcbc..1f667557 100644 --- a/example/wallet/macos/Podfile.lock +++ b/example/wallet/macos/Podfile.lock @@ -1,7 +1,5 @@ PODS: - FlutterMacOS (1.0.0) - - mobile_scanner (3.5.2): - - FlutterMacOS - package_info_plus (0.0.1): - FlutterMacOS - shared_preferences_foundation (0.0.1): @@ -12,7 +10,6 @@ PODS: DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - - mobile_scanner (from `Flutter/ephemeral/.symlinks/plugins/mobile_scanner/macos`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) @@ -20,8 +17,6 @@ DEPENDENCIES: EXTERNAL SOURCES: FlutterMacOS: :path: Flutter/ephemeral - mobile_scanner: - :path: Flutter/ephemeral/.symlinks/plugins/mobile_scanner/macos package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos shared_preferences_foundation: @@ -31,11 +26,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - mobile_scanner: 621cf2c34e1c74ae7ce5c6793638ab600723bdea package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c - shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 - url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.13.0 +COCOAPODS: 1.15.2 diff --git a/example/wallet/macos/Runner/DebugProfile.entitlements b/example/wallet/macos/Runner/DebugProfile.entitlements index 0830a9c5..91e6008a 100644 --- a/example/wallet/macos/Runner/DebugProfile.entitlements +++ b/example/wallet/macos/Runner/DebugProfile.entitlements @@ -10,5 +10,7 @@ com.apple.security.network.server + com.apple.security.network.client + diff --git a/example/wallet/macos/Runner/Release.entitlements b/example/wallet/macos/Runner/Release.entitlements index 852fa1a4..ee95ab7e 100644 --- a/example/wallet/macos/Runner/Release.entitlements +++ b/example/wallet/macos/Runner/Release.entitlements @@ -4,5 +4,7 @@ com.apple.security.app-sandbox + com.apple.security.network.client + diff --git a/example/wallet/pubspec.yaml b/example/wallet/pubspec.yaml index a0ba66ca..b40d5079 100644 --- a/example/wallet/pubspec.yaml +++ b/example/wallet/pubspec.yaml @@ -23,10 +23,13 @@ dependencies: package_info_plus: ^7.0.0 convert: ^3.0.1 url_launcher: ^6.2.2 + + # CHECK WEB SUPPORT kadena_dart_sdk: ^2.3.2 solana: ^0.30.4 polkadart_keyring: ^0.4.3 - polkadart: ^0.4.3 + polkadart: ^0.4.6 + # walletconnect_flutter_v2: path: ../.. diff --git a/lib/apis/core/connectivity/connectivity.dart b/lib/apis/core/connectivity/connectivity.dart index 157e3772..4f8828f3 100644 --- a/lib/apis/core/connectivity/connectivity.dart +++ b/lib/apis/core/connectivity/connectivity.dart @@ -1,8 +1,45 @@ -import 'package:walletconnect_flutter_v2/apis/core/connectivity/connectivity_models.dart'; +import 'dart:async'; + +import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/connectivity/i_connectivity.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; -class Connectivity implements IConnectivity { +class ConnectivityState implements IConnectivity { + final ICore _core; + ConnectivityState({required ICore core}) : _core = core; + + bool _initialized = false; + + bool _isOnline = false; + @override + bool get isOnline => _isOnline; + @override - Event onConnectivityChange = Event(); + Future init() async { + if (_initialized) return; + final result = await Connectivity().checkConnectivity(); + _updateConnectionStatus(result); + Connectivity().onConnectivityChanged.listen( + _updateConnectionStatus, + ); + _initialized = true; + } + + Future _updateConnectionStatus(List result) async { + _core.logger.i('[$runtimeType] Connectivity changed $result'); + final isMobileData = result.contains(ConnectivityResult.mobile); + final isWifi = result.contains(ConnectivityResult.wifi); + + _isOnline = isMobileData || isWifi; + + if (!_isOnline) { + if (_core.relayClient.isConnected) { + await _core.relayClient.disconnect(); + } + } else { + if (!_core.relayClient.isConnected) { + await _core.relayClient.connect(); + } + } + } } diff --git a/lib/apis/core/connectivity/i_connectivity.dart b/lib/apis/core/connectivity/i_connectivity.dart index 3907493b..8320cff6 100644 --- a/lib/apis/core/connectivity/i_connectivity.dart +++ b/lib/apis/core/connectivity/i_connectivity.dart @@ -1,6 +1,4 @@ -import 'package:event/event.dart'; -import 'package:walletconnect_flutter_v2/apis/core/connectivity/connectivity_models.dart'; - abstract class IConnectivity { - abstract final Event onConnectivityChange; + bool get isOnline; + Future init(); } diff --git a/lib/apis/core/core.dart b/lib/apis/core/core.dart index 9344cea9..4fede26c 100644 --- a/lib/apis/core/core.dart +++ b/lib/apis/core/core.dart @@ -1,4 +1,6 @@ import 'package:logger/logger.dart'; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/connectivity.dart'; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/i_connectivity.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/i_crypto.dart'; import 'package:walletconnect_flutter_v2/apis/core/echo/echo.dart'; @@ -65,6 +67,9 @@ class Core implements ICore { @override late IVerify verify; + @override + late IConnectivity connectivity; + Logger _logger = Logger( level: Level.off, printer: PrettyPrinter(), @@ -169,6 +174,9 @@ class Core implements ICore { core: this, httpClient: httpClient, ); + connectivity = ConnectivityState( + core: this, + ); } @override @@ -178,6 +186,7 @@ class Core implements ICore { await relayClient.init(); await expirer.init(); await pairing.init(); + await connectivity.init(); heartbeat.init(); } } diff --git a/lib/apis/core/i_core.dart b/lib/apis/core/i_core.dart index 85f067ad..bb88fbb5 100644 --- a/lib/apis/core/i_core.dart +++ b/lib/apis/core/i_core.dart @@ -1,4 +1,5 @@ import 'package:logger/logger.dart'; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/i_connectivity.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/i_crypto.dart'; import 'package:walletconnect_flutter_v2/apis/core/echo/i_echo.dart'; import 'package:walletconnect_flutter_v2/apis/core/heartbit/i_heartbeat.dart'; @@ -21,6 +22,7 @@ abstract class ICore { abstract IRelayClient relayClient; abstract IStore> storage; + abstract IConnectivity connectivity; abstract IExpirer expirer; abstract IPairing pairing; abstract IEcho echo; diff --git a/lib/apis/sign_api/sign_engine.dart b/lib/apis/sign_api/sign_engine.dart index 49582fc5..5bbe1078 100644 --- a/lib/apis/sign_api/sign_engine.dart +++ b/lib/apis/sign_api/sign_engine.dart @@ -836,6 +836,9 @@ class SignEngine implements ISignEngine { if (!_initialized) { throw Errors.getInternalError(Errors.NOT_INITIALIZED); } + if (!core.connectivity.isOnline) { + throw WalletConnectError(code: -1, message: 'No internet connection'); + } } String _getRegisterKey(String chainId, String value) { @@ -1964,11 +1967,11 @@ class SignEngine implements ISignEngine { // FORMER AUTH ENGINE PROPERTY @override Map getPendingAuthRequests() { - Map pendingRequests = {}; + Map pendingAuthRequests = {}; authRequests.getAll().forEach((key) { - pendingRequests[key.id] = key; + pendingAuthRequests[key.id] = key; }); - return pendingRequests; + return pendingAuthRequests; } // FORMER AUTH ENGINE PROPERTY @@ -2130,11 +2133,11 @@ class SignEngine implements ISignEngine { // NEW ONE-CLICK AUTH METHOD FOR DAPPS @override Map getPendingSessionAuthRequests() { - Map pendingRequests = {}; + Map pendingSessionAuthRequests = {}; sessionAuthRequests.getAll().forEach((key) { - pendingRequests[key.id] = key; + pendingSessionAuthRequests[key.id] = key; }); - return pendingRequests; + return pendingSessionAuthRequests; } @override diff --git a/pubspec.yaml b/pubspec.yaml index c425da2d..4cd8e856 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: json_annotation: ^4.8.1 logger: ^2.2.0 package_info_plus: ^7.0.0 - pointycastle: ^3.7.4 + pointycastle: ^3.9.1 shared_preferences: ^2.2.2 stack_trace: ^1.10.0 stream_channel: ^2.1.0 diff --git a/test/shared/shared_test_utils.mocks.dart b/test/shared/shared_test_utils.mocks.dart index ea3b4959..6ea9a3b6 100644 --- a/test/shared/shared_test_utils.mocks.dart +++ b/test/shared/shared_test_utils.mocks.dart @@ -3,20 +3,22 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i21; -import 'dart:typed_data' as _i19; +import 'dart:async' as _i22; +import 'dart:typed_data' as _i20; import 'package:event/event.dart' as _i8; import 'package:http/http.dart' as _i9; -import 'package:logger/logger.dart' as _i17; +import 'package:logger/logger.dart' as _i18; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i20; -import 'package:walletconnect_flutter_v2/apis/core/core.dart' as _i26; -import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart' as _i22; +import 'package:mockito/src/dummies.dart' as _i21; +import 'package:walletconnect_flutter_v2/apis/core/connectivity/i_connectivity.dart' + as _i17; +import 'package:walletconnect_flutter_v2/apis/core/core.dart' as _i27; +import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart' as _i23; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_models.dart' as _i2; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_utils.dart' - as _i18; + as _i19; import 'package:walletconnect_flutter_v2/apis/core/crypto/i_crypto.dart' as _i10; import 'package:walletconnect_flutter_v2/apis/core/crypto/i_crypto_utils.dart' @@ -34,16 +36,16 @@ import 'package:walletconnect_flutter_v2/apis/core/relay_auth/i_relay_auth.dart' import 'package:walletconnect_flutter_v2/apis/core/relay_client/i_relay_client.dart' as _i11; import 'package:walletconnect_flutter_v2/apis/core/relay_client/message_tracker.dart' - as _i23; + as _i24; import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/http_client.dart' - as _i25; + as _i26; import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/websocket_handler.dart' - as _i27; + as _i28; import 'package:walletconnect_flutter_v2/apis/core/store/i_generic_store.dart' as _i4; import 'package:walletconnect_flutter_v2/apis/core/store/i_store.dart' as _i7; import 'package:walletconnect_flutter_v2/apis/core/store/store_models.dart' - as _i24; + as _i25; import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart' as _i16; @@ -234,8 +236,19 @@ class _FakeIVerify_16 extends _i1.SmartFake implements _i16.IVerify { ); } -class _FakeLogger_17 extends _i1.SmartFake implements _i17.Logger { - _FakeLogger_17( +class _FakeIConnectivity_17 extends _i1.SmartFake + implements _i17.IConnectivity { + _FakeIConnectivity_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLogger_18 extends _i1.SmartFake implements _i18.Logger { + _FakeLogger_18( Object parent, Invocation parentInvocation, ) : super( @@ -247,7 +260,7 @@ class _FakeLogger_17 extends _i1.SmartFake implements _i17.Logger { /// A class which mocks [CryptoUtils]. /// /// See the documentation for Mockito's code generation for more information. -class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { +class MockCryptoUtils extends _i1.Mock implements _i19.CryptoUtils { MockCryptoUtils() { _i1.throwOnMissingStub(this); } @@ -268,13 +281,13 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ) as _i2.CryptoKeyPair); @override - _i19.Uint8List randomBytes(int? length) => (super.noSuchMethod( + _i20.Uint8List randomBytes(int? length) => (super.noSuchMethod( Invocation.method( #randomBytes, [length], ), - returnValue: _i19.Uint8List(0), - ) as _i19.Uint8List); + returnValue: _i20.Uint8List(0), + ) as _i20.Uint8List); @override String generateRandomBytes32() => (super.noSuchMethod( @@ -282,7 +295,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { #generateRandomBytes32, [], ), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.method( #generateRandomBytes32, @@ -292,7 +305,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ) as String); @override - _i21.Future deriveSymKey( + _i22.Future deriveSymKey( String? privKeyA, String? pubKeyB, ) => @@ -304,7 +317,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { pubKeyB, ], ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #deriveSymKey, @@ -314,7 +327,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ], ), )), - ) as _i21.Future); + ) as _i22.Future); @override String hashKey(String? key) => (super.noSuchMethod( @@ -322,7 +335,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { #hashKey, [key], ), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.method( #hashKey, @@ -337,7 +350,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { #hashMessage, [message], ), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.method( #hashMessage, @@ -347,7 +360,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ) as String); @override - _i21.Future encrypt( + _i22.Future encrypt( String? message, String? symKey, { int? type, @@ -367,7 +380,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { #senderPublicKey: senderPublicKey, }, ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #encrypt, @@ -382,10 +395,10 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { }, ), )), - ) as _i21.Future); + ) as _i22.Future); @override - _i21.Future decrypt( + _i22.Future decrypt( String? symKey, String? encoded, ) => @@ -397,7 +410,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { encoded, ], ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #decrypt, @@ -407,14 +420,14 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ], ), )), - ) as _i21.Future); + ) as _i22.Future); @override String serialize( int? type, - _i19.Uint8List? sealed, - _i19.Uint8List? iv, { - _i19.Uint8List? senderPublicKey, + _i20.Uint8List? sealed, + _i20.Uint8List? iv, { + _i20.Uint8List? senderPublicKey, }) => (super.noSuchMethod( Invocation.method( @@ -426,7 +439,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { ], {#senderPublicKey: senderPublicKey}, ), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.method( #serialize, @@ -519,7 +532,7 @@ class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { /// A class which mocks [Crypto]. /// /// See the documentation for Mockito's code generation for more information. -class MockCrypto extends _i1.Mock implements _i22.Crypto { +class MockCrypto extends _i1.Mock implements _i23.Crypto { MockCrypto() { _i1.throwOnMissingStub(this); } @@ -590,21 +603,21 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#name), ), ) as String); @override - _i21.Future init() => (super.noSuchMethod( + _i22.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override bool hasKeys(String? tag) => (super.noSuchMethod( @@ -616,37 +629,37 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { ) as bool); @override - _i21.Future getClientId() => (super.noSuchMethod( + _i22.Future getClientId() => (super.noSuchMethod( Invocation.method( #getClientId, [], ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #getClientId, [], ), )), - ) as _i21.Future); + ) as _i22.Future); @override - _i21.Future generateKeyPair() => (super.noSuchMethod( + _i22.Future generateKeyPair() => (super.noSuchMethod( Invocation.method( #generateKeyPair, [], ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #generateKeyPair, [], ), )), - ) as _i21.Future); + ) as _i22.Future); @override - _i21.Future generateSharedKey( + _i22.Future generateSharedKey( String? selfPublicKey, String? peerPublicKey, { String? overrideTopic, @@ -660,7 +673,7 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { ], {#overrideTopic: overrideTopic}, ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #generateSharedKey, @@ -671,10 +684,10 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { {#overrideTopic: overrideTopic}, ), )), - ) as _i21.Future); + ) as _i22.Future); @override - _i21.Future setSymKey( + _i22.Future setSymKey( String? symKey, { String? overrideTopic, }) => @@ -684,7 +697,7 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { [symKey], {#overrideTopic: overrideTopic}, ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #setSymKey, @@ -692,30 +705,30 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { {#overrideTopic: overrideTopic}, ), )), - ) as _i21.Future); + ) as _i22.Future); @override - _i21.Future deleteKeyPair(String? publicKey) => (super.noSuchMethod( + _i22.Future deleteKeyPair(String? publicKey) => (super.noSuchMethod( Invocation.method( #deleteKeyPair, [publicKey], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future deleteSymKey(String? topic) => (super.noSuchMethod( + _i22.Future deleteSymKey(String? topic) => (super.noSuchMethod( Invocation.method( #deleteSymKey, [topic], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future encode( + _i22.Future encode( String? topic, Map? payload, { _i2.EncodeOptions? options, @@ -729,11 +742,11 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { ], {#options: options}, ), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future decode( + _i22.Future decode( String? topic, String? encoded, { _i2.DecodeOptions? options, @@ -747,23 +760,23 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { ], {#options: options}, ), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future signJWT(String? aud) => (super.noSuchMethod( + _i22.Future signJWT(String? aud) => (super.noSuchMethod( Invocation.method( #signJWT, [aud], ), - returnValue: _i21.Future.value(_i20.dummyValue( + returnValue: _i22.Future.value(_i21.dummyValue( this, Invocation.method( #signJWT, [aud], ), )), - ) as _i21.Future); + ) as _i22.Future); @override int getPayloadType(String? encoded) => (super.noSuchMethod( @@ -793,7 +806,7 @@ class MockCrypto extends _i1.Mock implements _i22.Crypto { /// A class which mocks [MessageTracker]. /// /// See the documentation for Mockito's code generation for more information. -class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { +class MockMessageTracker extends _i1.Mock implements _i24.MessageTracker { MockMessageTracker() { _i1.throwOnMissingStub(this); } @@ -801,7 +814,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { @override String get context => (super.noSuchMethod( Invocation.getter(#context), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#context), ), @@ -810,7 +823,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { @override String get version => (super.noSuchMethod( Invocation.getter(#version), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#version), ), @@ -826,43 +839,43 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { ) as _i7.IStore); @override - _i8.Event<_i24.StoreCreateEvent>> get onCreate => + _i8.Event<_i25.StoreCreateEvent>> get onCreate => (super.noSuchMethod( Invocation.getter(#onCreate), - returnValue: _FakeEvent_8<_i24.StoreCreateEvent>>( + returnValue: _FakeEvent_8<_i25.StoreCreateEvent>>( this, Invocation.getter(#onCreate), ), - ) as _i8.Event<_i24.StoreCreateEvent>>); + ) as _i8.Event<_i25.StoreCreateEvent>>); @override - _i8.Event<_i24.StoreUpdateEvent>> get onUpdate => + _i8.Event<_i25.StoreUpdateEvent>> get onUpdate => (super.noSuchMethod( Invocation.getter(#onUpdate), - returnValue: _FakeEvent_8<_i24.StoreUpdateEvent>>( + returnValue: _FakeEvent_8<_i25.StoreUpdateEvent>>( this, Invocation.getter(#onUpdate), ), - ) as _i8.Event<_i24.StoreUpdateEvent>>); + ) as _i8.Event<_i25.StoreUpdateEvent>>); @override - _i8.Event<_i24.StoreDeleteEvent>> get onDelete => + _i8.Event<_i25.StoreDeleteEvent>> get onDelete => (super.noSuchMethod( Invocation.getter(#onDelete), - returnValue: _FakeEvent_8<_i24.StoreDeleteEvent>>( + returnValue: _FakeEvent_8<_i25.StoreDeleteEvent>>( this, Invocation.getter(#onDelete), ), - ) as _i8.Event<_i24.StoreDeleteEvent>>); + ) as _i8.Event<_i25.StoreDeleteEvent>>); @override - _i8.Event<_i24.StoreSyncEvent> get onSync => (super.noSuchMethod( + _i8.Event<_i25.StoreSyncEvent> get onSync => (super.noSuchMethod( Invocation.getter(#onSync), - returnValue: _FakeEvent_8<_i24.StoreSyncEvent>( + returnValue: _FakeEvent_8<_i25.StoreSyncEvent>( this, Invocation.getter(#onSync), ), - ) as _i8.Event<_i24.StoreSyncEvent>); + ) as _i8.Event<_i25.StoreSyncEvent>); @override Map> get data => (super.noSuchMethod( @@ -888,7 +901,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { @override String get storageKey => (super.noSuchMethod( Invocation.getter(#storageKey), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#storageKey), ), @@ -900,7 +913,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { #hashMessage, [message], ), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.method( #hashMessage, @@ -910,7 +923,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { ) as String); @override - _i21.Future recordMessageEvent( + _i22.Future recordMessageEvent( String? topic, String? message, ) => @@ -922,9 +935,9 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { message, ], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override bool messageIsRecorded( @@ -943,14 +956,14 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { ) as bool); @override - _i21.Future init() => (super.noSuchMethod( + _i22.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override bool has(String? key) => (super.noSuchMethod( @@ -978,7 +991,7 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { ) as List>); @override - _i21.Future set( + _i22.Future set( String? key, Map? value, ) => @@ -990,39 +1003,39 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { value, ], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future delete(String? key) => (super.noSuchMethod( + _i22.Future delete(String? key) => (super.noSuchMethod( Invocation.method( #delete, [key], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future persist() => (super.noSuchMethod( + _i22.Future persist() => (super.noSuchMethod( Invocation.method( #persist, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future restore() => (super.noSuchMethod( + _i22.Future restore() => (super.noSuchMethod( Invocation.method( #restore, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override void checkInitialized() => super.noSuchMethod( @@ -1037,13 +1050,13 @@ class MockMessageTracker extends _i1.Mock implements _i23.MessageTracker { /// A class which mocks [HttpWrapper]. /// /// See the documentation for Mockito's code generation for more information. -class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { +class MockHttpWrapper extends _i1.Mock implements _i26.HttpWrapper { MockHttpWrapper() { _i1.throwOnMissingStub(this); } @override - _i21.Future<_i9.Response> get( + _i22.Future<_i9.Response> get( Uri? url, { Map? headers, }) => @@ -1053,7 +1066,7 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { [url], {#headers: headers}, ), - returnValue: _i21.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i22.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #get, @@ -1061,10 +1074,10 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { {#headers: headers}, ), )), - ) as _i21.Future<_i9.Response>); + ) as _i22.Future<_i9.Response>); @override - _i21.Future<_i9.Response> delete( + _i22.Future<_i9.Response> delete( Uri? url, { Map? headers, }) => @@ -1074,7 +1087,7 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { [url], {#headers: headers}, ), - returnValue: _i21.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i22.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #delete, @@ -1082,10 +1095,10 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { {#headers: headers}, ), )), - ) as _i21.Future<_i9.Response>); + ) as _i22.Future<_i9.Response>); @override - _i21.Future<_i9.Response> post( + _i22.Future<_i9.Response> post( Uri? url, { Map? headers, Object? body, @@ -1099,7 +1112,7 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { #body: body, }, ), - returnValue: _i21.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i22.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #post, @@ -1110,13 +1123,13 @@ class MockHttpWrapper extends _i1.Mock implements _i25.HttpWrapper { }, ), )), - ) as _i21.Future<_i9.Response>); + ) as _i22.Future<_i9.Response>); } /// A class which mocks [Core]. /// /// See the documentation for Mockito's code generation for more information. -class MockCore extends _i1.Mock implements _i26.Core { +class MockCore extends _i1.Mock implements _i27.Core { MockCore() { _i1.throwOnMissingStub(this); } @@ -1124,7 +1137,7 @@ class MockCore extends _i1.Mock implements _i26.Core { @override String get projectId => (super.noSuchMethod( Invocation.getter(#projectId), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#projectId), ), @@ -1133,7 +1146,7 @@ class MockCore extends _i1.Mock implements _i26.Core { @override String get relayUrl => (super.noSuchMethod( Invocation.getter(#relayUrl), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#relayUrl), ), @@ -1151,7 +1164,7 @@ class MockCore extends _i1.Mock implements _i26.Core { @override String get pushUrl => (super.noSuchMethod( Invocation.getter(#pushUrl), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#pushUrl), ), @@ -1292,6 +1305,24 @@ class MockCore extends _i1.Mock implements _i26.Core { returnValueForMissingStub: null, ); + @override + _i17.IConnectivity get connectivity => (super.noSuchMethod( + Invocation.getter(#connectivity), + returnValue: _FakeIConnectivity_17( + this, + Invocation.getter(#connectivity), + ), + ) as _i17.IConnectivity); + + @override + set connectivity(_i17.IConnectivity? _connectivity) => super.noSuchMethod( + Invocation.setter( + #connectivity, + _connectivity, + ), + returnValueForMissingStub: null, + ); + @override _i7.IStore> get storage => (super.noSuchMethod( Invocation.getter(#storage), @@ -1313,7 +1344,7 @@ class MockCore extends _i1.Mock implements _i26.Core { @override String get protocol => (super.noSuchMethod( Invocation.getter(#protocol), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#protocol), ), @@ -1322,23 +1353,23 @@ class MockCore extends _i1.Mock implements _i26.Core { @override String get version => (super.noSuchMethod( Invocation.getter(#version), - returnValue: _i20.dummyValue( + returnValue: _i21.dummyValue( this, Invocation.getter(#version), ), ) as String); @override - _i17.Logger get logger => (super.noSuchMethod( + _i18.Logger get logger => (super.noSuchMethod( Invocation.getter(#logger), - returnValue: _FakeLogger_17( + returnValue: _FakeLogger_18( this, Invocation.getter(#logger), ), - ) as _i17.Logger); + ) as _i18.Logger); @override - void addLogListener(_i17.LogCallback? callback) => super.noSuchMethod( + void addLogListener(_i18.LogCallback? callback) => super.noSuchMethod( Invocation.method( #addLogListener, [callback], @@ -1347,7 +1378,7 @@ class MockCore extends _i1.Mock implements _i26.Core { ); @override - bool removeLogListener(_i17.LogCallback? callback) => (super.noSuchMethod( + bool removeLogListener(_i18.LogCallback? callback) => (super.noSuchMethod( Invocation.method( #removeLogListener, [callback], @@ -1356,58 +1387,58 @@ class MockCore extends _i1.Mock implements _i26.Core { ) as bool); @override - _i21.Future start() => (super.noSuchMethod( + _i22.Future start() => (super.noSuchMethod( Invocation.method( #start, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); } /// A class which mocks [WebSocketHandler]. /// /// See the documentation for Mockito's code generation for more information. -class MockWebSocketHandler extends _i1.Mock implements _i27.WebSocketHandler { +class MockWebSocketHandler extends _i1.Mock implements _i28.WebSocketHandler { MockWebSocketHandler() { _i1.throwOnMissingStub(this); } @override - _i21.Future get ready => (super.noSuchMethod( + _i22.Future get ready => (super.noSuchMethod( Invocation.getter(#ready), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future setup({required String? url}) => (super.noSuchMethod( + _i22.Future setup({required String? url}) => (super.noSuchMethod( Invocation.method( #setup, [], {#url: url}, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future connect() => (super.noSuchMethod( + _i22.Future connect() => (super.noSuchMethod( Invocation.method( #connect, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future close() => (super.noSuchMethod( + _i22.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); } From f9347755c755deccc40121ec8418a0d5e5cfc379 Mon Sep 17 00:00:00 2001 From: CyberWake Date: Thu, 8 Aug 2024 16:15:40 +0530 Subject: [PATCH 3/8] fix: Parsing in toEthereAmount --- lib/apis/utils/extensions.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/apis/utils/extensions.dart b/lib/apis/utils/extensions.dart index 596e3539..b9e04156 100644 --- a/lib/apis/utils/extensions.dart +++ b/lib/apis/utils/extensions.dart @@ -57,7 +57,7 @@ extension EtheraAmountExtension on String? { final hexValue = this!.replaceFirst('0x', ''); return EtherAmount.fromBigInt( EtherUnit.wei, - BigInt.from(int.parse(hexValue, radix: 16)), + BigInt.parse(hexValue, radix: 16), ); } return null; From 81987e3bed5e025716396a975df6dd442e47ead6 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 8 Aug 2024 14:11:52 +0200 Subject: [PATCH 4/8] tests --- test/auth_api/auth_client_test.dart | 16 ++++------ test/core_api/core_test.dart | 10 ++----- test/core_api/pairing_store_test.dart | 10 ++----- test/core_api/pairing_test.dart | 10 ++----- test/core_api/relay_auth_test.dart | 13 ++++----- test/core_api/relay_client_test.dart | 10 ++----- test/shared/shared_test_utils.dart | 39 +++++++++++++++++++++++++ test/sign_api/sign_client_test.dart | 12 ++------ test/sign_api/sign_engine_test.dart | 10 ++----- test/sign_api/web3wallet_sign_test.dart | 10 ++----- test/web3wallet/web3wallet_test.dart | 11 ++----- 11 files changed, 67 insertions(+), 84 deletions(-) diff --git a/test/auth_api/auth_client_test.dart b/test/auth_api/auth_client_test.dart index 9a795561..e233f328 100644 --- a/test/auth_api/auth_client_test.dart +++ b/test/auth_api/auth_client_test.dart @@ -1,9 +1,10 @@ import 'dart:async'; -import 'dart:typed_data'; -import 'package:eth_sig_util/eth_sig_util.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; + +import 'package:eth_sig_util/eth_sig_util.dart'; + import 'package:walletconnect_flutter_v2/apis/auth_api/auth_engine.dart'; import 'package:walletconnect_flutter_v2/apis/auth_api/i_auth_engine_app.dart'; import 'package:walletconnect_flutter_v2/apis/auth_api/i_auth_engine_wallet.dart'; @@ -18,13 +19,8 @@ import 'utils/signature_constants.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); final List Function(PairingMetadata)> authAppCreators = [ diff --git a/test/core_api/core_test.dart b/test/core_api/core_test.dart index 77f352ac..4587adbe 100644 --- a/test/core_api/core_test.dart +++ b/test/core_api/core_test.dart @@ -1,6 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/relay_client.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; @@ -9,13 +8,8 @@ import '../shared/shared_test_utils.mocks.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(['none']); group('Core throws errors', () { test('on start if there is no internet connection', () async { diff --git a/test/core_api/pairing_store_test.dart b/test/core_api/pairing_store_test.dart index 62f6d670..c5315d43 100644 --- a/test/core_api/pairing_store_test.dart +++ b/test/core_api/pairing_store_test.dart @@ -1,5 +1,4 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/core.dart'; import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; import 'package:walletconnect_flutter_v2/apis/core/pairing/i_json_rpc_history.dart'; @@ -18,13 +17,8 @@ import '../shared/shared_test_values.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); group('Pairing store', () { late ICore coreA; diff --git a/test/core_api/pairing_test.dart b/test/core_api/pairing_test.dart index a38c0c80..219f37a4 100644 --- a/test/core_api/pairing_test.dart +++ b/test/core_api/pairing_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/core.dart'; import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; @@ -18,13 +17,8 @@ import '../shared/shared_test_values.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); test('Format and parses URI correctly', () { Uri response = WalletConnectUtils.formatUri( diff --git a/test/core_api/relay_auth_test.dart b/test/core_api/relay_auth_test.dart index ed0fe89b..683f529e 100644 --- a/test/core_api/relay_auth_test.dart +++ b/test/core_api/relay_auth_test.dart @@ -1,21 +1,18 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_auth/relay_auth.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_auth/relay_auth_models.dart'; import 'package:walletconnect_flutter_v2/apis/utils/constants.dart'; +import '../shared/shared_test_utils.dart'; + void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); group('Relay Auth/API', () { // Client will sign a unique identifier as the subject diff --git a/test/core_api/relay_client_test.dart b/test/core_api/relay_client_test.dart index bbefcaf3..1cdaaf6c 100644 --- a/test/core_api/relay_client_test.dart +++ b/test/core_api/relay_client_test.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart'; import 'package:mockito/mockito.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/relay_client.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; @@ -13,13 +12,8 @@ import '../shared/shared_test_utils.mocks.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); const TEST_TOPIC = 'abc123'; const TEST_MESSAGE = 'swagmasterss'; diff --git a/test/shared/shared_test_utils.dart b/test/shared/shared_test_utils.dart index c9b56aa9..30c29b8e 100644 --- a/test/shared/shared_test_utils.dart +++ b/test/shared/shared_test_utils.dart @@ -1,8 +1,11 @@ // ignore_for_file: no_leading_underscores_for_local_identifiers +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/core.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_utils.dart'; @@ -82,3 +85,39 @@ MockHttpWrapper getHttpWrapper() { return httpWrapper; } + +mockPackageInfo() { + PackageInfo.setMockInitialValues( + appName: _mockInitialValues['appName'], + packageName: _mockInitialValues['packageName'], + version: _mockInitialValues['version'], + buildNumber: _mockInitialValues['buildNumber'], + buildSignature: _mockInitialValues['buildSignature'], + ); +} + +mockConnectivity([List values = const ['wifi']]) { + const channel = MethodChannel('dev.fluttercommunity.plus/connectivity'); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + channel.name, + (data) async { + final call = channel.codec.decodeMethodCall(data); + if (call.method == 'getAll') { + return channel.codec.encodeSuccessEnvelope(_mockInitialValues); + } + if (call.method == 'check') { + return channel.codec.encodeSuccessEnvelope(values); + } + return null; + }, + ); +} + +Map get _mockInitialValues => { + 'appName': 'walletconnect_flutter_v2', + 'packageName': 'com.walletconnect.flutterdapp', + 'version': '1.0', + 'buildNumber': '2', + 'buildSignature': 'buildSignature', + }; diff --git a/test/sign_api/sign_client_test.dart b/test/sign_api/sign_client_test.dart index ced4babc..aebe1fb5 100644 --- a/test/sign_api/sign_client_test.dart +++ b/test/sign_api/sign_client_test.dart @@ -1,7 +1,4 @@ -@Timeout(Duration(seconds: 45)) - import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import '../shared/shared_test_utils.dart'; @@ -11,13 +8,8 @@ import 'utils/sign_client_test_wrapper.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); signEngineTests( context: 'SignClient', diff --git a/test/sign_api/sign_engine_test.dart b/test/sign_api/sign_engine_test.dart index d6b4b433..b30f6d5e 100644 --- a/test/sign_api/sign_engine_test.dart +++ b/test/sign_api/sign_engine_test.dart @@ -1,5 +1,4 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/apis/core/store/generic_store.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/sign_engine.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; @@ -10,13 +9,8 @@ import 'tests/sign_common.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); signEngineTests( context: 'SignEngine', diff --git a/test/sign_api/web3wallet_sign_test.dart b/test/sign_api/web3wallet_sign_test.dart index 04f689b3..770bc7df 100644 --- a/test/sign_api/web3wallet_sign_test.dart +++ b/test/sign_api/web3wallet_sign_test.dart @@ -1,5 +1,4 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import '../shared/shared_test_utils.dart'; @@ -8,13 +7,8 @@ import 'tests/sign_common.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); signEngineTests( context: 'Web3App/Wallet', diff --git a/test/web3wallet/web3wallet_test.dart b/test/web3wallet/web3wallet_test.dart index 7893abfc..8c3e849d 100644 --- a/test/web3wallet/web3wallet_test.dart +++ b/test/web3wallet/web3wallet_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import '../shared/shared_test_utils.dart'; @@ -10,13 +9,9 @@ import 'web3wallet_helpers.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - PackageInfo.setMockInitialValues( - appName: 'walletconnect_flutter_v2', - packageName: 'com.walletconnect.flutterdapp', - version: '1.0', - buildNumber: '2', - buildSignature: 'buildSignature', - ); + mockPackageInfo(); + mockConnectivity(); + final List Function(PairingMetadata)> appCreators = [ (PairingMetadata metadata) async => await Web3App.createInstance( projectId: TEST_PROJECT_ID, From 561ad1fda19ca00d20d52f397b73cf83c91af753 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 8 Aug 2024 15:29:27 +0200 Subject: [PATCH 5/8] fix review --- example/wallet/lib/dependencies/deep_link_handler.dart | 4 ---- example/wallet/lib/dependencies/key_service/key_service.dart | 4 ---- example/wallet/lib/dependencies/web3wallet_service.dart | 5 ++++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index 104fea61..edb2509a 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -9,19 +9,15 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/bottom_sheet/i_bott import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; class DeepLinkHandler { - // static const _methodChannel = MethodChannel( 'com.walletconnect.flutterwallet/methods', ); static const _eventChannel = EventChannel( 'com.walletconnect.flutterwallet/events', ); - // static final _linksController = StreamController.broadcast(); static Stream get onLink => _linksController.stream; - // static final waiting = ValueNotifier(false); - // static void initListener() { if (kIsWeb) return; diff --git a/example/wallet/lib/dependencies/key_service/key_service.dart b/example/wallet/lib/dependencies/key_service/key_service.dart index 91427eb5..abfc0be1 100644 --- a/example/wallet/lib/dependencies/key_service/key_service.dart +++ b/example/wallet/lib/dependencies/key_service/key_service.dart @@ -88,9 +88,6 @@ class KeyService extends IKeyService { _keys.add(chainKey); await _saveKeys(); - - // final mnemonic = bip39.generateMnemonic(); - // await restoreWallet(mnemonic: mnemonic); } @override @@ -98,7 +95,6 @@ class KeyService extends IKeyService { // ⚠️ WARNING: SharedPreferences is not the best way to store your keys! This is just for example purposes! final prefs = await SharedPreferences.getInstance(); await prefs.remove('w3w_chain_keys'); - // await prefs.remove('w3w_mnemonic'); await prefs.setString('w3w_mnemonic', mnemonic); final keyPair = _keyPairFromMnemonic(mnemonic); diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index 61e35295..1f2e3898 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -102,9 +102,12 @@ class Web3WalletService extends IWeb3WalletService { final chainKeys = GetIt.I().getKeysForChain('eip155'); for (var session in sessions) { try { + final chainIds = NamespaceUtils.getChainIdsFromNamespaces( + namespaces: session.namespaces, + ); _web3Wallet!.emitSessionEvent( topic: session.topic, - chainId: 'eip155:1', + chainId: chainIds.first, event: SessionEventParams( name: 'accountsChanged', data: [chainKeys.first.address], From 72d78169bcb582f5609524c4d3118ccd94ca3bb9 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 8 Aug 2024 17:23:35 +0200 Subject: [PATCH 6/8] fix link handler --- .../android/app/src/main/AndroidManifest.xml | 7 +++++++ .../lib/dependencies/deep_link_handler.dart | 17 +++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/example/wallet/android/app/src/main/AndroidManifest.xml b/example/wallet/android/app/src/main/AndroidManifest.xml index c6f892b6..6d620813 100644 --- a/example/wallet/android/app/src/main/AndroidManifest.xml +++ b/example/wallet/android/app/src/main/AndroidManifest.xml @@ -24,6 +24,13 @@ + + + + + + + diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index edb2509a..57adba7e 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -98,15 +98,16 @@ class DeepLinkHandler { static void _onLink(Object? event) { final decodedUri = Uri.parse(Uri.decodeFull(event.toString())); - if (decodedUri.toString().startsWith('wc:')) { - return; + if (decodedUri.isScheme('wc')) { + waiting.value = true; + _linksController.sink.add(decodedUri.toString()); + } else { + if (decodedUri.query.startsWith('uri=')) { + final pairingUri = decodedUri.query.replaceFirst('uri=', ''); + waiting.value = true; + _linksController.sink.add(pairingUri); + } } - final pairingUri = decodedUri.query.replaceFirst('uri=', ''); - if (!pairingUri.toString().startsWith('wc:')) { - return; - } - waiting.value = true; - _linksController.sink.add(pairingUri); } static void _onError(Object error) { From d915fad47dc1633b55edf2433f8915732461a068 Mon Sep 17 00:00:00 2001 From: Alfreedom Date: Thu, 8 Aug 2024 17:43:10 +0200 Subject: [PATCH 7/8] Update lib/apis/core/connectivity/connectivity.dart Co-authored-by: Ignacio Santise <25931366+ignaciosantise@users.noreply.github.com> --- lib/apis/core/connectivity/connectivity.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/apis/core/connectivity/connectivity.dart b/lib/apis/core/connectivity/connectivity.dart index 4f8828f3..db476795 100644 --- a/lib/apis/core/connectivity/connectivity.dart +++ b/lib/apis/core/connectivity/connectivity.dart @@ -32,14 +32,10 @@ class ConnectivityState implements IConnectivity { _isOnline = isMobileData || isWifi; - if (!_isOnline) { - if (_core.relayClient.isConnected) { - await _core.relayClient.disconnect(); - } - } else { - if (!_core.relayClient.isConnected) { - await _core.relayClient.connect(); - } + if (_isOnline && !_core.relayClient.isConnected) { + await _core.relayClient.connect(); + } else if (!_isOnline && _core.relayClient.isConnected) { + await _core.relayClient.disconnect(); } } } From 6d03b1a8a831984910a0e3704b3bc3c33b3bd392 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 8 Aug 2024 17:51:20 +0200 Subject: [PATCH 8/8] version up --- CHANGELOG.md | 6 ++++-- lib/apis/core/connectivity/connectivity.dart | 4 ++-- lib/src/version.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69578656..920c1d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ -## 2.3.1-beta01 +## 2.3.1-beta02 -- Minor changes +- Added Connectivity check to core and throw exceptions when internet connection is gone +- Fix for https://github.com/WalletConnect/WalletConnectFlutterV2/issues/303 (EIP-55 validation for SIWE) +- Minor improvements ## 2.3.0 diff --git a/lib/apis/core/connectivity/connectivity.dart b/lib/apis/core/connectivity/connectivity.dart index db476795..a1639538 100644 --- a/lib/apis/core/connectivity/connectivity.dart +++ b/lib/apis/core/connectivity/connectivity.dart @@ -33,9 +33,9 @@ class ConnectivityState implements IConnectivity { _isOnline = isMobileData || isWifi; if (_isOnline && !_core.relayClient.isConnected) { - await _core.relayClient.connect(); + await _core.relayClient.connect(); } else if (!_isOnline && _core.relayClient.isConnected) { - await _core.relayClient.disconnect(); + await _core.relayClient.disconnect(); } } } diff --git a/lib/src/version.dart b/lib/src/version.dart index bc803013..d9d891dc 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '2.3.1-beta01'; +const packageVersion = '2.3.1-beta02'; diff --git a/pubspec.yaml b/pubspec.yaml index 4cd8e856..c5e7b410 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: walletconnect_flutter_v2 description: WalletConnect's official Dart library v2 for WalletKit and AppKit. The communications protocol for web3. -version: 2.3.1-beta01 +version: 2.3.1-beta02 repository: https://github.com/WalletConnect/WalletConnectFlutterV2 environment: