diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f081ee..9123cd6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -## 2.3.0-beta03 +## 2.3.0-beta04 - One-Click Auth support +- Bug fixes ## 2.2.3 diff --git a/example/dapp/lib/main.dart b/example/dapp/lib/main.dart index 802e6827..2e8398b9 100644 --- a/example/dapp/lib/main.dart +++ b/example/dapp/lib/main.dart @@ -58,9 +58,10 @@ class _MyHomePageState extends State { } Future initialize() async { - _web3App = await Web3App.createInstance( - projectId: DartDefines.projectId, - logLevel: LogLevel.error, + _web3App = Web3App( + core: Core( + projectId: DartDefines.projectId, + ), metadata: const PairingMetadata( name: 'Sample dApp Flutter', description: 'WalletConnect\'s sample dapp with Flutter', @@ -75,19 +76,12 @@ class _MyHomePageState extends State { ), ); - // Loop through all the chain data - for (final ChainMetadata chain in ChainData.allChains) { - // Loop through the events for that chain - for (final event in getChainEvents(chain.type)) { - _web3App!.registerEventHandler( - chainId: chain.chainId, - event: event, - ); - } - } + _web3App!.core.addLogListener(_logListener); // Register event handlers - _web3App!.core.addLogListener(_logListener); + _web3App!.core.relayClient.onRelayClientError.subscribe( + _relayClientError, + ); _web3App!.core.relayClient.onRelayClientConnect.subscribe(_setState); _web3App!.core.relayClient.onRelayClientDisconnect.subscribe(_setState); _web3App!.core.relayClient.onRelayClientMessage.subscribe( @@ -100,6 +94,19 @@ class _MyHomePageState extends State { _web3App!.onSessionConnect.subscribe(_onSessionConnect); _web3App!.onSessionAuthResponse.subscribe(_onSessionAuthResponse); + await _web3App!.init(); + + // Loop through all the chain data + for (final ChainMetadata chain in ChainData.allChains) { + // Loop through the events for that chain + for (final event in getChainEvents(chain.type)) { + _web3App!.registerEventHandler( + chainId: chain.chainId, + event: event, + ); + } + } + setState(() { _pageDatas = [ PageData( @@ -138,10 +145,34 @@ class _MyHomePageState extends State { void _setState(dynamic args) => setState(() {}); + void _relayClientError(ErrorEvent? event) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: Text(event?.error.toString() ?? 'Relay Client error'), + actions: [ + TextButton( + onPressed: () { + _web3App!.core.relayClient.connect(); + Navigator.of(context).pop(); + }, + child: const Text('RETRY'), + ), + ], + ); + }, + ); + } + @override void dispose() { // Unregister event handlers _web3App!.core.removeLogListener(_logListener); + + _web3App!.core.relayClient.onRelayClientError.unsubscribe( + _relayClientError, + ); _web3App!.core.relayClient.onRelayClientConnect.unsubscribe(_setState); _web3App!.core.relayClient.onRelayClientDisconnect.unsubscribe(_setState); _web3App!.core.relayClient.onRelayClientMessage.unsubscribe( @@ -158,9 +189,11 @@ class _MyHomePageState extends State { } void _logListener(LogEvent event) { - debugPrint('[Logger] ${event.level.name}: ${event.message}'); - if (event.level == Level.error) { + if (event.level == Level.debug) { // TODO send to mixpanel + log('[Mixpanel] ${event.message}'); + } else { + debugPrint('[Logger] ${event.level.name}: ${event.message}'); } } diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index 210ee07e..bb6f6e71 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -27,9 +27,10 @@ class Web3WalletService extends IWeb3WalletService { @override Future create() async { // Create the web3wallet - _web3Wallet = await Web3Wallet.createInstance( - projectId: DartDefines.projectId, - logLevel: LogLevel.error, + _web3Wallet = Web3Wallet( + core: Core( + projectId: DartDefines.projectId, + ), metadata: const PairingMetadata( name: 'Sample Wallet Flutter', description: 'WalletConnect\'s sample wallet with Flutter', @@ -44,6 +45,28 @@ class Web3WalletService extends IWeb3WalletService { ), ); + _web3Wallet!.core.addLogListener(_logListener); + + // Setup our listeners + debugPrint('[SampleWallet] create'); + _web3Wallet!.core.pairing.onPairingInvalid.subscribe(_onPairingInvalid); + _web3Wallet!.core.pairing.onPairingCreate.subscribe(_onPairingCreate); + _web3Wallet!.core.relayClient.onRelayClientError.subscribe( + _onRelayClientError, + ); + _web3Wallet!.core.relayClient.onRelayClientMessage.subscribe( + _onRelayClientMessage, + ); + + _web3Wallet!.onSessionProposal.subscribe(_onSessionProposal); + _web3Wallet!.onSessionProposalError.subscribe(_onSessionProposalError); + _web3Wallet!.onSessionConnect.subscribe(_onSessionConnect); + _web3Wallet!.onSessionAuthRequest.subscribe(_onSessionAuthRequest); + + _web3Wallet!.onAuthRequest.subscribe(_onAuthRequest); + + await _web3Wallet!.init(); + // Setup our accounts List chainKeys = await GetIt.I().setKeys(); if (chainKeys.isEmpty) { @@ -69,25 +92,6 @@ class Web3WalletService extends IWeb3WalletService { } } } - - // Setup our listeners - debugPrint('[SampleWallet] create'); - _web3Wallet!.core.addLogListener(_logListener); - _web3Wallet!.core.pairing.onPairingInvalid.subscribe(_onPairingInvalid); - _web3Wallet!.core.pairing.onPairingCreate.subscribe(_onPairingCreate); - _web3Wallet!.core.relayClient.onRelayClientError.subscribe( - _onRelayClientError, - ); - _web3Wallet!.core.relayClient.onRelayClientMessage.subscribe( - _onRelayClientMessage, - ); - - _web3Wallet!.onSessionProposal.subscribe(_onSessionProposal); - _web3Wallet!.onSessionProposalError.subscribe(_onSessionProposalError); - _web3Wallet!.onSessionConnect.subscribe(_onSessionConnect); - _web3Wallet!.onSessionAuthRequest.subscribe(_onSessionAuthRequest); - - _web3Wallet!.onAuthRequest.subscribe(_onAuthRequest); } @override diff --git a/lib/apis/core/relay_client/relay_client.dart b/lib/apis/core/relay_client/relay_client.dart index 8e482da8..943de875 100644 --- a/lib/apis/core/relay_client/relay_client.dart +++ b/lib/apis/core/relay_client/relay_client.dart @@ -187,33 +187,33 @@ class RelayClient implements IRelayClient { /// PRIVATE FUNCTIONS /// Future _connect({String? relayUrl}) async { - core.logger.t('RelayClient Internal: Connecting to relay'); if (isConnected) { return; } + core.relayUrl = relayUrl ?? core.relayUrl; + core.logger.d('[$runtimeType] Connecting to relay ${core.relayUrl}'); + // If we have tried connecting to the relay before, disconnect if (_active) { await _disconnect(); } - // Connect and track the connection progress, then start the heartbeat - _connectingFuture = _createJsonRPCProvider(); - await _connectingFuture; - _subscribeToHeartbeat(); - - // If it didn't connect, and the relayUrl is the default, - // recursively try the fallback - core.relayUrl = relayUrl ?? core.relayUrl; - if (!isConnected && - core.relayUrl == WalletConnectConstants.DEFAULT_RELAY_URL) { - core.relayUrl = WalletConnectConstants.FALLBACK_RELAY_URL; - await _connect(); - - // If we still didn't connect, reset the relayUrl to the default - if (!isConnected) { - core.relayUrl = WalletConnectConstants.DEFAULT_RELAY_URL; - } + try { + // Connect and track the connection progress, then start the heartbeat + _connectingFuture = _createJsonRPCProvider(); + await _connectingFuture; + _connecting = false; + _subscribeToHeartbeat(); + // + } on TimeoutException catch (e) { + core.logger.d('[$runtimeType] Connect timeout: $e'); + onRelayClientError.broadcast(ErrorEvent('Connection to relay timeout')); + _connecting = false; + } catch (e) { + core.logger.d('[$runtimeType] Connect error: $e'); + onRelayClientError.broadcast(ErrorEvent(e)); + _connecting = false; } } @@ -238,66 +238,62 @@ class RelayClient implements IRelayClient { _active = true; final auth = await core.crypto.signJWT(core.relayUrl); core.logger.t('Signed JWT: $auth'); - try { - final url = WalletConnectUtils.formatRelayRpcUrl( - protocol: WalletConnectConstants.CORE_PROTOCOL, - version: WalletConnectConstants.CORE_VERSION, - relayUrl: core.relayUrl, - sdkVersion: WalletConnectConstants.SDK_VERSION, - auth: auth, - projectId: core.projectId, - packageName: (await WalletConnectUtils.getPackageName()), - ); + final url = WalletConnectUtils.formatRelayRpcUrl( + protocol: WalletConnectConstants.CORE_PROTOCOL, + version: WalletConnectConstants.CORE_VERSION, + relayUrl: core.relayUrl, + sdkVersion: WalletConnectConstants.SDK_VERSION, + auth: auth, + projectId: core.projectId, + packageName: (await WalletConnectUtils.getPackageName()), + ); - if (jsonRPC != null) { - await jsonRPC!.close(); - jsonRPC = null; - } + if (jsonRPC != null) { + await jsonRPC!.close(); + jsonRPC = null; + } - core.logger.t('Initializing WebSocket with $url'); - await socketHandler.setup(url: url); - await socketHandler.connect(); + core.logger.t('Initializing WebSocket with $url'); + await socketHandler.setup(url: url); + await socketHandler.connect().timeout(Duration(seconds: 5)); - jsonRPC = Peer(socketHandler.channel!); + jsonRPC = Peer(socketHandler.channel!); - jsonRPC!.registerMethod( - _buildMethod(JSON_RPC_SUBSCRIPTION), - _handleSubscription, - ); - jsonRPC!.registerMethod( - _buildMethod(JSON_RPC_SUBSCRIBE), - _handleSubscribe, - ); - jsonRPC!.registerMethod( - _buildMethod(JSON_RPC_UNSUBSCRIBE), - _handleUnsubscribe, - ); + jsonRPC!.registerMethod( + _buildMethod(JSON_RPC_SUBSCRIPTION), + _handleSubscription, + ); + jsonRPC!.registerMethod( + _buildMethod(JSON_RPC_SUBSCRIBE), + _handleSubscribe, + ); + jsonRPC!.registerMethod( + _buildMethod(JSON_RPC_UNSUBSCRIBE), + _handleUnsubscribe, + ); - if (jsonRPC!.isClosed) { - throw const WalletConnectError( - code: 0, - message: 'WebSocket closed', - ); - } + if (jsonRPC!.isClosed) { + throw const WalletConnectError( + code: 0, + message: 'WebSocket closed', + ); + } - jsonRPC!.listen(); + jsonRPC!.listen(); - // When jsonRPC closes, emit the event - _handledClose = false; - jsonRPC!.done.then( - (value) { - _handleRelayClose( - socketHandler.closeCode, - socketHandler.closeReason, - ); - }, - ); + // When jsonRPC closes, emit the event + _handledClose = false; + jsonRPC!.done.then( + (value) { + _handleRelayClose( + socketHandler.closeCode, + socketHandler.closeReason, + ); + }, + ); - onRelayClientConnect.broadcast(); - } catch (e) { - onRelayClientError.broadcast(ErrorEvent(e)); - } - _connecting = false; + onRelayClientConnect.broadcast(); + core.logger.d('[$runtimeType] Connected to relay ${core.relayUrl}'); } Future _handleRelayClose(int? code, String? reason) async { diff --git a/lib/apis/core/verify/verify.dart b/lib/apis/core/verify/verify.dart index 0538c4de..23610d66 100644 --- a/lib/apis/core/verify/verify.dart +++ b/lib/apis/core/verify/verify.dart @@ -27,48 +27,23 @@ class Verify implements IVerify { @override Future resolve({required String attestationId}) async { - AttestationResponse? response; try { - response = await _fetchAttestation(attestationId, _verifyUrl); - } on AttestationNotFound catch (e) { - _core.logger.i(e.message); - response = await _fetchAttestation( - attestationId, - WalletConnectConstants.VERIFY_FALLBACK_SERVER, - ); - } on Exception catch (error) { - _core.logger.e(error); - response = await _fetchAttestation( - attestationId, - WalletConnectConstants.VERIFY_FALLBACK_SERVER, - ); - } - return response; - } - - Future _fetchAttestation( - String attestationId, - String url, - ) async { - final uri = Uri.parse('$url/attestation/$attestationId'); - final response = await _httpClient.get(uri); - if (response.statusCode == 404) { - throw AttestationNotFound( - code: 404, - message: 'Attestion for this dapp could not be found', - ); - } - if (response.statusCode != 200) { - final error = 'Attestation response error: ${response.statusCode}'; - throw Exception(error); - } - if (response.body.isEmpty) { - throw AttestationNotFound( - code: 404, - message: 'Attestion for this dapp could not be found', - ); + final uri = Uri.parse('$_verifyUrl/attestation/$attestationId'); + final response = await _httpClient.get(uri).timeout(Duration(seconds: 5)); + if (response.statusCode == 404 || response.body.isEmpty) { + throw AttestationNotFound( + code: 404, + message: 'Attestion for this dapp could not be found', + ); + } + if (response.statusCode != 200) { + throw Exception('Attestation response error: ${response.statusCode}'); + } + return AttestationResponse.fromJson(jsonDecode(response.body)); + } catch (e) { + _core.logger.d('[$runtimeType] resolve $e'); + rethrow; } - return AttestationResponse.fromJson(jsonDecode(response.body)); } String _setVerifyUrl({String? verifyUrl}) { diff --git a/lib/apis/sign_api/i_sign_client.dart b/lib/apis/sign_api/i_sign_client.dart index b8482cd9..b0dc519a 100644 --- a/lib/apis/sign_api/i_sign_client.dart +++ b/lib/apis/sign_api/i_sign_client.dart @@ -98,6 +98,7 @@ abstract class ISignClient { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }); Future requestWriteContract({ diff --git a/lib/apis/sign_api/i_sign_engine_app.dart b/lib/apis/sign_api/i_sign_engine_app.dart index c7ced660..05b1ffe8 100644 --- a/lib/apis/sign_api/i_sign_engine_app.dart +++ b/lib/apis/sign_api/i_sign_engine_app.dart @@ -27,6 +27,7 @@ abstract class ISignEngineApp extends ISignEngineCommon { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }); Future requestWriteContract({ diff --git a/lib/apis/sign_api/sign_client.dart b/lib/apis/sign_api/sign_client.dart index 6b939421..fba5a520 100644 --- a/lib/apis/sign_api/sign_client.dart +++ b/lib/apis/sign_api/sign_client.dart @@ -292,10 +292,12 @@ class SignClient implements ISignClient { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }) async { try { return await engine.requestReadContract( + sender: sender, deployedContract: deployedContract, functionName: functionName, rpcUrl: rpcUrl, diff --git a/lib/apis/sign_api/sign_engine.dart b/lib/apis/sign_api/sign_engine.dart index d4a40ddc..ac6e2910 100644 --- a/lib/apis/sign_api/sign_engine.dart +++ b/lib/apis/sign_api/sign_engine.dart @@ -522,10 +522,12 @@ class SignEngine implements ISignEngine { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }) async { try { final results = await Web3Client(rpcUrl, http.Client()).call( + sender: sender, contract: deployedContract, function: deployedContract.function(functionName), params: parameters, diff --git a/lib/apis/sign_api/utils/auth/auth_constants.dart b/lib/apis/sign_api/utils/auth/auth_constants.dart index cdddca3e..5508dcda 100644 --- a/lib/apis/sign_api/utils/auth/auth_constants.dart +++ b/lib/apis/sign_api/utils/auth/auth_constants.dart @@ -4,7 +4,7 @@ class AuthConstants { static const AUTH_REQUEST_EXPIRY_MIN = WalletConnectConstants.FIVE_MINUTES; static const AUTH_REQUEST_EXPIRY_MAX = WalletConnectConstants.SEVEN_DAYS; - static const AUTH_DEFAULT_URL = 'https://rpc.walletconnect.com/v1'; + static const AUTH_DEFAULT_URL = 'https://rpc.walletconnect.org/v1'; static const AUTH_PROTOCOL = 'wc'; static const AUTH_VERSION = 1.5; diff --git a/lib/apis/utils/constants.dart b/lib/apis/utils/constants.dart index 77e148e3..f757db30 100644 --- a/lib/apis/utils/constants.dart +++ b/lib/apis/utils/constants.dart @@ -7,8 +7,7 @@ class WalletConnectConstants { static const CORE_VERSION = 2; static const CORE_CONTEXT = 'core'; - static const DEFAULT_RELAY_URL = 'wss://relay.walletconnect.com'; - static const FALLBACK_RELAY_URL = 'wss://relay.walletconnect.org'; + static const DEFAULT_RELAY_URL = 'wss://relay.walletconnect.org'; static const CORE_STORAGE_PREFIX = '$CORE_PROTOCOL@$CORE_VERSION:$CORE_CONTEXT:'; @@ -23,11 +22,10 @@ class WalletConnectConstants { static const RELAYER_DEFAULT_PROTOCOL = 'irn'; - static const DEFAULT_PUSH_URL = 'https://echo.walletconnect.com'; + static const DEFAULT_PUSH_URL = 'https://echo.walletconnect.org'; - static const VERIFY_SERVER = 'https://verify.walletconnect.com'; - static const VERIFY_FALLBACK_SERVER = 'https://verify.walletconnect.org'; - static const TRUSTED_VERIFY_URLS = [VERIFY_SERVER, VERIFY_FALLBACK_SERVER]; + static const VERIFY_SERVER = 'https://verify.walletconnect.org'; + static const TRUSTED_VERIFY_URLS = [VERIFY_SERVER]; } class StoreVersions { diff --git a/lib/apis/web3app/web3app.dart b/lib/apis/web3app/web3app.dart index 28be6cb8..a0523310 100644 --- a/lib/apis/web3app/web3app.dart +++ b/lib/apis/web3app/web3app.dart @@ -227,10 +227,12 @@ class Web3App implements IWeb3App { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }) async { try { return await signEngine.requestReadContract( + sender: sender, deployedContract: deployedContract, functionName: functionName, rpcUrl: rpcUrl, diff --git a/lib/src/version.dart b/lib/src/version.dart index f367dc72..002d4142 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '2.3.0-beta03'; +const packageVersion = '2.3.0-beta04'; diff --git a/pubspec.yaml b/pubspec.yaml index 14bc6fb9..c9355529 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.0-beta03 +version: 2.3.0-beta04 repository: https://github.com/WalletConnect/WalletConnectFlutterV2 environment: diff --git a/test/core_api/core_test.dart b/test/core_api/core_test.dart index 5f155f82..77f352ac 100644 --- a/test/core_api/core_test.dart +++ b/test/core_api/core_test.dart @@ -42,7 +42,7 @@ void main() { }); await core.start(); - expect(errorCount, 2); + expect(errorCount, 1); expect(core.relayUrl, WalletConnectConstants.DEFAULT_RELAY_URL); verifyInOrder([ @@ -55,15 +55,6 @@ void main() { ), ), mockWebSocketHandler.connect(), - mockWebSocketHandler.setup( - url: argThat( - contains( - WalletConnectConstants.FALLBACK_RELAY_URL, - ), - named: 'url', - ), - ), - mockWebSocketHandler.connect(), ]); core.relayClient.onRelayClientError.unsubscribeAll(); diff --git a/test/core_api/relay_client_test.dart b/test/core_api/relay_client_test.dart index d8cc8446..bbefcaf3 100644 --- a/test/core_api/relay_client_test.dart +++ b/test/core_api/relay_client_test.dart @@ -27,11 +27,11 @@ void main() { test('relays are correct', () { expect( WalletConnectConstants.DEFAULT_RELAY_URL, - 'wss://relay.walletconnect.com', + 'wss://relay.walletconnect.org', ); expect( WalletConnectConstants.DEFAULT_PUSH_URL, - 'https://echo.walletconnect.com', + 'https://echo.walletconnect.org', ); }); diff --git a/test/shared/shared_test_values.dart b/test/shared/shared_test_values.dart index 320e9e06..772cf906 100644 --- a/test/shared/shared_test_values.dart +++ b/test/shared/shared_test_values.dart @@ -3,7 +3,7 @@ import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; const TEST_RELAY_URL = String.fromEnvironment( 'RELAY_ENDPOINT', - defaultValue: 'wss://relay.walletconnect.com', + defaultValue: 'wss://relay.walletconnect.org', ); const TEST_PROJECT_ID = String.fromEnvironment( 'PROJECT_ID', diff --git a/test/sign_api/utils/sign_client_test_wrapper.dart b/test/sign_api/utils/sign_client_test_wrapper.dart index 11f74f0c..cc8074ef 100644 --- a/test/sign_api/utils/sign_client_test_wrapper.dart +++ b/test/sign_api/utils/sign_client_test_wrapper.dart @@ -223,10 +223,12 @@ class SignClientTestWrapper implements ISignEngine { required DeployedContract deployedContract, required String functionName, required String rpcUrl, + EthereumAddress? sender, List parameters = const [], }) async { try { return await client.requestReadContract( + sender: sender, deployedContract: deployedContract, functionName: functionName, rpcUrl: rpcUrl,