From 310bedc367321755a2d57cbb153fe14078936431 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 11 Apr 2024 11:02:02 +0200 Subject: [PATCH] Enhancements on loading states --- .../lib/dependencies/chains/evm_service.dart | 27 +-- .../lib/dependencies/deep_link_handler.dart | 23 ++- .../lib/dependencies/web3wallet_service.dart | 162 +++++++++++------- example/wallet/lib/pages/app_detail_page.dart | 1 + example/wallet/lib/pages/apps_page.dart | 50 +++--- .../lib/utils/namespace_model_builder.dart | 12 +- example/wallet/lib/widgets/pairing_item.dart | 17 +- lib/apis/core/core.dart | 3 - lib/apis/core/relay_client/relay_client.dart | 13 +- lib/apis/sign_api/sign_engine.dart | 1 - lib/walletconnect_flutter_v2.dart | 1 + 11 files changed, 179 insertions(+), 131 deletions(-) diff --git a/example/wallet/lib/dependencies/chains/evm_service.dart b/example/wallet/lib/dependencies/chains/evm_service.dart index 9f78702c..cb882db4 100644 --- a/example/wallet/lib/dependencies/chains/evm_service.dart +++ b/example/wallet/lib/dependencies/chains/evm_service.dart @@ -27,20 +27,20 @@ class EVMService { late final Web3Client ethClient; Map get sessionRequestHandlers => { - 'personal_sign': personalSign, - }; - - Map get methodRequestHandlers => { - 'personal_sign': personalSign, + // 'personal_sign': personalSign, 'eth_sign': ethSign, 'eth_signTransaction': ethSignTransaction, - 'eth_sendTransaction': ethSendTransaction, 'eth_signTypedData': ethSignTypedData, 'eth_signTypedData_v4': ethSignTypedDataV4, 'wallet_switchEthereumChain': switchChain, 'wallet_addEthereumChain': addChain, }; + Map get methodRequestHandlers => { + 'personal_sign': personalSign, + 'eth_sendTransaction': ethSendTransaction, + }; + EVMService({required this.chainSupported}) { final supportedId = chainSupported.chainId; final chainMetadata = ChainData.allChains.firstWhere( @@ -55,6 +55,13 @@ class EVMService { ); } + for (var handler in sessionRequestHandlers.entries) { + _web3Wallet.registerRequestHandler( + chainId: chainSupported.chainId, + method: handler.key, + handler: handler.value, + ); + } for (var handler in methodRequestHandlers.entries) { _web3Wallet.registerRequestHandler( chainId: chainSupported.chainId, @@ -67,8 +74,8 @@ class EVMService { } void _onSessionRequest(SessionRequestEvent? args) async { - debugPrint('[WALLET] _onSessionRequest ${args?.toString()}'); if (args != null && args.chainId == chainSupported.chainId) { + debugPrint('[WALLET] _onSessionRequest ${args.toString()}'); final handler = sessionRequestHandlers[args.method]; if (handler != null) { await handler(args.topic, args.params); @@ -79,7 +86,6 @@ class EVMService { // personal_sign is handled using onSessionRequest event for demo purposes Future personalSign(String topic, dynamic parameters) async { debugPrint('[WALLET] personalSign request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getDataFromParamsList(parameters); final message = EthUtils.getUtf8Message(data.toString()); @@ -123,7 +129,6 @@ class EVMService { Future ethSign(String topic, dynamic parameters) async { debugPrint('[WALLET] ethSign request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getDataFromParamsList(parameters); final message = EthUtils.getUtf8Message(data.toString()); @@ -167,7 +172,6 @@ class EVMService { Future ethSignTypedData(String topic, dynamic parameters) async { debugPrint('[WALLET] ethSignTypedData request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getDataFromParamsList(parameters); var response = JsonRpcResponse( @@ -209,7 +213,6 @@ class EVMService { Future ethSignTypedDataV4(String topic, dynamic parameters) async { debugPrint('[WALLET] ethSignTypedDataV4 request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getDataFromParamsList(parameters); var response = JsonRpcResponse( @@ -251,7 +254,6 @@ class EVMService { Future ethSignTransaction(String topic, dynamic parameters) async { debugPrint('[WALLET] ethSignTransaction request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getTransactionFromParams(parameters); if (data == null) return; @@ -305,7 +307,6 @@ class EVMService { Future ethSendTransaction(String topic, dynamic parameters) async { debugPrint('[WALLET] ethSendTransaction request: $parameters'); - DeepLinkHandler.waiting.value = true; final pRequest = _web3Wallet.pendingRequests.getAll().last; final data = EthUtils.getTransactionFromParams(parameters); if (data == null) return; diff --git a/example/wallet/lib/dependencies/deep_link_handler.dart b/example/wallet/lib/dependencies/deep_link_handler.dart index e716a8b4..496aafca 100644 --- a/example/wallet/lib/dependencies/deep_link_handler.dart +++ b/example/wallet/lib/dependencies/deep_link_handler.dart @@ -44,18 +44,17 @@ class DeepLinkHandler { waiting.value = false; if (scheme.isEmpty) return; await Future.delayed(Duration(milliseconds: delay)); - launchUrlString(scheme, mode: LaunchMode.externalApplication).catchError( - (e) { - debugPrint( - '[WALLET] [DeepLinkHandler] error re-opening dapp ($scheme). $e'); - _goBackModal( - title: modalTitle, - message: modalMessage, - success: success, - ); - return true; - }, - ); + try { + await launchUrlString(scheme, mode: LaunchMode.externalApplication); + } catch (e) { + debugPrint( + '[WALLET] [DeepLinkHandler] error re-opening dapp ($scheme). $e'); + _goBackModal( + title: modalTitle, + message: modalMessage, + success: success, + ); + } } static void _onLink(Object? event) { diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index df4ac322..446dd8ba 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; import 'package:eth_sig_util/eth_sig_util.dart'; @@ -22,6 +23,20 @@ class Web3WalletService extends IWeb3WalletService { final _bottomSheetHandler = GetIt.I(); Web3Wallet? _web3Wallet; + static final supportedMethods = { + 'eth_sign', + 'eth_signTransaction', + 'eth_signTypedData', + 'eth_signTypedData_v4', + 'wallet_switchEthereumChain', + 'wallet_addEthereumChain', + }; + + static final requiredMethods = { + 'personal_sign', + 'eth_sendTransaction', + }; + @override void create() async { // Create the web3wallet @@ -77,7 +92,6 @@ class Web3WalletService extends IWeb3WalletService { debugPrint('[WALLET] [$runtimeType] create'); _web3Wallet!.core.pairing.onPairingInvalid.subscribe(_onPairingInvalid); _web3Wallet!.core.pairing.onPairingCreate.subscribe(_onPairingCreate); - _web3Wallet!.pairings.onSync.subscribe(_onPairingsSync); _web3Wallet!.onSessionProposal.subscribe(_onSessionProposal); _web3Wallet!.onSessionProposalError.subscribe(_onSessionProposalError); _web3Wallet!.onAuthRequest.subscribe(_onAuthRequest); @@ -100,7 +114,7 @@ class Web3WalletService extends IWeb3WalletService { FutureOr onDispose() { debugPrint('[$runtimeType] [WALLET] dispose'); _web3Wallet!.core.pairing.onPairingInvalid.unsubscribe(_onPairingInvalid); - _web3Wallet!.pairings.onSync.unsubscribe(_onPairingsSync); + _web3Wallet!.core.pairing.onPairingCreate.unsubscribe(_onPairingCreate); _web3Wallet!.onSessionProposal.unsubscribe(_onSessionProposal); _web3Wallet!.onSessionProposalError.unsubscribe(_onSessionProposalError); _web3Wallet!.onAuthRequest.unsubscribe(_onAuthRequest); @@ -115,57 +129,15 @@ class Web3WalletService extends IWeb3WalletService { @override Web3Wallet get web3wallet => _web3Wallet!; - void _onPairingsSync(StoreSyncEvent? args) { - debugPrint('[$runtimeType] [WALLET] _onPairingsSync'); - } - - void _onSessionProposalError(SessionProposalErrorEvent? args) async { - debugPrint('[$runtimeType] [WALLET] _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), - ], - ), - ), - ); - } - } - Map _generateNamespaces( Map? approvedNamespaces, ChainType chainType, ) { - // final constructedNS = Map.from(approvedNamespaces ?? {}); constructedNS[chainType.name] = constructedNS[chainType.name]!.copyWith( methods: [ - 'personal_sign', ...constructedNS[chainType.name]!.methods, + ...supportedMethods, ], ); return constructedNS; @@ -183,6 +155,7 @@ class Web3WalletService extends IWeb3WalletService { final proposalData = args.params.copyWith( generatedNamespaces: approvedNS, ); + debugPrint('[WALLET] proposalData $proposalData'); final approved = await _bottomSheetHandler.queueBottomSheet( widget: WCRequestWidget( child: WCConnectionRequestWidget( @@ -195,17 +168,17 @@ class Web3WalletService extends IWeb3WalletService { ), ); - final scheme = args.params.proposer.metadata.redirect?.native ?? ''; - if (approved == true) { await _web3Wallet!.approveSession(id: args.id, namespaces: approvedNS); - DeepLinkHandler.goTo(scheme); } else { final error = Errors.getSdkError(Errors.USER_REJECTED); await _web3Wallet!.rejectSession(id: args.id, reason: error); - // await _web3Wallet!.core.pairing.disconnect( - // topic: args.params.pairingTopic, - // ); + await _web3Wallet!.core.pairing.disconnect( + topic: args.params.pairingTopic, + ); + + // TODO this should be triggered on _onRelayClientMessage + final scheme = args.params.proposer.metadata.redirect?.native ?? ''; DeepLinkHandler.goTo( scheme, modalTitle: 'Error', @@ -216,10 +189,77 @@ class Web3WalletService extends IWeb3WalletService { } } - void _onRelayClientMessage(MessageEvent? args) { - debugPrint( - '[$runtimeType] [WALLET] _onRelayClientMessage ${args.toString()}', - ); + void _onSessionProposalError(SessionProposalErrorEvent? args) async { + debugPrint('[$runtimeType] [WALLET] _onSessionProposalError $args'); + DeepLinkHandler.waiting.value = false; + 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 _onRelayClientMessage(MessageEvent? args) async { + debugPrint('[$runtimeType] [WALLET] _onRelayClientMessage $args'); + if (args != null) { + final payloadString = await _web3Wallet!.core.crypto.decode( + args.topic, + args.message, + ); + if (payloadString == null) return; + + final data = jsonDecode(payloadString); + if (data.containsKey('method')) { + final request = JsonRpcRequest.fromJson(data); + debugPrint('[$runtimeType] [WALLET] _onRelayClientMessage $request'); + if (request.method != 'wc_sessionDelete' && + request.method != 'wc_pairingDelete') { + DeepLinkHandler.waiting.value = true; + } + } else { + final response = JsonRpcResponse.fromJson(data); + debugPrint('[$runtimeType] [WALLET] _onRelayClientMessage $response'); + // REDIRECT BACK TO DAPP + final session = _web3Wallet!.sessions.get(args.topic); + final scheme = session?.peer.metadata.redirect?.native ?? ''; + DeepLinkHandler.goTo( + scheme, + modalTitle: response.result != null ? null : 'Error', + modalMessage: response.result != null + ? null + : response.error?.message ?? 'Error', + success: response.result != null, + ); + } + } } void _onRelayClientError(ErrorEvent? args) { @@ -261,14 +301,6 @@ class Web3WalletService extends IWeb3WalletService { ), ); - // EthPrivateKey credentials = - // EthPrivateKey.fromHex(chainKeys.first.privateKey); - // final String sig = utf8.decode( - // credentials.signPersonalMessageToUint8List( - // Uint8List.fromList(message.codeUnits), - // ), - // ); - final String sig = EthSigUtil.signPersonalMessage( message: Uint8List.fromList(message.codeUnits), privateKey: chainKeys.first.privateKey, @@ -286,9 +318,7 @@ class Web3WalletService extends IWeb3WalletService { await _web3Wallet!.respondAuthRequest( id: args.id, iss: iss, - error: Errors.getSdkError( - Errors.USER_REJECTED_AUTH, - ), + error: Errors.getSdkError(Errors.USER_REJECTED_AUTH), ); } } diff --git a/example/wallet/lib/pages/app_detail_page.dart b/example/wallet/lib/pages/app_detail_page.dart index a1202a50..af5bc3eb 100644 --- a/example/wallet/lib/pages/app_detail_page.dart +++ b/example/wallet/lib/pages/app_detail_page.dart @@ -66,6 +66,7 @@ class AppDetailPageState extends State { final namespaceWidget = ConnectionWidgetBuilder.buildFromNamespaces( session.topic, session.namespaces, + context, ); // Loop through and add the namespace widgets, but put 20 pixels between each one for (int i = 0; i < namespaceWidget.length; i++) { diff --git a/example/wallet/lib/pages/apps_page.dart b/example/wallet/lib/pages/apps_page.dart index 9f20f57d..1fb24919 100644 --- a/example/wallet/lib/pages/apps_page.dart +++ b/example/wallet/lib/pages/apps_page.dart @@ -32,28 +32,48 @@ class AppsPageState extends State with GetItStateMixin { _web3Wallet = _web3walletService.web3wallet; _pairings = _web3Wallet.pairings.getAll(); _pairings = _pairings.where((p) => p.active).toList(); - _web3Wallet.core.relayClient.onRelayClientMessage.subscribe(_updateState); - _web3Wallet.onSessionProposal.subscribe(_updateState); - _web3Wallet.onSessionProposalError.subscribe(_updateState); - _web3Wallet.onSessionDelete.subscribe(_updateState); + // + _registerListeners(); // TODO web3Wallet.core.echo.register(firebaseAccessToken); DeepLinkHandler.onLink.listen(_onFoundUri); DeepLinkHandler.checkInitialLink(); } + void _registerListeners() { + _web3Wallet.core.relayClient.onRelayClientMessage.subscribe( + _refreshState, + ); + _web3Wallet.pairings.onSync.subscribe(_refreshState); + _web3Wallet.pairings.onUpdate.subscribe(_refreshState); + _web3Wallet.onSessionConnect.subscribe(_refreshState); + _web3Wallet.onSessionDelete.subscribe(_refreshState); + } + + void _unregisterListeners() { + _web3Wallet.onSessionDelete.unsubscribe(_refreshState); + _web3Wallet.onSessionConnect.unsubscribe(_refreshState); + _web3Wallet.pairings.onSync.unsubscribe(_refreshState); + _web3Wallet.pairings.onUpdate.unsubscribe(_refreshState); + _web3Wallet.core.relayClient.onRelayClientMessage.unsubscribe( + _refreshState, + ); + } + @override void dispose() { - _web3Wallet.onSessionProposal.unsubscribe(_updateState); - _web3Wallet.onSessionProposalError.unsubscribe(_updateState); - _web3Wallet.onSessionDelete.unsubscribe(_updateState); - _web3Wallet.core.relayClient.onRelayClientMessage.unsubscribe(_updateState); + _unregisterListeners(); super.dispose(); } + void _refreshState(dynamic event) { + debugPrint('[WALLET] [$runtimeType] $event'); + setState(() {}); + } + @override Widget build(BuildContext context) { - // _pairings = (watch(target: GetIt.I().pairings)); - // _pairings = _pairings.where((p) => p.active).toList(); + _pairings = _web3Wallet.pairings.getAll(); + _pairings = _pairings.where((p) => p.active).toList(); return Stack( children: [ _pairings.isEmpty ? _buildNoPairingMessage() : _buildPairingList(), @@ -192,16 +212,6 @@ class AppsPageState extends State with GetItStateMixin { } } - void _updateState(dynamic event) { - setState(() { - if (event is SessionProposalEvent) { - DeepLinkHandler.waiting.value = true; - } - _pairings = _web3Wallet.pairings.getAll(); - _pairings = _pairings.where((p) => p.active).toList(); - }); - } - void _onListItemTap(PairingInfo pairing) { Navigator.push( context, diff --git a/example/wallet/lib/utils/namespace_model_builder.dart b/example/wallet/lib/utils/namespace_model_builder.dart index 6d252be4..508270c1 100644 --- a/example/wallet/lib/utils/namespace_model_builder.dart +++ b/example/wallet/lib/utils/namespace_model_builder.dart @@ -1,3 +1,5 @@ +import 'package:fl_toast/fl_toast.dart'; +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'; @@ -48,6 +50,7 @@ class ConnectionWidgetBuilder { static List buildFromNamespaces( String topic, Map namespaces, + BuildContext context, ) { final List views = []; for (final key in namespaces.keys) { @@ -70,9 +73,7 @@ class ConnectionWidgetBuilder { Map actions = {}; for (final String event in ns.events) { actions[event] = () async { - final String chainId = NamespaceUtils.isValidChainId(key) - ? key - : NamespaceUtils.getChainFromAccount(ns.accounts.first); + final chainId = NamespaceUtils.getChainFromAccount(ns.accounts.first); await GetIt.I().web3wallet.emitSessionEvent( topic: topic, chainId: chainId, @@ -81,6 +82,11 @@ class ConnectionWidgetBuilder { data: 'Event: $event', ), ); + showPlatformToast( + child: Text('Event $event sent to dapp'), + // ignore: use_build_context_synchronously + context: context, + ); }; } models.add( diff --git a/example/wallet/lib/widgets/pairing_item.dart b/example/wallet/lib/widgets/pairing_item.dart index d4e0066a..7195ff3c 100644 --- a/example/wallet/lib/widgets/pairing_item.dart +++ b/example/wallet/lib/widgets/pairing_item.dart @@ -1,6 +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/deep_link_handler.dart'; import 'package:walletconnect_flutter_v2_wallet/dependencies/i_web3wallet_service.dart'; class PairingItem extends StatelessWidget { @@ -42,11 +43,25 @@ class PairingItem extends StatelessWidget { ), subtitle: Text( sessions.isEmpty + // ? DeepLinkHandler.waiting.value + // ? 'Settling session. Wait...' + // : 'No active sessions' ? 'No active sessions' : 'Active sessions: ${sessions.length}', style: TextStyle( - color: sessions.isEmpty ? Colors.black : Colors.blueAccent, + color: sessions.isEmpty + // ? DeepLinkHandler.waiting.value + // ? Colors.green + // : Colors.black + ? Colors.black + : Colors.blueAccent, fontSize: 13.0, + fontWeight: sessions.isEmpty + // ? DeepLinkHandler.waiting.value + // ? FontWeight.bold + // : FontWeight.normal + ? FontWeight.normal + : FontWeight.bold, ), ), trailing: const Icon( diff --git a/lib/apis/core/core.dart b/lib/apis/core/core.dart index 226eb5ab..13766119 100644 --- a/lib/apis/core/core.dart +++ b/lib/apis/core/core.dart @@ -88,9 +88,6 @@ class Core implements ICore { level: logLevel.toLevel(), printer: PrettyPrinter(), ); - Logger.addLogListener( - (LogEvent event) => print('LOGGER: ${event.message}'), - ); heartbeat = HeartBeat(); storage = SharedPrefsStores( memoryStore: memoryStore, diff --git a/lib/apis/core/relay_client/relay_client.dart b/lib/apis/core/relay_client/relay_client.dart index 7a8006d3..8e482da8 100644 --- a/lib/apis/core/relay_client/relay_client.dart +++ b/lib/apis/core/relay_client/relay_client.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:event/event.dart'; -// import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto_models.dart'; import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/json_rpc_utils.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/i_message_tracker.dart'; @@ -372,21 +371,11 @@ class RelayClient implements IRelayClient { // Record a message event await messageTracker.recordMessageEvent(topic, message); - // final pairing = core.pairing.getPairing(topic: topic); - // Decode the message - // final payloadString = await core.crypto.decode( - // topic, - // message, - // options: DecodeOptions( - // receiverPublicKey: receiverPublicKey?.publicKey, - // ), - // ); - // Broadcast the message onRelayClientMessage.broadcast( MessageEvent( topic, - message, // TODO parse message + message, ), ); return true; diff --git a/lib/apis/sign_api/sign_engine.dart b/lib/apis/sign_api/sign_engine.dart index e0acba34..af421359 100644 --- a/lib/apis/sign_api/sign_engine.dart +++ b/lib/apis/sign_api/sign_engine.dart @@ -5,7 +5,6 @@ import 'package:http/http.dart' as http; import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/json_rpc_utils.dart'; import 'package:walletconnect_flutter_v2/apis/core/store/i_generic_store.dart'; import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; -import 'package:walletconnect_flutter_v2/apis/models/json_rpc_request.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/i_sessions.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/utils/custom_credentials.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/utils/sign_api_validator_utils.dart'; diff --git a/lib/walletconnect_flutter_v2.dart b/lib/walletconnect_flutter_v2.dart index 0164ce4d..2a5a1b50 100644 --- a/lib/walletconnect_flutter_v2.dart +++ b/lib/walletconnect_flutter_v2.dart @@ -14,6 +14,7 @@ export 'apis/utils/errors.dart'; export 'apis/utils/walletconnect_utils.dart'; export 'apis/models/json_rpc_error.dart'; export 'apis/models/json_rpc_response.dart'; +export 'apis/models/json_rpc_request.dart'; export 'apis/utils/constants.dart'; export 'apis/models/uri_parse_result.dart'; export 'apis/utils/method_constants.dart';