From 014f85809f52a452bc34c1043509803267b8265d Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Wed, 7 Feb 2024 17:08:29 +0100 Subject: [PATCH] Several bug fixes and enhancements --- CHANGELOG.md | 4 + example/dapp/lib/widgets/session_widget.dart | 9 +- .../bottom_sheet/bottom_sheet_listener.dart | 27 +- .../bottom_sheet/bottom_sheet_service.dart | 2 + .../bottom_sheet/i_bottom_sheet_service.dart | 7 +- .../lib/dependencies/chains/evm_service.dart | 208 ++++++------ .../lib/dependencies/deep_link_handler.dart | 26 +- .../dependencies/key_service/key_service.dart | 7 +- .../lib/dependencies/web3wallet_service.dart | 53 +++- example/wallet/lib/main.dart | 7 +- example/wallet/lib/models/chain_data.dart | 54 +++- example/wallet/lib/pages/app_detail_page.dart | 77 ++++- example/wallet/lib/pages/apps_page.dart | 18 +- example/wallet/lib/pages/settings_page.dart | 299 +++++++++--------- example/wallet/lib/widgets/pairing_item.dart | 36 +-- .../wc_connection_request_widget.dart | 14 +- lib/apis/utils/extensions.dart | 50 +++ lib/src/version.dart | 2 +- lib/walletconnect_flutter_v2.dart | 2 + pubspec.yaml | 2 +- 20 files changed, 572 insertions(+), 332 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afaa040f..7dab9ec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.0-beta02 + +- Improvements on example wallet + ## 2.2.0-beta01 - Added Smart Contract interactions to SignEngine diff --git a/example/dapp/lib/widgets/session_widget.dart b/example/dapp/lib/widgets/session_widget.dart index 7532033f..56d99bb4 100644 --- a/example/dapp/lib/widgets/session_widget.dart +++ b/example/dapp/lib/widgets/session_widget.dart @@ -60,10 +60,11 @@ class SessionWidgetState extends State { child: ElevatedButton( onPressed: () async { await widget.web3App.disconnectSession( - topic: widget.session.topic, - reason: Errors.getSdkError( - Errors.USER_DISCONNECTED, - )); + topic: widget.session.topic, + reason: Errors.getSdkError( + Errors.USER_DISCONNECTED, + ), + ); }, style: ButtonStyle( backgroundColor: MaterialStateProperty.all( 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 0d4a7bb6..cac0c2e0 100644 --- a/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart +++ b/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_listener.dart @@ -43,13 +43,16 @@ class BottomSheetListenerState extends State { maxHeight: MediaQuery.of(context).size.height * 0.9, ), builder: (context) { + if (item.closeAfter > 0) { + Future.delayed(Duration(seconds: item.closeAfter), () { + Navigator.pop(context); + }); + } return Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all( - Radius.circular( - StyleConstants.linear16, - ), + Radius.circular(StyleConstants.linear16), ), ), padding: EdgeInsets.only( @@ -62,7 +65,23 @@ class BottomSheetListenerState extends State { margin: const EdgeInsets.all( StyleConstants.linear16, ), - child: item.widget, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + padding: const EdgeInsets.all(0.0), + visualDensity: VisualDensity.compact, + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.close_sharp), + ), + ], + ), + Flexible(child: item.widget), + ], + ), ); }, ); diff --git a/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_service.dart b/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_service.dart index e2568ec2..fb48fa05 100644 --- a/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_service.dart +++ b/example/wallet/lib/dependencies/bottom_sheet/bottom_sheet_service.dart @@ -13,12 +13,14 @@ class BottomSheetService extends IBottomSheetService { @override Future queueBottomSheet({ required Widget widget, + int closeAfter = 0, }) async { // Create the bottom sheet queue item final completer = Completer(); final queueItem = BottomSheetQueueItem( widget: widget, completer: completer, + closeAfter: closeAfter, ); // If the current sheet it null, set it to the queue item diff --git a/example/wallet/lib/dependencies/bottom_sheet/i_bottom_sheet_service.dart b/example/wallet/lib/dependencies/bottom_sheet/i_bottom_sheet_service.dart index adca14af..5ccca104 100644 --- a/example/wallet/lib/dependencies/bottom_sheet/i_bottom_sheet_service.dart +++ b/example/wallet/lib/dependencies/bottom_sheet/i_bottom_sheet_service.dart @@ -5,17 +5,22 @@ import 'package:flutter/material.dart'; class BottomSheetQueueItem { final Widget widget; final Completer completer; + final int closeAfter; BottomSheetQueueItem({ required this.widget, required this.completer, + this.closeAfter = 0, }); } abstract class IBottomSheetService { abstract final ValueNotifier currentSheet; - Future queueBottomSheet({required Widget widget}); + Future queueBottomSheet({ + required Widget widget, + int closeAfter = 0, + }); void showNext(); } diff --git a/example/wallet/lib/dependencies/chains/evm_service.dart b/example/wallet/lib/dependencies/chains/evm_service.dart index 1f2521c5..80e4b9af 100644 --- a/example/wallet/lib/dependencies/chains/evm_service.dart +++ b/example/wallet/lib/dependencies/chains/evm_service.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; // ignore: depend_on_referenced_packages import 'package:http/http.dart' as http; import 'package:convert/convert.dart'; @@ -11,57 +12,23 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/deep_link_handler.d 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_data.dart'; +import 'package:walletconnect_flutter_v2_wallet/models/chain_metadata.dart'; +import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/eth_utils.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/wc_connection_widget/wc_connection_model.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/wc_connection_widget/wc_connection_widget.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/wc_request_widget.dart/wc_request_widget.dart'; -enum EVMChainsSupported { - ethereum, - polygon, - arbitrum, - sepolia, - // bsc, - mumbai; - - String chain() { - String id = ''; - - switch (this) { - case EVMChainsSupported.ethereum: - id = '1'; - break; - case EVMChainsSupported.polygon: - id = '137'; - break; - case EVMChainsSupported.arbitrum: - id = '42161'; - break; - case EVMChainsSupported.sepolia: - id = '11155111'; - break; - // case EVMChainsSupported.bsc: - // id = '56'; - // break; - case EVMChainsSupported.mumbai: - id = '80001'; - break; - } - - return 'eip155:$id'; - } -} - class EVMService { final _bottomSheetService = GetIt.I(); final _web3WalletService = GetIt.I(); final _web3Wallet = GetIt.I().getWeb3Wallet(); - final EVMChainsSupported chainSupported; + final ChainMetadata chainSupported; late final Web3Client ethClient; EVMService({required this.chainSupported}) { - final supportedId = chainSupported.chain(); + final supportedId = chainSupported.chainId; final chainMetadata = ChainData.allChains.firstWhere( (c) => c.chainId == supportedId, ); @@ -70,9 +37,9 @@ class EVMService { const supportedEvents = EventsConstants.requiredEvents; for (final String event in supportedEvents) { - debugPrint('Supported event ${chainSupported.chain()} $event'); + debugPrint('Supported event ${chainSupported.chainId} $event'); _web3Wallet.registerEventEmitter( - chainId: chainSupported.chain(), + chainId: chainSupported.chainId, event: event, ); } @@ -81,8 +48,8 @@ class EVMService { 'personal_sign': personalSign, 'eth_sign': ethSign, 'eth_signTransaction': ethSignTransaction, - 'eth_signTypedData': ethSignTypedData, 'eth_sendTransaction': ethSendTransaction, + 'eth_signTypedData': ethSignTypedData, 'eth_signTypedData_v4': ethSignTypedData, 'wallet_switchEthereumChain': switchChain, 'wallet_addEthereumChain': addChain, @@ -91,7 +58,7 @@ class EVMService { for (var handler in methodsHandlers.entries) { _web3Wallet.registerRequestHandler( - chainId: chainSupported.chain(), + chainId: chainSupported.chainId, method: handler.key, handler: handler.value, ); @@ -101,6 +68,8 @@ class EVMService { Future personalSign(String topic, dynamic parameters) async { debugPrint('[$runtimeType] personalSign request: $parameters'); dynamic result; + + // final pRequest = _web3Wallet.pendingRequests.getAll().first; final data = EthUtils.getDataFromParamsList(parameters); final message = EthUtils.getUtf8Message(data.toString()); @@ -108,7 +77,7 @@ class EVMService { try { // Load the private key final keys = GetIt.I().getKeysForChain( - chainSupported.chain(), + chainSupported.chainId, ); final credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -127,9 +96,7 @@ class EVMService { result = const JsonRpcError(code: 5001, message: 'User rejected method'); } - final session = _web3Wallet.sessions.get(topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + _goBackToDapp(topic, result); return result; } @@ -137,6 +104,8 @@ class EVMService { Future ethSign(String topic, dynamic parameters) async { debugPrint('[$runtimeType] ethSign request: $parameters'); dynamic result; + + // final pRequest = _web3Wallet.pendingRequests.getAll().first; final data = EthUtils.getDataFromParamsList(parameters); final message = EthUtils.getUtf8Message(data.toString()); @@ -144,7 +113,7 @@ class EVMService { try { // Load the private key final keys = GetIt.I().getKeysForChain( - chainSupported.chain(), + chainSupported.chainId, ); final credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -163,9 +132,7 @@ class EVMService { result = const JsonRpcError(code: 5001, message: 'User rejected method'); } - final session = _web3Wallet.sessions.get(topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + _goBackToDapp(topic, result); return result; } @@ -173,12 +140,13 @@ class EVMService { Future ethSignTypedData(String topic, dynamic parameters) async { debugPrint('[$runtimeType] ethSignTypedData request: $parameters'); dynamic result; - final data = parameters[1] as String; + // final pRequest = _web3Wallet.pendingRequests.getAll().first; + final data = parameters[1] as String; if (await requestApproval(data)) { try { final keys = GetIt.I().getKeysForChain( - chainSupported.chain(), + chainSupported.chainId, ); result = EthSigUtil.signTypedData( @@ -194,9 +162,7 @@ class EVMService { result = const JsonRpcError(code: 5001, message: 'User rejected method'); } - final session = _web3Wallet.sessions.get(topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + _goBackToDapp(topic, result); return result; } @@ -221,28 +187,31 @@ class EVMService { debugPrint('[$runtimeType] ethSignTransaction request: $parameters'); dynamic result; + // final pRequest = _web3Wallet.pendingRequests.getAll().first; final tJson = parameters[0] as Map; final transaction = await approveTransaction(tJson); if (transaction != null) { try { // Load the private key final keys = GetIt.I().getKeysForChain( - chainSupported.chain(), + chainSupported.chainId, ); final credentials = EthPrivateKey.fromHex('0x${keys[0].privateKey}'); - final chainId = chainSupported.chain().split(':').last; + final chainId = chainSupported.chainId.split(':').last; + debugPrint('[$runtimeType] ethSignTransaction chainId: $chainId'); final signature = await ethClient.signTransaction( credentials, transaction, chainId: int.parse(chainId), ); - // Sign the transaction final signedTx = hex.encode(signature); - // Return the signed transaction as a hexadecimal string result = '0x$signedTx'; + } on RPCError catch (e) { + debugPrint('[$runtimeType] ethSignTransaction error $e'); + result = JsonRpcError(code: e.errorCode, message: e.message); } catch (e) { debugPrint('[$runtimeType] ethSignTransaction error $e'); result = JsonRpcError(code: 0, message: e.toString()); @@ -251,9 +220,7 @@ class EVMService { result = const JsonRpcError(code: 5001, message: 'User rejected method'); } - final session = _web3Wallet.sessions.get(topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + _goBackToDapp(topic, result); return result; } @@ -262,17 +229,17 @@ class EVMService { debugPrint('[$runtimeType] ethSendTransaction request: $parameters'); dynamic result; + // final pRequest = _web3Wallet.pendingRequests.getAll().first; final tJson = parameters[0] as Map; final transaction = await approveTransaction(tJson); - if (transaction != null) { + if (transaction is Transaction) { try { // Load the private key final keys = GetIt.I().getKeysForChain( - chainSupported.chain(), + chainSupported.chainId, ); final credentials = EthPrivateKey.fromHex('0x${keys[0].privateKey}'); - - final chainId = chainSupported.chain().split(':').last; + final chainId = chainSupported.chainId.split(':').last; debugPrint('[$runtimeType] ethSendTransaction chainId: $chainId'); final signedTx = await ethClient.sendTransaction( @@ -282,21 +249,43 @@ class EVMService { ); result = '0x$signedTx'; + } on RPCError catch (e) { + debugPrint('[$runtimeType] ethSendTransaction error $e'); + result = JsonRpcError(code: e.errorCode, message: e.message); } catch (e) { debugPrint('[$runtimeType] ethSendTransaction error $e'); result = JsonRpcError(code: 0, message: e.toString()); } } else { - result = const JsonRpcError(code: 5001, message: 'User rejected method'); + result = transaction as JsonRpcError; } - final session = _web3Wallet.sessions.get(topic); - final scheme = session?.peer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + _goBackToDapp(topic, result); return result; } + void _goBackToDapp(String topic, dynamic result) { + try { + final session = _web3Wallet.sessions.get(topic); + final scheme = session?.peer.metadata.redirect?.native ?? ''; + if (result is String) { + DeepLinkHandler.goTo(scheme, delay: 300, modalTitle: 'Success'); + } else { + DeepLinkHandler.goTo( + scheme, + delay: 300, + modalTitle: 'Error', + modalMessage: result.toString(), + success: false, + ); + } + } catch (e, s) { + debugPrint(e.toString()); + print(s); + } + } + Future addChain(String topic, dynamic parameters) async { debugPrint('received addChain request: $topic $parameters'); } @@ -316,43 +305,52 @@ class EVMService { return approved ?? false; } - Future approveTransaction(Map tJson) async { - String? tValue = tJson['value']; - EtherAmount? value; - if (tValue != null) { - tValue = tValue.replaceFirst('0x', ''); - value = EtherAmount.fromBigInt( - EtherUnit.wei, - BigInt.from(int.parse(tValue, radix: 16)), - ); - } - Transaction transaction = Transaction( - from: EthereumAddress.fromHex(tJson['from']), - to: EthereumAddress.fromHex(tJson['to']), - value: value, - gasPrice: tJson['gasPrice'], - maxFeePerGas: tJson['maxFeePerGas'], - maxPriorityFeePerGas: tJson['maxPriorityFeePerGas'], - maxGas: tJson['maxGas'], - nonce: tJson['nonce'], - data: (tJson['data'] != null && tJson['data'] != '0x') - ? Uint8List.fromList(hex.decode(tJson['data']!)) - : null, - ); + Future approveTransaction(Map tJson) async { + Transaction transaction = tJson.toTransaction(); final gasPrice = await ethClient.getGasPrice(); - final gasLimit = await ethClient.estimateGas( - sender: transaction.from, - to: transaction.to, - value: transaction.value, - data: transaction.data, - gasPrice: gasPrice, - ); + try { + final gasLimit = await ethClient.estimateGas( + sender: transaction.from, + to: transaction.to, + value: transaction.value, + data: transaction.data, + gasPrice: gasPrice, + ); - transaction = transaction.copyWith( - gasPrice: gasPrice, - maxGas: gasLimit.toInt(), - ); + transaction = transaction.copyWith( + gasPrice: gasPrice, + maxGas: gasLimit.toInt(), + ); + } on RPCError catch (e) { + await _bottomSheetService.queueBottomSheet( + widget: Container( + color: Colors.white, + height: 210.0, + width: double.infinity, + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Icon( + Icons.error_outline_sharp, + color: Colors.red[100], + size: 80.0, + ), + Text( + 'Error', + style: StyleConstants.subtitleText.copyWith( + color: Colors.black, + fontSize: 18.0, + ), + ), + Text(e.message), + ], + ), + ), + ); + + return JsonRpcError(code: e.errorCode, message: e.message); + } final gweiGasPrice = (transaction.gasPrice?.getInWei ?? BigInt.zero) / BigInt.from(1000000000); @@ -376,6 +374,6 @@ class EVMService { return transaction; } - return null; + return const JsonRpcError(code: 5001, message: 'User rejected method'); } } diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index 56d83a8c..de47a44d 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -36,13 +36,20 @@ class DeepLinkHandler { String scheme, { int delay = 0, String? modalTitle, + String? modalMessage, + bool success = true, }) async { + if (scheme.isEmpty) return; await Future.delayed(Duration(milliseconds: delay)); try { await launchUrlString(scheme, mode: LaunchMode.externalApplication); } catch (e) { debugPrint('[DeepLinkHandler] error re-opening dapp ($scheme). $e'); - _goBackModal(title: modalTitle); + _goBackModal( + title: modalTitle, + message: modalMessage, + success: success, + ); } } @@ -62,18 +69,23 @@ class DeepLinkHandler { debugPrint('[DeepLinkHandler] _onError $error'); } - static void _goBackModal({String? title}) async { - GetIt.I().queueBottomSheet( + static void _goBackModal({ + String? title, + String? message, + bool success = true, + }) async { + await GetIt.I().queueBottomSheet( + closeAfter: success ? 3 : 0, widget: Container( color: Colors.white, - height: 180.0, + height: 210.0, width: double.infinity, padding: const EdgeInsets.all(20.0), child: Column( children: [ Icon( - Icons.check_circle_sharp, - color: Colors.green[100], + success ? Icons.check_circle_sharp : Icons.error_outline_sharp, + color: success ? Colors.green[100] : Colors.red[100], size: 80.0, ), Text( @@ -83,7 +95,7 @@ class DeepLinkHandler { fontSize: 18.0, ), ), - const Text('You can go back to your dApp now'), + Text(message ?? 'You can go back to your dApp now'), ], ), ), diff --git a/example/wallet/lib/dependencies/key_service/key_service.dart b/example/wallet/lib/dependencies/key_service/key_service.dart index f831ffe4..be12c496 100644 --- a/example/wallet/lib/dependencies/key_service/key_service.dart +++ b/example/wallet/lib/dependencies/key_service/key_service.dart @@ -2,9 +2,9 @@ import 'package:convert/convert.dart'; import 'package:flutter/foundation.dart'; import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_models.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; -import 'package:walletconnect_flutter_v2_wallet/dependencies/chains/evm_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/chain_key.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/i_key_service.dart'; +import 'package:walletconnect_flutter_v2_wallet/models/chain_data.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/dart_defines.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/bip39/bip39_base.dart' as bip39; @@ -25,7 +25,7 @@ class KeyService extends IKeyService { final publicKey = prefs.getString('publicKey') ?? ''; final address = getAddressFromPrivateKey(privateKey); final evmChainKey = ChainKey( - chains: EVMChainsSupported.values.map((e) => e.chain()).toList(), + chains: ChainData.allChains.map((e) => e.chainId).toList(), privateKey: privateKey, publicKey: publicKey, address: address, @@ -107,11 +107,10 @@ class KeyService extends IKeyService { @override Future restoreWallet({required String mnemonic}) async { - print(mnemonic); final keyPair = keyPairFromMnemonic(mnemonic); final address = getAddressFromPrivateKey(keyPair.privateKey); final evmChainKey = ChainKey( - chains: EVMChainsSupported.values.map((e) => e.chain()).toList(), + chains: ChainData.allChains.map((e) => e.chainId).toList(), privateKey: keyPair.privateKey, publicKey: keyPair.publicKey, address: address, diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index e898b79d..2a7c897a 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -10,6 +10,7 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/deep_link_handler.d import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/chain_key.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/i_key_service.dart'; +import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/dart_defines.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/wc_connection_request/wc_auth_request_model.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/wc_connection_request/wc_connection_request_widget.dart'; @@ -127,8 +128,41 @@ class Web3WalletService extends IWeb3WalletService { debugPrint('[$runtimeType] _onRelayClientError ${args?.error}'); } - void _onSessionProposalError(SessionProposalErrorEvent? args) { + void _onSessionProposalError(SessionProposalErrorEvent? args) async { debugPrint('[$runtimeType] _onSessionProposalError $args'); + if (args != null) { + String errorMessage = args.error.message; + if (args.error.code == 5100) { + errorMessage = + errorMessage.replaceFirst('Requested:', '\n\nRequested:'); + errorMessage = + errorMessage.replaceFirst('Supported:', '\n\nSupported:'); + } + GetIt.I().queueBottomSheet( + widget: Container( + color: Colors.white, + width: double.infinity, + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Icon( + Icons.error_outline_sharp, + color: Colors.red[100], + size: 80.0, + ), + Text( + 'Error', + style: StyleConstants.subtitleText.copyWith( + color: Colors.black, + fontSize: 18.0, + ), + ), + Text(errorMessage), + ], + ), + ), + ); + } } void _onSessionProposal(SessionProposalEvent? args) async { @@ -150,15 +184,26 @@ class Web3WalletService extends IWeb3WalletService { id: args.id, namespaces: args.params.generatedNamespaces!, ); + final scheme = args.params.proposer.metadata.redirect?.native ?? ''; + DeepLinkHandler.goTo(scheme, delay: 300); } else { _web3Wallet!.rejectSession( id: args.id, reason: Errors.getSdkError(Errors.USER_REJECTED), ); - } + _web3Wallet!.core.pairing.disconnect( + topic: args.params.pairingTopic, + ); - final scheme = args.params.proposer.metadata.redirect?.native ?? ''; - DeepLinkHandler.goTo(scheme, delay: 300); + final scheme = args.params.proposer.metadata.redirect?.native ?? ''; + DeepLinkHandler.goTo( + scheme, + delay: 300, + modalTitle: 'Error', + modalMessage: 'User rejected', + success: false, + ); + } } } diff --git a/example/wallet/lib/main.dart b/example/wallet/lib/main.dart index f6006faf..b5260396 100644 --- a/example/wallet/lib/main.dart +++ b/example/wallet/lib/main.dart @@ -9,6 +9,7 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_servic import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/i_key_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/key_service/key_service.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/web3wallet_service.dart'; +import 'package:walletconnect_flutter_v2_wallet/models/chain_data.dart'; import 'package:walletconnect_flutter_v2_wallet/models/page_data.dart'; import 'package:walletconnect_flutter_v2_wallet/pages/apps_page.dart'; import 'package:walletconnect_flutter_v2_wallet/pages/settings_page.dart'; @@ -62,10 +63,10 @@ class _MyHomePageState extends State with GetItStateMixin { web3WalletService.create(); GetIt.I.registerSingleton(web3WalletService); - for (final supportedChain in EVMChainsSupported.values) { + for (final chainData in ChainData.allChains) { GetIt.I.registerSingleton( - EVMService(chainSupported: supportedChain), - instanceName: supportedChain.chain(), + EVMService(chainSupported: chainData), + instanceName: chainData.chainId, ); } diff --git a/example/wallet/lib/models/chain_data.dart b/example/wallet/lib/models/chain_data.dart index edaef5a4..c42baaa6 100644 --- a/example/wallet/lib/models/chain_data.dart +++ b/example/wallet/lib/models/chain_data.dart @@ -27,14 +27,46 @@ class ChainData { color: Colors.blue, rpc: ['https://arbitrum.blockpi.network/v1/rpc/public'], ), + const ChainMetadata( + type: ChainType.eip155, + chainId: 'eip155:10', + name: 'OP Mainnet', + logo: '/chain-logos/eip155-10.png', + color: Colors.red, + rpc: ['https://mainnet.optimism.io/'], + ), const ChainMetadata( type: ChainType.eip155, chainId: 'eip155:43114', name: 'Avalanche', logo: '/chain-logos/eip155-43114.png', - color: Colors.red, + color: Colors.orange, rpc: ['https://api.avax.network/ext/bc/C/rpc'], ), + const ChainMetadata( + type: ChainType.eip155, + chainId: 'eip155:42220', + name: 'Celo', + logo: '/chain-logos/eip155-42220.png', + color: Colors.green, + rpc: ['https://forno.celo.org/'], + ), + const ChainMetadata( + type: ChainType.eip155, + chainId: 'eip155:100', + name: 'Gnosis', + logo: '/chain-logos/eip155-100.png', + color: Colors.greenAccent, + rpc: ['https://rpc.gnosischain.com/'], + ), + const ChainMetadata( + type: ChainType.eip155, + chainId: 'eip155:324', + name: 'zkSync', + logo: '/chain-logos/eip155-324.png', + color: Colors.black, + rpc: ['https://mainnet.era.zksync.io'], + ), ]; static final List testChains = [ @@ -56,16 +88,16 @@ class ChainData { isTestnet: true, rpc: ['https://matic-mumbai.chainstacklabs.com'], ), - ChainMetadata( - type: ChainType.kadena, - chainId: 'kadena:testnet04', - name: 'Kadena', - logo: 'TODO', - color: Colors.purple.shade600, - rpc: [ - 'https://api.testnet.chainweb.com', - ], - ), + // ChainMetadata( + // type: ChainType.kadena, + // chainId: 'kadena:testnet04', + // name: 'Kadena', + // logo: 'TODO', + // color: Colors.purple.shade600, + // rpc: [ + // 'https://api.testnet.chainweb.com', + // ], + // ), ]; static final List allChains = [...mainChains, ...testChains]; diff --git a/example/wallet/lib/pages/app_detail_page.dart b/example/wallet/lib/pages/app_detail_page.dart index f78393b5..7e416941 100644 --- a/example/wallet/lib/pages/app_detail_page.dart +++ b/example/wallet/lib/pages/app_detail_page.dart @@ -5,7 +5,6 @@ import 'package:walletconnect_flutter_v2_wallet/dependencies/deep_link_handler.d import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_service.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/namespace_model_builder.dart'; -import 'package:walletconnect_flutter_v2_wallet/utils/string_constants.dart'; import 'package:walletconnect_flutter_v2_wallet/widgets/custom_button.dart'; class AppDetailPage extends StatefulWidget { @@ -21,6 +20,31 @@ class AppDetailPage extends StatefulWidget { } class AppDetailPageState extends State { + late Web3Wallet _web3Wallet; + + @override + void initState() { + super.initState(); + _web3Wallet = GetIt.I().getWeb3Wallet(); + _web3Wallet.onSessionDelete.subscribe(_onSessionDelete); + _web3Wallet.onSessionExpire.subscribe(_onSessionDelete); + } + + @override + void dispose() { + _web3Wallet.onSessionDelete.unsubscribe(_onSessionDelete); + _web3Wallet.onSessionExpire.unsubscribe(_onSessionDelete); + super.dispose(); + } + + void _onSessionDelete(dynamic args) { + _web3Wallet = GetIt.I().getWeb3Wallet(); + setState(() { + // _pairings = web3Wallet.pairings.getAll(); + // _sessions = web3Wallet.sessions.getAll(); + }); + } + @override Widget build(BuildContext context) { DateTime dateTime = @@ -32,10 +56,7 @@ class AppDetailPageState extends State { String expiryDate = '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}'; - List sessions = GetIt.I - .get() - .getWeb3Wallet() - .sessions + final sessions = _web3Wallet.sessions .getAll() .where((element) => element.pairingTopic == widget.pairing.topic) .toList(); @@ -53,6 +74,36 @@ class AppDetailPageState extends State { sessionWidgets.add(const SizedBox(height: 20.0)); } } + sessionWidgets.add(const SizedBox.square(dimension: 10.0)); + sessionWidgets.add( + Row( + children: [ + CustomButton( + type: CustomButtonType.normal, + onTap: () async { + try { + await _web3Wallet.disconnectSession( + topic: session.topic, + reason: Errors.getSdkError(Errors.USER_DISCONNECTED), + ); + setState(() {}); + } catch (e) { + debugPrint(e.toString()); + } + }, + child: const Center( + child: Text( + 'Disconnect Session', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ); } final scheme = widget.pairing.peerMetadata?.redirect?.native ?? ''; return Scaffold( @@ -116,11 +167,15 @@ class AppDetailPageState extends State { type: CustomButtonType.invalid, onTap: () async { try { - await GetIt.I() - .getWeb3Wallet() - .core - .pairing - .disconnect(topic: widget.pairing.topic); + for (var session in sessions) { + await _web3Wallet.disconnectSession( + topic: session.topic, + reason: Errors.getSdkError(Errors.USER_DISCONNECTED), + ); + } + await _web3Wallet.core.pairing.disconnect( + topic: widget.pairing.topic, + ); _back(); } catch (e) { //debugPrint(e.toString()); @@ -128,7 +183,7 @@ class AppDetailPageState extends State { }, child: const Center( child: Text( - StringConstants.delete, + 'Delete Pairing', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, diff --git a/example/wallet/lib/pages/apps_page.dart b/example/wallet/lib/pages/apps_page.dart index 5baacd59..baa2d50d 100644 --- a/example/wallet/lib/pages/apps_page.dart +++ b/example/wallet/lib/pages/apps_page.dart @@ -29,8 +29,12 @@ class AppsPageState extends State with GetItStateMixin { super.initState(); web3Wallet = GetIt.I().getWeb3Wallet(); _pairings = web3Wallet.pairings.getAll(); + _pairings = _pairings.where((p) => p.active).toList(); web3Wallet.core.pairing.onPairingDelete.subscribe(_onPairingDelete); web3Wallet.core.pairing.onPairingExpire.subscribe(_onPairingDelete); + web3Wallet.onSessionDelete.subscribe(_updateState); + web3Wallet.onSessionExpire.subscribe(_updateState); + web3Wallet.onSessionConnect.subscribe(_updateState); // TODO web3Wallet.core.echo.register(firebaseAccessToken); DeepLinkHandler.onLink.listen(_deepLinkListener); DeepLinkHandler.checkInitialLink(); @@ -48,12 +52,16 @@ class AppsPageState extends State with GetItStateMixin { void dispose() { web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete); web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete); + web3Wallet.onSessionDelete.unsubscribe(_updateState); + web3Wallet.onSessionExpire.unsubscribe(_updateState); + web3Wallet.onSessionConnect.unsubscribe(_updateState); super.dispose(); } @override Widget build(BuildContext context) { - _pairings = watch(target: GetIt.I().pairings); + _pairings = (watch(target: GetIt.I().pairings)); + _pairings = _pairings.where((p) => p.active).toList(); return Stack( children: [ _pairings.isEmpty ? _buildNoPairingMessage() : _buildPairingList(), @@ -84,7 +92,7 @@ class AppsPageState extends State with GetItStateMixin { } Widget _buildPairingList() { - final List pairingItems = _pairings + final pairingItems = _pairings .map( (PairingInfo pairing) => PairingItem( key: ValueKey(pairing.topic), @@ -184,6 +192,12 @@ class AppsPageState extends State with GetItStateMixin { }); } + void _updateState(dynamic args) { + setState(() { + _pairings = web3Wallet.pairings.getAll(); + }); + } + void _onListItemTap(PairingInfo pairing) { Navigator.push( context, diff --git a/example/wallet/lib/pages/settings_page.dart b/example/wallet/lib/pages/settings_page.dart index 466450e5..d8134d25 100644 --- a/example/wallet/lib/pages/settings_page.dart +++ b/example/wallet/lib/pages/settings_page.dart @@ -1,10 +1,17 @@ +import 'dart:ui'; + +import 'package:fl_toast/fl_toast.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; 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/key_service/i_key_service.dart'; 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'; +// ignore: depend_on_referenced_packages +import 'package:package_info_plus/package_info_plus.dart'; class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); @@ -14,6 +21,18 @@ class SettingsPage extends StatefulWidget { } class _SettingsPageState extends State { + String? version; + @override + void initState() { + super.initState(); + PackageInfo.fromPlatform().then((info) { + setState(() { + version = + '${info.version} (${info.buildNumber}) - SDK v$packageVersion'; + }); + }); + } + @override Widget build(BuildContext context) { final keysService = GetIt.I(); @@ -23,143 +42,64 @@ class _SettingsPageState extends State { 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, - ), - ), - ), - Container( - decoration: BoxDecoration( - color: StyleConstants.lightGray, - borderRadius: BorderRadius.circular( - StyleConstants.linear16, - ), - ), - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - Text( - 'CAIP-10', + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + const Padding( + padding: EdgeInsets.only(left: 8.0, bottom: 8.0), + child: Text( + 'Account', style: TextStyle( color: Colors.black, - fontSize: 14.0, - fontWeight: FontWeight.bold, + fontSize: 16.0, + fontWeight: FontWeight.w500, ), ), - SizedBox( - width: 8.0, - ), - Icon( - Icons.copy, - size: 14.0, - ), - ], - ), - Text( - 'eip155:1:${chainKeys.first.address}', - style: const TextStyle( - color: Colors.black87, - fontSize: 13.0, - fontWeight: FontWeight.w400, ), - ), - ], - ), - ), - const SizedBox(height: 12.0), - Container( - decoration: BoxDecoration( - color: StyleConstants.lightGray, - borderRadius: BorderRadius.circular( - StyleConstants.linear16, - ), - ), - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - Text( - 'Private key', - style: TextStyle( - color: Colors.black, - fontSize: 14.0, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - width: 8.0, - ), - Icon( - Icons.copy, - size: 14.0, - ), - ], - ), - Text( - chainKeys.first.privateKey, - style: const TextStyle( - color: Colors.black87, - fontSize: 13.0, - fontWeight: FontWeight.w400, + _DataContainer( + title: 'CAIP-10', + data: 'eip155:1:${chainKeys.first.address}', ), - ), - ], - ), - ), - const SizedBox(height: 12.0), - Container( - decoration: BoxDecoration( - color: StyleConstants.lightGray, - borderRadius: BorderRadius.circular( - StyleConstants.linear16, + 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, + ); + }, + ), + ], ), ), - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - Text( - 'Public key', - style: TextStyle( - color: Colors.black, - fontSize: 14.0, - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - width: 8.0, - ), - Icon( - Icons.copy, - size: 14.0, - ), - ], - ), - Text( - chainKeys.first.publicKey, - style: const TextStyle( - color: Colors.black87, - fontSize: 13.0, - fontWeight: FontWeight.w400, - ), + ), + const SizedBox(height: 8.0), + Row( + children: [ + Expanded( + child: Text( + version ?? '', + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 11.0), ), - ], - ), + ) + ], ), - const Expanded(child: SizedBox()), + const SizedBox(height: 8.0), Row( children: [ CustomButton( @@ -169,7 +109,6 @@ class _SettingsPageState extends State { widget: RecoverFromSeed(), ); if (mnemonic is String) { - debugPrint(mnemonic); await keysService.restoreWallet(mnemonic: mnemonic); setState(() {}); } @@ -186,27 +125,6 @@ class _SettingsPageState extends State { ), ], ), - // const SizedBox(height: 12.0), - // Row( - // children: [ - // CustomButton( - // type: CustomButtonType.normal, - // onTap: () async { - // await keysService.createWallet(); - // setState(() {}); - // }, - // child: const Center( - // child: Text( - // 'Restart account', - // style: TextStyle( - // color: Colors.white, - // fontWeight: FontWeight.bold, - // ), - // ), - // ), - // ), - // ], - // ), const SizedBox(height: 12.0), Row( children: [ @@ -233,3 +151,86 @@ class _SettingsPageState extends State { ); } } + +class _DataContainer extends StatefulWidget { + const _DataContainer({ + required this.title, + required this.data, + this.blurred = false, + }); + final String title; + final String data; + final bool blurred; + + @override + State<_DataContainer> createState() => __DataContainerState(); +} + +class __DataContainerState extends State<_DataContainer> { + late bool blurred; + + @override + void initState() { + super.initState(); + blurred = widget.blurred; + } + + @override + Widget build(BuildContext context) { + final blurValue = blurred ? 5.0 : 0.0; + return GestureDetector( + onTap: () => Clipboard.setData(ClipboardData(text: widget.data)).then( + (_) => showPlatformToast( + child: Text('${widget.title} copied'), + context: context, + ), + ), + onLongPress: () => setState(() { + blurred = false; + }), + onLongPressUp: () => setState(() { + blurred = widget.blurred; + }), + child: Container( + decoration: BoxDecoration( + color: StyleConstants.lightGray, + borderRadius: BorderRadius.circular( + StyleConstants.linear16, + ), + ), + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + widget.title, + style: const TextStyle( + color: Colors.black, + fontSize: 14.0, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 8.0), + const Icon(Icons.copy, size: 14.0), + ], + ), + ImageFiltered( + imageFilter: + ImageFilter.blur(sigmaX: blurValue, sigmaY: blurValue), + child: Text( + widget.data, + style: const TextStyle( + color: Colors.black87, + fontSize: 13.0, + fontWeight: FontWeight.w400, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/example/wallet/lib/widgets/pairing_item.dart b/example/wallet/lib/widgets/pairing_item.dart index b799b787..c9d29037 100644 --- a/example/wallet/lib/widgets/pairing_item.dart +++ b/example/wallet/lib/widgets/pairing_item.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_service.dart'; class PairingItem extends StatelessWidget { const PairingItem({ @@ -20,15 +22,12 @@ class PairingItem extends StatelessWidget { subtitle: Text('No metadata available'), ); } - - DateTime dateTime = - DateTime.fromMillisecondsSinceEpoch(pairing.expiry * 1000); - int year = dateTime.year; - int month = dateTime.month; - int day = dateTime.day; - - String expiryDate = - '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}'; + final sessions = GetIt.I() + .getWeb3Wallet() + .sessions + .getAll() + .where((element) => element.pairingTopic == pairing.topic) + .toList(); return ListTile( leading: CircleAvatar( @@ -41,17 +40,14 @@ class PairingItem extends StatelessWidget { metadata.name, style: const TextStyle(color: Colors.black), ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Expires on: $expiryDate', - style: const TextStyle( - color: Colors.grey, - fontSize: 12.0, - ), - ), - ], + subtitle: Text( + sessions.isEmpty + ? 'No active sessions' + : 'Active sessions: ${sessions.length}', + style: TextStyle( + color: sessions.isEmpty ? Colors.black : Colors.blueAccent, + fontSize: 13.0, + ), ), trailing: const Icon( Icons.arrow_forward_ios, diff --git a/example/wallet/lib/widgets/wc_connection_request/wc_connection_request_widget.dart b/example/wallet/lib/widgets/wc_connection_request/wc_connection_request_widget.dart index 47f3e8d4..cca9deeb 100644 --- a/example/wallet/lib/widgets/wc_connection_request/wc_connection_request_widget.dart +++ b/example/wallet/lib/widgets/wc_connection_request/wc_connection_request_widget.dart @@ -162,8 +162,8 @@ class VerifyHeader extends StatelessWidget { const SizedBox(width: StyleConstants.linear8), Text( title, - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: iconColor, fontWeight: FontWeight.bold, ), ), @@ -198,19 +198,23 @@ class VerifyBanner extends StatelessWidget { Container( padding: const EdgeInsets.all(8.0), decoration: BoxDecoration( - color: color, + color: color.withOpacity(0.2), borderRadius: const BorderRadius.all(Radius.circular(12.0)), ), child: Column( children: [ VerifyHeader( - iconColor: Colors.white, + iconColor: color, title: title, ), const SizedBox(height: 4.0), Text( text, - style: const TextStyle(color: Colors.white), + textAlign: TextAlign.center, + style: TextStyle( + color: color, + fontWeight: FontWeight.bold, + ), ), ], ), diff --git a/lib/apis/utils/extensions.dart b/lib/apis/utils/extensions.dart index fa855498..e5efa51e 100644 --- a/lib/apis/utils/extensions.dart +++ b/lib/apis/utils/extensions.dart @@ -1,3 +1,6 @@ +import 'dart:typed_data'; + +import 'package:convert/convert.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:web3dart/crypto.dart' as crypto; @@ -20,3 +23,50 @@ extension TransactionExtension on Transaction { }; } } + +extension TransactionExtension2 on Map { + Transaction toTransaction() { + return Transaction( + from: EthereumAddress.fromHex(this['from']), + to: EthereumAddress.fromHex(this['to']), + value: (this['value'] as String?).toEthereAmount(), + gasPrice: (this['gasPrice'] as String?).toEthereAmount(), + maxFeePerGas: (this['maxFeePerGas'] as String?).toEthereAmount(), + maxPriorityFeePerGas: + (this['maxPriorityFeePerGas'] as String?).toEthereAmount(), + maxGas: (this['maxGas'] as String?).toIntFromHex(), + nonce: (this['nonce'] as String?).toInt(), + data: (this['data'] != null && this['data'] != '0x') + ? Uint8List.fromList(hex.decode(this['data']!)) + : null, + ); + } +} + +extension EtheraAmountExtension on String? { + EtherAmount? toEthereAmount() { + if (this != null) { + final hexValue = this!.replaceFirst('0x', ''); + return EtherAmount.fromBigInt( + EtherUnit.wei, + BigInt.from(int.parse(hexValue, radix: 16)), + ); + } + return null; + } + + int? toIntFromHex() { + if (this != null) { + final hexValue = this!.replaceFirst('0x', ''); + return int.parse(hexValue, radix: 16); + } + return null; + } + + int? toInt() { + if (this != null) { + return int.tryParse(this!); + } + return null; + } +} diff --git a/lib/src/version.dart b/lib/src/version.dart index c79752e5..dec81e91 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '2.2.0-beta01'; +const packageVersion = '2.2.0-beta02'; diff --git a/lib/walletconnect_flutter_v2.dart b/lib/walletconnect_flutter_v2.dart index 0c4d6767..0164ce4d 100644 --- a/lib/walletconnect_flutter_v2.dart +++ b/lib/walletconnect_flutter_v2.dart @@ -58,3 +58,5 @@ export 'package:logger/logger.dart'; export 'package:shared_preferences/shared_preferences.dart'; export 'package:universal_io/io.dart'; export 'package:web3dart/web3dart.dart'; +export 'package:web3dart/crypto.dart'; +export 'package:web3dart/json_rpc.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index b319543a..5d0c9ca6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: walletconnect_flutter_v2 description: This repository contains oficial implementation of WalletConnect v2 protocols for Flutter applications. The communications protocol for web3. -version: 2.2.0-beta01 +version: 2.2.0-beta02 repository: https://github.com/WalletConnect/WalletConnectFlutterV2 environment: