From 16007ccd54ac619cc692716b41f3bfeb89699fb5 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Thu, 26 Oct 2023 11:22:40 +0200 Subject: [PATCH 1/4] first steps --- lib/apis/core/core.dart | 11 +++ lib/apis/core/i_core.dart | 2 + lib/apis/core/verify/i_verify.dart | 40 +++++++++++ lib/apis/core/verify/verify.dart | 106 +++++++++++++++++++++++++++++ lib/apis/utils/constants.dart | 7 +- 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 lib/apis/core/verify/i_verify.dart create mode 100644 lib/apis/core/verify/verify.dart diff --git a/lib/apis/core/core.dart b/lib/apis/core/core.dart index 23f8fc24..1aa3e904 100644 --- a/lib/apis/core/core.dart +++ b/lib/apis/core/core.dart @@ -23,6 +23,8 @@ import 'package:walletconnect_flutter_v2/apis/core/store/i_store.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/i_relay_client.dart'; import 'package:walletconnect_flutter_v2/apis/core/pairing/i_pairing.dart'; import 'package:walletconnect_flutter_v2/apis/core/store/shared_prefs_store.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/verify.dart'; import 'package:walletconnect_flutter_v2/apis/utils/constants.dart'; import 'package:walletconnect_flutter_v2/apis/utils/log_level.dart'; import 'package:walletconnect_flutter_v2/apis/utils/walletconnect_utils.dart'; @@ -60,6 +62,9 @@ class Core implements ICore { @override late IHeartBeat heartbeat; + @override + late IVerify verify; + Logger _logger = Logger( level: Level.off, printer: PrettyPrinter(), @@ -150,6 +155,11 @@ class Core implements ICore { httpClient: httpClient, ), ); + verify = Verify( + core: this, + projectId: projectId, + httpClient: httpClient, + ); } @override @@ -159,6 +169,7 @@ class Core implements ICore { await relayClient.init(); await expirer.init(); await pairing.init(); + await verify.init(); heartbeat.init(); } } diff --git a/lib/apis/core/i_core.dart b/lib/apis/core/i_core.dart index 07bbac17..b713ad22 100644 --- a/lib/apis/core/i_core.dart +++ b/lib/apis/core/i_core.dart @@ -6,6 +6,7 @@ import 'package:walletconnect_flutter_v2/apis/core/pairing/i_expirer.dart'; import 'package:walletconnect_flutter_v2/apis/core/pairing/i_pairing.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/i_relay_client.dart'; import 'package:walletconnect_flutter_v2/apis/core/store/i_store.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart'; abstract class ICore { final String protocol = 'wc'; @@ -24,6 +25,7 @@ abstract class ICore { abstract IPairing pairing; abstract IEcho echo; abstract final Logger logger; + abstract IVerify verify; Future start(); } diff --git a/lib/apis/core/verify/i_verify.dart b/lib/apis/core/verify/i_verify.dart new file mode 100644 index 00000000..cff66343 --- /dev/null +++ b/lib/apis/core/verify/i_verify.dart @@ -0,0 +1,40 @@ +enum Validation { + UNKNOWN, + VALID, + INVALID, +} + +class VerifyResult { + String origin; + Validation validation; + String verifyUrl; + bool? isScam; + + VerifyResult({ + required this.origin, + required this.validation, + required this.verifyUrl, + }); +} + +abstract class IVerify { + // public abstract readonly context: string; + // abstract String context; + + // constructor(public projectId: string, public logger: Logger) {} + // IVerify({required String projectId}); + + // public abstract init(params?: { verifyUrl?: string }): Promise; + Future init({String? verifyUrl}); + + // public abstract register(params: { attestationId: string }): Promise; + Future register({required String attestationId}); + + // public abstract resolve(params: { + // attestationId: string; + // verifyUrl?: string; + // }): Promise<{ origin: string; isScam?: boolean }>; + Future resolve({required String attestationId}); + + // String getVerifyUrl({String? verifyUrl}); +} diff --git a/lib/apis/core/verify/verify.dart b/lib/apis/core/verify/verify.dart new file mode 100644 index 00000000..3fb52609 --- /dev/null +++ b/lib/apis/core/verify/verify.dart @@ -0,0 +1,106 @@ +import 'package:flutter/foundation.dart'; +import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; +import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/i_http_client.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart'; +import 'package:walletconnect_flutter_v2/apis/utils/constants.dart'; + +class Verify implements IVerify { + final ICore _core; + final IHttpClient _httpClient; + + String name = WalletConnectConstants.VERIFY_CONTEXT; + String? _verifyUrl; + bool _initialized = false; + // private isDevEnv; + // the queue is only used during the loading phase of the iframe to ensure all attestations are posted + List _queue = []; + // flag to disable verify when the iframe fails to load on main & fallback urls. + // this means Verify API is not enabled for the current projectId and there's no point in trying to initialize it again. + bool _verifyDisabled = false; + + Verify({ + required ICore core, + required String projectId, + required IHttpClient httpClient, + }) : _core = core, + _httpClient = httpClient; + + @override + Future init({String? verifyUrl}) async { + if (_verifyDisabled) { + return; + } + + _verifyUrl = _getVerifyUrl(verifyUrl: verifyUrl); + } + + @override + Future register({required String attestationId}) async { + if (!_initialized) { + _queue.add(attestationId); + await init(); + } else { + // this.sendPost(params.attestationId); + } + } + + @override + Future resolve({required String attestationId}) async { + VerifyResult verifyResult = VerifyResult( + origin: '', + validation: Validation.VALID, + verifyUrl: '', + ); + if (kDebugMode) { + return verifyResult; + } + + final vurl = _getVerifyUrl(); + try { + final result = await _fetchAttestation(attestationId, vurl); + debugPrint('result $result'); + // TODO set verifyResult + } catch (error) { + _core.logger.e( + 'failed to resolve attestation: $attestationId from url: $vurl', + ); + _core.logger.e(error); + final result = await _fetchAttestation( + attestationId, + WalletConnectConstants.VERIFY_FALLBACK_SERVER, + ); + debugPrint('result $result'); + // TODO set verifyResult + } + return verifyResult; + } + + Future _fetchAttestation(String attestationId, String url) async { + _core.logger.i('resolving attestation: $attestationId from url: $url'); + // set artificial timeout to prevent hanging + await Future.delayed(const Duration(seconds: 2)); + // const timeout = this.startAbortTimer(ONE_SECOND * 2); + // const result = await fetch(`${url}/attestation/${attestationId}`, { + // signal: this.abortController.signal, + // }); + final uri = Uri.parse('$url/attestation/$attestationId'); + final response = await _httpClient.get(uri); + // clearTimeout(timeout); + // return result.status === 200 ? await result.json() : undefined; + if (response.statusCode == 200) { + return response.body; + } + return null; + } + + String _getVerifyUrl({String? verifyUrl}) { + String url = + (verifyUrl ?? _verifyUrl) ?? WalletConnectConstants.VERIFY_SERVER; + if (!WalletConnectConstants.TRUSTED_VERIFY_URLS.contains(url)) { + _core.logger.i( + 'verify url: $url, not included in trusted list, assigning default: ${WalletConnectConstants.VERIFY_SERVER}'); + url = WalletConnectConstants.VERIFY_SERVER; + } + return url; + } +} diff --git a/lib/apis/utils/constants.dart b/lib/apis/utils/constants.dart index 3c09d31d..8b65651a 100644 --- a/lib/apis/utils/constants.dart +++ b/lib/apis/utils/constants.dart @@ -1,5 +1,5 @@ class WalletConnectConstants { - static const SDK_VERSION = '2.1.5'; + static const SDK_VERSION = '2.1.6'; static const CORE_PROTOCOL = 'wc'; static const CORE_VERSION = 2; @@ -22,6 +22,11 @@ class WalletConnectConstants { static const RELAYER_DEFAULT_PROTOCOL = 'irn'; static const DEFAULT_PUSH_URL = 'https://echo.walletconnect.com'; + + static const VERIFY_CONTEXT = 'verify-api'; + 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]; } class StoreVersions { From 3199a123852223d99433a4aed0a1e48e3227ea6c Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Fri, 3 Nov 2023 17:53:10 +0100 Subject: [PATCH 2/4] Verify API implementation --- CHANGELOG.md | 4 + example/dapp/lib/pages/connect_page.dart | 2 +- .../lib/dependencies/web3wallet_service.dart | 4 +- .../wc_connection_request_widget.dart | 134 +++++- .../wc_session_request_model.dart | 5 +- lib/apis/core/core.dart | 9 +- .../core/pairing/utils/pairing_models.dart | 1 + .../pairing/utils/pairing_models.freezed.dart | 25 +- .../core/pairing/utils/pairing_models.g.dart | 2 + lib/apis/core/verify/i_verify.dart | 37 +- .../core/verify/models/verify_context.dart | 43 ++ .../verify/models/verify_context.freezed.dart | 388 ++++++++++++++++++ .../core/verify/models/verify_context.g.dart | 46 +++ lib/apis/core/verify/verify.dart | 88 ++-- lib/apis/sign_api/models/session_models.dart | 2 + .../models/session_models.freezed.dart | 56 ++- .../sign_api/models/session_models.g.dart | 3 + .../sign_api/models/sign_client_events.dart | 12 +- lib/apis/sign_api/sign_engine.dart | 67 ++- lib/apis/utils/constants.dart | 2 +- lib/src/version.dart | 2 +- pubspec.yaml | 3 +- test/shared/shared_test_utils.mocks.dart | 312 +++++++------- 23 files changed, 968 insertions(+), 279 deletions(-) create mode 100644 lib/apis/core/verify/models/verify_context.dart create mode 100644 lib/apis/core/verify/models/verify_context.freezed.dart create mode 100644 lib/apis/core/verify/models/verify_context.g.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 97ac9487..fea3c0bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.9 + +- Added support for Verify API + ## 2.1.8 - Minor changes. diff --git a/example/dapp/lib/pages/connect_page.dart b/example/dapp/lib/pages/connect_page.dart index 9940b946..a8b0462f 100644 --- a/example/dapp/lib/pages/connect_page.dart +++ b/example/dapp/lib/pages/connect_page.dart @@ -184,7 +184,7 @@ class ConnectPageState extends State { // Send off a connect debugPrint('Creating connection and session'); final ConnectResponse res = await widget.web3App.connect( - requiredNamespaces: requiredNamespaces, + optionalNamespaces: requiredNamespaces, ); // debugPrint('Connection created, connection response: ${res.uri}'); diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index 46684df7..4ad40cca 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -36,7 +36,7 @@ class Web3WalletService extends IWeb3WalletService { @override void create() { -// Create the web3wallet + // Create the web3wallet _web3Wallet = Web3Wallet( core: Core( projectId: DartDefines.projectId, @@ -49,6 +49,7 @@ class Web3WalletService extends IWeb3WalletService { icons: [ 'https://github.com/WalletConnect/Web3ModalFlutter/blob/master/assets/png/logo_wc.png' ], + // verifyUrl: 'https://your_verify_url.here', ), ); @@ -137,6 +138,7 @@ class Web3WalletService extends IWeb3WalletService { wallet: _web3Wallet!, sessionProposal: WCSessionRequestModel( request: args.params, + verifyContext: args.verifyContext, ), ), ); 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 1ba7488a..690cee63 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 @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/constants.dart'; import 'package:walletconnect_flutter_v2_wallet/utils/namespace_model_builder.dart'; @@ -49,10 +50,8 @@ class WCConnectionRequestWidget extends StatelessWidget { textAlign: TextAlign.center, ), const SizedBox(height: StyleConstants.linear8), - Text( - metadata.metadata.url, - style: StyleConstants.bodyText, - textAlign: TextAlign.center, + VerifyContextWidget( + verifyContext: sessionProposal?.verifyContext, ), const SizedBox(height: StyleConstants.linear8), authRequest != null @@ -109,3 +108,130 @@ class WCConnectionRequestWidget extends StatelessWidget { // ); } } + +class VerifyContextWidget extends StatelessWidget { + const VerifyContextWidget({ + super.key, + required this.verifyContext, + }); + final VerifyContext? verifyContext; + + @override + Widget build(BuildContext context) { + if (verifyContext == null) { + return const SizedBox.shrink(); + } + + if (verifyContext!.validation.scam) { + return VerifyBanner( + color: StyleConstants.errorColor, + origin: verifyContext!.origin, + title: 'Security risk', + text: 'This domain is flagged as unsafe by multiple security providers.' + ' Leave immediately to protect your assets.', + ); + } + if (verifyContext!.validation.invalid) { + return VerifyBanner( + color: StyleConstants.errorColor, + origin: verifyContext!.origin, + title: 'Domain mismatch', + text: + 'This website has a domain that does not match the sender of this request.' + ' Approving may lead to loss of funds.', + ); + } + if (verifyContext!.validation.valid) { + return VerifyHeader( + iconColor: StyleConstants.successColor, + title: verifyContext!.origin, + ); + } + return VerifyBanner( + color: Colors.orange, + origin: verifyContext!.origin, + title: 'Cannot verify', + text: 'This domain cannot be verified. ' + 'Check the request carefully before approving.', + ); + } +} + +class VerifyHeader extends StatelessWidget { + const VerifyHeader({ + super.key, + required this.iconColor, + required this.title, + }); + final Color iconColor; + final String title; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.shield_outlined, + color: iconColor, + ), + const SizedBox(width: StyleConstants.linear8), + Text( + title, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ); + } +} + +class VerifyBanner extends StatelessWidget { + const VerifyBanner({ + super.key, + required this.origin, + required this.title, + required this.text, + required this.color, + }); + final String origin, title, text; + final Color color; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text( + origin, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox.square(dimension: 8.0), + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: color, + borderRadius: const BorderRadius.all(Radius.circular(12.0)), + ), + child: Column( + children: [ + VerifyHeader( + iconColor: Colors.white, + title: title, + ), + const SizedBox(height: 4.0), + Text( + text, + style: const TextStyle(color: Colors.white), + ), + ], + ), + ), + ], + ); + } +} diff --git a/example/wallet/lib/widgets/wc_connection_request/wc_session_request_model.dart b/example/wallet/lib/widgets/wc_connection_request/wc_session_request_model.dart index 22a205ea..5afd07a2 100644 --- a/example/wallet/lib/widgets/wc_connection_request/wc_session_request_model.dart +++ b/example/wallet/lib/widgets/wc_connection_request/wc_session_request_model.dart @@ -1,11 +1,12 @@ +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; class WCSessionRequestModel { - // final List accounts; final ProposalData request; + final VerifyContext? verifyContext; WCSessionRequestModel({ - // required this.accounts, required this.request, + this.verifyContext, }); } diff --git a/lib/apis/core/core.dart b/lib/apis/core/core.dart index 1aa3e904..13766119 100644 --- a/lib/apis/core/core.dart +++ b/lib/apis/core/core.dart @@ -36,13 +36,13 @@ class Core implements ICore { String get version => '2'; @override - String relayUrl = WalletConnectConstants.DEFAULT_RELAY_URL; + final String projectId; @override - final String projectId; + String relayUrl = WalletConnectConstants.DEFAULT_RELAY_URL; @override - final String pushUrl; + String pushUrl = WalletConnectConstants.DEFAULT_PUSH_URL; @override late ICrypto crypto; @@ -76,8 +76,8 @@ class Core implements ICore { late IStore> storage; Core({ - this.relayUrl = WalletConnectConstants.DEFAULT_RELAY_URL, required this.projectId, + this.relayUrl = WalletConnectConstants.DEFAULT_RELAY_URL, this.pushUrl = WalletConnectConstants.DEFAULT_PUSH_URL, bool memoryStore = false, LogLevel logLevel = LogLevel.nothing, @@ -169,7 +169,6 @@ class Core implements ICore { await relayClient.init(); await expirer.init(); await pairing.init(); - await verify.init(); heartbeat.init(); } } diff --git a/lib/apis/core/pairing/utils/pairing_models.dart b/lib/apis/core/pairing/utils/pairing_models.dart index b40dd442..d7fda7ef 100644 --- a/lib/apis/core/pairing/utils/pairing_models.dart +++ b/lib/apis/core/pairing/utils/pairing_models.dart @@ -36,6 +36,7 @@ class PairingMetadata with _$PairingMetadata { required String description, required String url, required List icons, + String? verifyUrl, Redirect? redirect, }) = _PairingMetadata; diff --git a/lib/apis/core/pairing/utils/pairing_models.freezed.dart b/lib/apis/core/pairing/utils/pairing_models.freezed.dart index 4a9e590b..3e953958 100644 --- a/lib/apis/core/pairing/utils/pairing_models.freezed.dart +++ b/lib/apis/core/pairing/utils/pairing_models.freezed.dart @@ -264,6 +264,7 @@ mixin _$PairingMetadata { String get description => throw _privateConstructorUsedError; String get url => throw _privateConstructorUsedError; List get icons => throw _privateConstructorUsedError; + String? get verifyUrl => throw _privateConstructorUsedError; Redirect? get redirect => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @@ -283,6 +284,7 @@ abstract class $PairingMetadataCopyWith<$Res> { String description, String url, List icons, + String? verifyUrl, Redirect? redirect}); $RedirectCopyWith<$Res>? get redirect; @@ -305,6 +307,7 @@ class _$PairingMetadataCopyWithImpl<$Res, $Val extends PairingMetadata> Object? description = null, Object? url = null, Object? icons = null, + Object? verifyUrl = freezed, Object? redirect = freezed, }) { return _then(_value.copyWith( @@ -324,6 +327,10 @@ class _$PairingMetadataCopyWithImpl<$Res, $Val extends PairingMetadata> ? _value.icons : icons // ignore: cast_nullable_to_non_nullable as List, + verifyUrl: freezed == verifyUrl + ? _value.verifyUrl + : verifyUrl // ignore: cast_nullable_to_non_nullable + as String?, redirect: freezed == redirect ? _value.redirect : redirect // ignore: cast_nullable_to_non_nullable @@ -357,6 +364,7 @@ abstract class _$$_PairingMetadataCopyWith<$Res> String description, String url, List icons, + String? verifyUrl, Redirect? redirect}); @override @@ -378,6 +386,7 @@ class __$$_PairingMetadataCopyWithImpl<$Res> Object? description = null, Object? url = null, Object? icons = null, + Object? verifyUrl = freezed, Object? redirect = freezed, }) { return _then(_$_PairingMetadata( @@ -397,6 +406,10 @@ class __$$_PairingMetadataCopyWithImpl<$Res> ? _value._icons : icons // ignore: cast_nullable_to_non_nullable as List, + verifyUrl: freezed == verifyUrl + ? _value.verifyUrl + : verifyUrl // ignore: cast_nullable_to_non_nullable + as String?, redirect: freezed == redirect ? _value.redirect : redirect // ignore: cast_nullable_to_non_nullable @@ -414,6 +427,7 @@ class _$_PairingMetadata implements _PairingMetadata { required this.description, required this.url, required final List icons, + this.verifyUrl, this.redirect}) : _icons = icons; @@ -434,12 +448,14 @@ class _$_PairingMetadata implements _PairingMetadata { return EqualUnmodifiableListView(_icons); } + @override + final String? verifyUrl; @override final Redirect? redirect; @override String toString() { - return 'PairingMetadata(name: $name, description: $description, url: $url, icons: $icons, redirect: $redirect)'; + return 'PairingMetadata(name: $name, description: $description, url: $url, icons: $icons, verifyUrl: $verifyUrl, redirect: $redirect)'; } @override @@ -452,6 +468,8 @@ class _$_PairingMetadata implements _PairingMetadata { other.description == description) && (identical(other.url, url) || other.url == url) && const DeepCollectionEquality().equals(other._icons, _icons) && + (identical(other.verifyUrl, verifyUrl) || + other.verifyUrl == verifyUrl) && (identical(other.redirect, redirect) || other.redirect == redirect)); } @@ -459,7 +477,7 @@ class _$_PairingMetadata implements _PairingMetadata { @JsonKey(ignore: true) @override int get hashCode => Object.hash(runtimeType, name, description, url, - const DeepCollectionEquality().hash(_icons), redirect); + const DeepCollectionEquality().hash(_icons), verifyUrl, redirect); @JsonKey(ignore: true) @override @@ -481,6 +499,7 @@ abstract class _PairingMetadata implements PairingMetadata { required final String description, required final String url, required final List icons, + final String? verifyUrl, final Redirect? redirect}) = _$_PairingMetadata; factory _PairingMetadata.fromJson(Map json) = @@ -495,6 +514,8 @@ abstract class _PairingMetadata implements PairingMetadata { @override List get icons; @override + String? get verifyUrl; + @override Redirect? get redirect; @override @JsonKey(ignore: true) diff --git a/lib/apis/core/pairing/utils/pairing_models.g.dart b/lib/apis/core/pairing/utils/pairing_models.g.dart index faeb9314..f7cbd239 100644 --- a/lib/apis/core/pairing/utils/pairing_models.g.dart +++ b/lib/apis/core/pairing/utils/pairing_models.g.dart @@ -33,6 +33,7 @@ _$_PairingMetadata _$$_PairingMetadataFromJson(Map json) => description: json['description'] as String, url: json['url'] as String, icons: (json['icons'] as List).map((e) => e as String).toList(), + verifyUrl: json['verifyUrl'] as String?, redirect: json['redirect'] == null ? null : Redirect.fromJson(json['redirect'] as Map), @@ -52,6 +53,7 @@ Map _$$_PairingMetadataToJson(_$_PairingMetadata instance) { } } + writeNotNull('verifyUrl', instance.verifyUrl); writeNotNull('redirect', instance.redirect?.toJson()); return val; } diff --git a/lib/apis/core/verify/i_verify.dart b/lib/apis/core/verify/i_verify.dart index cff66343..83d30080 100644 --- a/lib/apis/core/verify/i_verify.dart +++ b/lib/apis/core/verify/i_verify.dart @@ -1,40 +1,7 @@ -enum Validation { - UNKNOWN, - VALID, - INVALID, -} - -class VerifyResult { - String origin; - Validation validation; - String verifyUrl; - bool? isScam; - - VerifyResult({ - required this.origin, - required this.validation, - required this.verifyUrl, - }); -} +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; abstract class IVerify { - // public abstract readonly context: string; - // abstract String context; - - // constructor(public projectId: string, public logger: Logger) {} - // IVerify({required String projectId}); - - // public abstract init(params?: { verifyUrl?: string }): Promise; Future init({String? verifyUrl}); - // public abstract register(params: { attestationId: string }): Promise; - Future register({required String attestationId}); - - // public abstract resolve(params: { - // attestationId: string; - // verifyUrl?: string; - // }): Promise<{ origin: string; isScam?: boolean }>; - Future resolve({required String attestationId}); - - // String getVerifyUrl({String? verifyUrl}); + Future resolve({required String attestationId}); } diff --git a/lib/apis/core/verify/models/verify_context.dart b/lib/apis/core/verify/models/verify_context.dart new file mode 100644 index 00000000..173bdb86 --- /dev/null +++ b/lib/apis/core/verify/models/verify_context.dart @@ -0,0 +1,43 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'verify_context.g.dart'; +part 'verify_context.freezed.dart'; + +enum Validation { + UNKNOWN, + VALID, + INVALID, + SCAM; + + bool get invalid => this == INVALID; + bool get valid => this == VALID; + bool get unknown => this == UNKNOWN; + bool get scam => this == SCAM; +} + +@freezed +class VerifyContext with _$VerifyContext { + @JsonSerializable() + const factory VerifyContext({ + required String origin, + required Validation validation, + required String verifyUrl, + bool? isScam, + }) = _VerifyContext; + + factory VerifyContext.fromJson(Map json) => + _$VerifyContextFromJson(json); +} + +@freezed +class AttestationResponse with _$AttestationResponse { + @JsonSerializable() + const factory AttestationResponse({ + required String origin, + required String attestationId, + bool? isScam, + }) = _AttestationResponse; + + factory AttestationResponse.fromJson(Map json) => + _$AttestationResponseFromJson(json); +} diff --git a/lib/apis/core/verify/models/verify_context.freezed.dart b/lib/apis/core/verify/models/verify_context.freezed.dart new file mode 100644 index 00000000..985355f3 --- /dev/null +++ b/lib/apis/core/verify/models/verify_context.freezed.dart @@ -0,0 +1,388 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'verify_context.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +VerifyContext _$VerifyContextFromJson(Map json) { + return _VerifyContext.fromJson(json); +} + +/// @nodoc +mixin _$VerifyContext { + String get origin => throw _privateConstructorUsedError; + Validation get validation => throw _privateConstructorUsedError; + String get verifyUrl => throw _privateConstructorUsedError; + bool? get isScam => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $VerifyContextCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $VerifyContextCopyWith<$Res> { + factory $VerifyContextCopyWith( + VerifyContext value, $Res Function(VerifyContext) then) = + _$VerifyContextCopyWithImpl<$Res, VerifyContext>; + @useResult + $Res call( + {String origin, Validation validation, String verifyUrl, bool? isScam}); +} + +/// @nodoc +class _$VerifyContextCopyWithImpl<$Res, $Val extends VerifyContext> + implements $VerifyContextCopyWith<$Res> { + _$VerifyContextCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? origin = null, + Object? validation = null, + Object? verifyUrl = null, + Object? isScam = freezed, + }) { + return _then(_value.copyWith( + origin: null == origin + ? _value.origin + : origin // ignore: cast_nullable_to_non_nullable + as String, + validation: null == validation + ? _value.validation + : validation // ignore: cast_nullable_to_non_nullable + as Validation, + verifyUrl: null == verifyUrl + ? _value.verifyUrl + : verifyUrl // ignore: cast_nullable_to_non_nullable + as String, + isScam: freezed == isScam + ? _value.isScam + : isScam // ignore: cast_nullable_to_non_nullable + as bool?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_VerifyContextCopyWith<$Res> + implements $VerifyContextCopyWith<$Res> { + factory _$$_VerifyContextCopyWith( + _$_VerifyContext value, $Res Function(_$_VerifyContext) then) = + __$$_VerifyContextCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String origin, Validation validation, String verifyUrl, bool? isScam}); +} + +/// @nodoc +class __$$_VerifyContextCopyWithImpl<$Res> + extends _$VerifyContextCopyWithImpl<$Res, _$_VerifyContext> + implements _$$_VerifyContextCopyWith<$Res> { + __$$_VerifyContextCopyWithImpl( + _$_VerifyContext _value, $Res Function(_$_VerifyContext) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? origin = null, + Object? validation = null, + Object? verifyUrl = null, + Object? isScam = freezed, + }) { + return _then(_$_VerifyContext( + origin: null == origin + ? _value.origin + : origin // ignore: cast_nullable_to_non_nullable + as String, + validation: null == validation + ? _value.validation + : validation // ignore: cast_nullable_to_non_nullable + as Validation, + verifyUrl: null == verifyUrl + ? _value.verifyUrl + : verifyUrl // ignore: cast_nullable_to_non_nullable + as String, + isScam: freezed == isScam + ? _value.isScam + : isScam // ignore: cast_nullable_to_non_nullable + as bool?, + )); + } +} + +/// @nodoc + +@JsonSerializable() +class _$_VerifyContext implements _VerifyContext { + const _$_VerifyContext( + {required this.origin, + required this.validation, + required this.verifyUrl, + this.isScam}); + + factory _$_VerifyContext.fromJson(Map json) => + _$$_VerifyContextFromJson(json); + + @override + final String origin; + @override + final Validation validation; + @override + final String verifyUrl; + @override + final bool? isScam; + + @override + String toString() { + return 'VerifyContext(origin: $origin, validation: $validation, verifyUrl: $verifyUrl, isScam: $isScam)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_VerifyContext && + (identical(other.origin, origin) || other.origin == origin) && + (identical(other.validation, validation) || + other.validation == validation) && + (identical(other.verifyUrl, verifyUrl) || + other.verifyUrl == verifyUrl) && + (identical(other.isScam, isScam) || other.isScam == isScam)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, origin, validation, verifyUrl, isScam); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_VerifyContextCopyWith<_$_VerifyContext> get copyWith => + __$$_VerifyContextCopyWithImpl<_$_VerifyContext>(this, _$identity); + + @override + Map toJson() { + return _$$_VerifyContextToJson( + this, + ); + } +} + +abstract class _VerifyContext implements VerifyContext { + const factory _VerifyContext( + {required final String origin, + required final Validation validation, + required final String verifyUrl, + final bool? isScam}) = _$_VerifyContext; + + factory _VerifyContext.fromJson(Map json) = + _$_VerifyContext.fromJson; + + @override + String get origin; + @override + Validation get validation; + @override + String get verifyUrl; + @override + bool? get isScam; + @override + @JsonKey(ignore: true) + _$$_VerifyContextCopyWith<_$_VerifyContext> get copyWith => + throw _privateConstructorUsedError; +} + +AttestationResponse _$AttestationResponseFromJson(Map json) { + return _AttestationResponse.fromJson(json); +} + +/// @nodoc +mixin _$AttestationResponse { + String get origin => throw _privateConstructorUsedError; + String get attestationId => throw _privateConstructorUsedError; + bool? get isScam => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $AttestationResponseCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AttestationResponseCopyWith<$Res> { + factory $AttestationResponseCopyWith( + AttestationResponse value, $Res Function(AttestationResponse) then) = + _$AttestationResponseCopyWithImpl<$Res, AttestationResponse>; + @useResult + $Res call({String origin, String attestationId, bool? isScam}); +} + +/// @nodoc +class _$AttestationResponseCopyWithImpl<$Res, $Val extends AttestationResponse> + implements $AttestationResponseCopyWith<$Res> { + _$AttestationResponseCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? origin = null, + Object? attestationId = null, + Object? isScam = freezed, + }) { + return _then(_value.copyWith( + origin: null == origin + ? _value.origin + : origin // ignore: cast_nullable_to_non_nullable + as String, + attestationId: null == attestationId + ? _value.attestationId + : attestationId // ignore: cast_nullable_to_non_nullable + as String, + isScam: freezed == isScam + ? _value.isScam + : isScam // ignore: cast_nullable_to_non_nullable + as bool?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_AttestationResponseCopyWith<$Res> + implements $AttestationResponseCopyWith<$Res> { + factory _$$_AttestationResponseCopyWith(_$_AttestationResponse value, + $Res Function(_$_AttestationResponse) then) = + __$$_AttestationResponseCopyWithImpl<$Res>; + @override + @useResult + $Res call({String origin, String attestationId, bool? isScam}); +} + +/// @nodoc +class __$$_AttestationResponseCopyWithImpl<$Res> + extends _$AttestationResponseCopyWithImpl<$Res, _$_AttestationResponse> + implements _$$_AttestationResponseCopyWith<$Res> { + __$$_AttestationResponseCopyWithImpl(_$_AttestationResponse _value, + $Res Function(_$_AttestationResponse) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? origin = null, + Object? attestationId = null, + Object? isScam = freezed, + }) { + return _then(_$_AttestationResponse( + origin: null == origin + ? _value.origin + : origin // ignore: cast_nullable_to_non_nullable + as String, + attestationId: null == attestationId + ? _value.attestationId + : attestationId // ignore: cast_nullable_to_non_nullable + as String, + isScam: freezed == isScam + ? _value.isScam + : isScam // ignore: cast_nullable_to_non_nullable + as bool?, + )); + } +} + +/// @nodoc + +@JsonSerializable() +class _$_AttestationResponse implements _AttestationResponse { + const _$_AttestationResponse( + {required this.origin, required this.attestationId, this.isScam}); + + factory _$_AttestationResponse.fromJson(Map json) => + _$$_AttestationResponseFromJson(json); + + @override + final String origin; + @override + final String attestationId; + @override + final bool? isScam; + + @override + String toString() { + return 'AttestationResponse(origin: $origin, attestationId: $attestationId, isScam: $isScam)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_AttestationResponse && + (identical(other.origin, origin) || other.origin == origin) && + (identical(other.attestationId, attestationId) || + other.attestationId == attestationId) && + (identical(other.isScam, isScam) || other.isScam == isScam)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, origin, attestationId, isScam); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_AttestationResponseCopyWith<_$_AttestationResponse> get copyWith => + __$$_AttestationResponseCopyWithImpl<_$_AttestationResponse>( + this, _$identity); + + @override + Map toJson() { + return _$$_AttestationResponseToJson( + this, + ); + } +} + +abstract class _AttestationResponse implements AttestationResponse { + const factory _AttestationResponse( + {required final String origin, + required final String attestationId, + final bool? isScam}) = _$_AttestationResponse; + + factory _AttestationResponse.fromJson(Map json) = + _$_AttestationResponse.fromJson; + + @override + String get origin; + @override + String get attestationId; + @override + bool? get isScam; + @override + @JsonKey(ignore: true) + _$$_AttestationResponseCopyWith<_$_AttestationResponse> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/apis/core/verify/models/verify_context.g.dart b/lib/apis/core/verify/models/verify_context.g.dart new file mode 100644 index 00000000..41b5eb12 --- /dev/null +++ b/lib/apis/core/verify/models/verify_context.g.dart @@ -0,0 +1,46 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'verify_context.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_VerifyContext _$$_VerifyContextFromJson(Map json) => + _$_VerifyContext( + origin: json['origin'] as String, + validation: $enumDecode(_$ValidationEnumMap, json['validation']), + verifyUrl: json['verifyUrl'] as String, + isScam: json['isScam'] as bool?, + ); + +Map _$$_VerifyContextToJson(_$_VerifyContext instance) => + { + 'origin': instance.origin, + 'validation': _$ValidationEnumMap[instance.validation]!, + 'verifyUrl': instance.verifyUrl, + 'isScam': instance.isScam, + }; + +const _$ValidationEnumMap = { + Validation.UNKNOWN: 'UNKNOWN', + Validation.VALID: 'VALID', + Validation.INVALID: 'INVALID', + Validation.SCAM: 'SCAM', +}; + +_$_AttestationResponse _$$_AttestationResponseFromJson( + Map json) => + _$_AttestationResponse( + origin: json['origin'] as String, + attestationId: json['attestationId'] as String, + isScam: json['isScam'] as bool?, + ); + +Map _$$_AttestationResponseToJson( + _$_AttestationResponse instance) => + { + 'origin': instance.origin, + 'attestationId': instance.attestationId, + 'isScam': instance.isScam, + }; diff --git a/lib/apis/core/verify/verify.dart b/lib/apis/core/verify/verify.dart index 3fb52609..7f3b117a 100644 --- a/lib/apis/core/verify/verify.dart +++ b/lib/apis/core/verify/verify.dart @@ -1,22 +1,15 @@ -import 'package:flutter/foundation.dart'; +import 'dart:convert'; + import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/i_http_client.dart'; import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; import 'package:walletconnect_flutter_v2/apis/utils/constants.dart'; class Verify implements IVerify { final ICore _core; final IHttpClient _httpClient; - - String name = WalletConnectConstants.VERIFY_CONTEXT; - String? _verifyUrl; - bool _initialized = false; - // private isDevEnv; - // the queue is only used during the loading phase of the iframe to ensure all attestations are posted - List _queue = []; - // flag to disable verify when the iframe fails to load on main & fallback urls. - // this means Verify API is not enabled for the current projectId and there's no point in trying to initialize it again. - bool _verifyDisabled = false; + late String _verifyUrl; Verify({ required ICore core, @@ -27,78 +20,45 @@ class Verify implements IVerify { @override Future init({String? verifyUrl}) async { - if (_verifyDisabled) { - return; - } - - _verifyUrl = _getVerifyUrl(verifyUrl: verifyUrl); + _verifyUrl = _setVerifyUrl(verifyUrl: verifyUrl); } @override - Future register({required String attestationId}) async { - if (!_initialized) { - _queue.add(attestationId); - await init(); - } else { - // this.sendPost(params.attestationId); - } - } - - @override - Future resolve({required String attestationId}) async { - VerifyResult verifyResult = VerifyResult( - origin: '', - validation: Validation.VALID, - verifyUrl: '', - ); - if (kDebugMode) { - return verifyResult; - } - - final vurl = _getVerifyUrl(); + Future resolve({required String attestationId}) async { + AttestationResponse? response; try { - final result = await _fetchAttestation(attestationId, vurl); - debugPrint('result $result'); - // TODO set verifyResult + response = await _fetchAttestation(attestationId, _verifyUrl); } catch (error) { - _core.logger.e( - 'failed to resolve attestation: $attestationId from url: $vurl', - ); _core.logger.e(error); - final result = await _fetchAttestation( + response = await _fetchAttestation( attestationId, WalletConnectConstants.VERIFY_FALLBACK_SERVER, ); - debugPrint('result $result'); - // TODO set verifyResult } - return verifyResult; + return response; } - Future _fetchAttestation(String attestationId, String url) async { - _core.logger.i('resolving attestation: $attestationId from url: $url'); - // set artificial timeout to prevent hanging - await Future.delayed(const Duration(seconds: 2)); - // const timeout = this.startAbortTimer(ONE_SECOND * 2); - // const result = await fetch(`${url}/attestation/${attestationId}`, { - // signal: this.abortController.signal, - // }); + Future _fetchAttestation( + String attestationId, + String url, + ) async { final uri = Uri.parse('$url/attestation/$attestationId'); final response = await _httpClient.get(uri); - // clearTimeout(timeout); - // return result.status === 200 ? await result.json() : undefined; - if (response.statusCode == 200) { - return response.body; + if (response.statusCode != 200) { + final error = 'Attestation response error: ${response.statusCode}'; + throw Exception(error); } - return null; + return AttestationResponse.fromJson(jsonDecode(response.body)); } - String _getVerifyUrl({String? verifyUrl}) { - String url = - (verifyUrl ?? _verifyUrl) ?? WalletConnectConstants.VERIFY_SERVER; + String _setVerifyUrl({String? verifyUrl}) { + String url = verifyUrl ?? WalletConnectConstants.VERIFY_SERVER; + if (!WalletConnectConstants.TRUSTED_VERIFY_URLS.contains(url)) { _core.logger.i( - 'verify url: $url, not included in trusted list, assigning default: ${WalletConnectConstants.VERIFY_SERVER}'); + '[$runtimeType] verifyUrl $url not included in trusted list, ' + 'assigning default: ${WalletConnectConstants.VERIFY_SERVER}', + ); url = WalletConnectConstants.VERIFY_SERVER; } return url; diff --git a/lib/apis/sign_api/models/session_models.dart b/lib/apis/sign_api/models/session_models.dart index 3f096a20..b14d1e4c 100644 --- a/lib/apis/sign_api/models/session_models.dart +++ b/lib/apis/sign_api/models/session_models.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/relay_client_models.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; import 'package:walletconnect_flutter_v2/apis/models/basic_models.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/models/proposal_models.dart'; @@ -77,6 +78,7 @@ class SessionRequest with _$SessionRequest { required String method, required String chainId, required dynamic params, + required VerifyContext verifyContext, }) = _SessionRequest; factory SessionRequest.fromJson(Map json) => diff --git a/lib/apis/sign_api/models/session_models.freezed.dart b/lib/apis/sign_api/models/session_models.freezed.dart index 526a2f9d..1a1a360a 100644 --- a/lib/apis/sign_api/models/session_models.freezed.dart +++ b/lib/apis/sign_api/models/session_models.freezed.dart @@ -667,6 +667,7 @@ mixin _$SessionRequest { String get method => throw _privateConstructorUsedError; String get chainId => throw _privateConstructorUsedError; dynamic get params => throw _privateConstructorUsedError; + VerifyContext get verifyContext => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -681,7 +682,14 @@ abstract class $SessionRequestCopyWith<$Res> { _$SessionRequestCopyWithImpl<$Res, SessionRequest>; @useResult $Res call( - {int id, String topic, String method, String chainId, dynamic params}); + {int id, + String topic, + String method, + String chainId, + dynamic params, + VerifyContext verifyContext}); + + $VerifyContextCopyWith<$Res> get verifyContext; } /// @nodoc @@ -702,6 +710,7 @@ class _$SessionRequestCopyWithImpl<$Res, $Val extends SessionRequest> Object? method = null, Object? chainId = null, Object? params = freezed, + Object? verifyContext = null, }) { return _then(_value.copyWith( id: null == id @@ -724,8 +733,20 @@ class _$SessionRequestCopyWithImpl<$Res, $Val extends SessionRequest> ? _value.params : params // ignore: cast_nullable_to_non_nullable as dynamic, + verifyContext: null == verifyContext + ? _value.verifyContext + : verifyContext // ignore: cast_nullable_to_non_nullable + as VerifyContext, ) as $Val); } + + @override + @pragma('vm:prefer-inline') + $VerifyContextCopyWith<$Res> get verifyContext { + return $VerifyContextCopyWith<$Res>(_value.verifyContext, (value) { + return _then(_value.copyWith(verifyContext: value) as $Val); + }); + } } /// @nodoc @@ -737,7 +758,15 @@ abstract class _$$_SessionRequestCopyWith<$Res> @override @useResult $Res call( - {int id, String topic, String method, String chainId, dynamic params}); + {int id, + String topic, + String method, + String chainId, + dynamic params, + VerifyContext verifyContext}); + + @override + $VerifyContextCopyWith<$Res> get verifyContext; } /// @nodoc @@ -756,6 +785,7 @@ class __$$_SessionRequestCopyWithImpl<$Res> Object? method = null, Object? chainId = null, Object? params = freezed, + Object? verifyContext = null, }) { return _then(_$_SessionRequest( id: null == id @@ -778,6 +808,10 @@ class __$$_SessionRequestCopyWithImpl<$Res> ? _value.params : params // ignore: cast_nullable_to_non_nullable as dynamic, + verifyContext: null == verifyContext + ? _value.verifyContext + : verifyContext // ignore: cast_nullable_to_non_nullable + as VerifyContext, )); } } @@ -791,7 +825,8 @@ class _$_SessionRequest implements _SessionRequest { required this.topic, required this.method, required this.chainId, - required this.params}); + required this.params, + required this.verifyContext}); factory _$_SessionRequest.fromJson(Map json) => _$$_SessionRequestFromJson(json); @@ -806,10 +841,12 @@ class _$_SessionRequest implements _SessionRequest { final String chainId; @override final dynamic params; + @override + final VerifyContext verifyContext; @override String toString() { - return 'SessionRequest(id: $id, topic: $topic, method: $method, chainId: $chainId, params: $params)'; + return 'SessionRequest(id: $id, topic: $topic, method: $method, chainId: $chainId, params: $params, verifyContext: $verifyContext)'; } @override @@ -821,13 +858,15 @@ class _$_SessionRequest implements _SessionRequest { (identical(other.topic, topic) || other.topic == topic) && (identical(other.method, method) || other.method == method) && (identical(other.chainId, chainId) || other.chainId == chainId) && - const DeepCollectionEquality().equals(other.params, params)); + const DeepCollectionEquality().equals(other.params, params) && + (identical(other.verifyContext, verifyContext) || + other.verifyContext == verifyContext)); } @JsonKey(ignore: true) @override int get hashCode => Object.hash(runtimeType, id, topic, method, chainId, - const DeepCollectionEquality().hash(params)); + const DeepCollectionEquality().hash(params), verifyContext); @JsonKey(ignore: true) @override @@ -849,7 +888,8 @@ abstract class _SessionRequest implements SessionRequest { required final String topic, required final String method, required final String chainId, - required final dynamic params}) = _$_SessionRequest; + required final dynamic params, + required final VerifyContext verifyContext}) = _$_SessionRequest; factory _SessionRequest.fromJson(Map json) = _$_SessionRequest.fromJson; @@ -865,6 +905,8 @@ abstract class _SessionRequest implements SessionRequest { @override dynamic get params; @override + VerifyContext get verifyContext; + @override @JsonKey(ignore: true) _$$_SessionRequestCopyWith<_$_SessionRequest> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/apis/sign_api/models/session_models.g.dart b/lib/apis/sign_api/models/session_models.g.dart index b47a1e69..aa8ba731 100644 --- a/lib/apis/sign_api/models/session_models.g.dart +++ b/lib/apis/sign_api/models/session_models.g.dart @@ -85,6 +85,8 @@ _$_SessionRequest _$$_SessionRequestFromJson(Map json) => method: json['method'] as String, chainId: json['chainId'] as String, params: json['params'], + verifyContext: + VerifyContext.fromJson(json['verifyContext'] as Map), ); Map _$$_SessionRequestToJson(_$_SessionRequest instance) => @@ -94,4 +96,5 @@ Map _$$_SessionRequestToJson(_$_SessionRequest instance) => 'method': instance.method, 'chainId': instance.chainId, 'params': instance.params, + 'verifyContext': instance.verifyContext.toJson(), }; diff --git a/lib/apis/sign_api/models/sign_client_events.dart b/lib/apis/sign_api/models/sign_client_events.dart index 097bbd0c..5eb125ee 100644 --- a/lib/apis/sign_api/models/sign_client_events.dart +++ b/lib/apis/sign_api/models/sign_client_events.dart @@ -1,4 +1,5 @@ import 'package:event/event.dart'; +import 'package:walletconnect_flutter_v2/apis/core/verify/models/verify_context.dart'; import 'package:walletconnect_flutter_v2/apis/models/basic_models.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/models/proposal_models.dart'; import 'package:walletconnect_flutter_v2/apis/sign_api/models/session_models.dart'; @@ -6,16 +7,13 @@ import 'package:walletconnect_flutter_v2/apis/sign_api/models/session_models.dar class SessionProposalEvent extends EventArgs { int id; ProposalData params; + VerifyContext? verifyContext; SessionProposalEvent( this.id, - this.params, - ); - - SessionProposalEvent.fromSessionProposal( - SessionProposal proposal, - ) : id = proposal.id, - params = proposal.params; + this.params, [ + this.verifyContext, + ]); @override String toString() { diff --git a/lib/apis/sign_api/sign_engine.dart b/lib/apis/sign_api/sign_engine.dart index f3d9cfa4..7eac4fb0 100644 --- a/lib/apis/sign_api/sign_engine.dart +++ b/lib/apis/sign_api/sign_engine.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:event/event.dart'; import 'package:walletconnect_flutter_v2/apis/core/i_core.dart'; @@ -7,6 +8,7 @@ import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/json_rpc_utils. import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; import 'package:walletconnect_flutter_v2/apis/core/relay_client/relay_client_models.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/basic_models.dart'; import 'package:walletconnect_flutter_v2/apis/models/json_rpc_error.dart'; import 'package:walletconnect_flutter_v2/apis/models/json_rpc_request.dart'; @@ -90,6 +92,7 @@ class SignEngine implements ISignEngine { } await core.pairing.init(); + await core.verify.init(verifyUrl: metadata.verifyUrl); await proposals.init(); await sessions.init(); await pendingRequests.init(); @@ -962,10 +965,19 @@ class SignEngine implements ISignEngine { ); await _setProposal(payload.id, proposal); - onSessionProposal.broadcast(SessionProposalEvent( - payload.id, - proposal, - )); + + final verifyContext = await _getVerifyContext( + payload, + proposal.proposer.metadata, + ); + + onSessionProposal.broadcast( + SessionProposalEvent( + payload.id, + proposal, + verifyContext, + ), + ); } on WalletConnectError catch (err) { core.logger.e('_onSessionProposeRequest Error: $err'); await core.pairing.sendError( @@ -1185,10 +1197,7 @@ class SignEngine implements ISignEngine { /// Called when a session request is received /// Will attempt to find a handler for the request, if it doesn't, /// it will throw an error. - Future _onSessionRequest( - String topic, - JsonRpcRequest payload, - ) async { + Future _onSessionRequest(String topic, JsonRpcRequest payload) async { try { final request = WcSessionRequestRequest.fromJson(payload.params); await _isValidRequest( @@ -1197,12 +1206,19 @@ class SignEngine implements ISignEngine { request.request, ); - SessionRequest sessionRequest = SessionRequest( + final session = sessions.get(topic)!; + final verifyContext = await _getVerifyContext( + payload, + session.peer.metadata, + ); + + final sessionRequest = SessionRequest( id: payload.id, topic: topic, method: request.request.method, chainId: request.chainId, params: request.request.params, + verifyContext: verifyContext, ); // print('payload id: ${payload.id}'); @@ -1701,4 +1717,37 @@ class SignEngine implements ISignEngine { return true; } + + Future _getVerifyContext( + JsonRpcRequest payload, + PairingMetadata proposerMetada, + ) async { + try { + final jsonStringify = jsonEncode(payload.toJson()); + final hash = core.crypto.getUtils().hashMessage(jsonStringify); + + final result = await core.verify.resolve(attestationId: hash); + final validation = result?.origin == Uri.parse(proposerMetada.url).origin + ? Validation.VALID + : Validation.INVALID; + + return VerifyContext( + origin: result?.origin ?? proposerMetada.url, + verifyUrl: proposerMetada.verifyUrl ?? '', + validation: result?.isScam == true ? Validation.SCAM : validation, + isScam: result?.isScam, + ); + } catch (e, s) { + core.logger.e( + '[$runtimeType] _getVerifyContext', + error: e, + stackTrace: s, + ); + return VerifyContext( + origin: proposerMetada.url, + verifyUrl: proposerMetada.verifyUrl ?? '', + validation: Validation.UNKNOWN, + ); + } + } } diff --git a/lib/apis/utils/constants.dart b/lib/apis/utils/constants.dart index 55dce39e..5c7b500d 100644 --- a/lib/apis/utils/constants.dart +++ b/lib/apis/utils/constants.dart @@ -1,5 +1,5 @@ class WalletConnectConstants { - static const SDK_VERSION = '2.1.8'; + static const SDK_VERSION = '2.1.9'; static const CORE_PROTOCOL = 'wc'; static const CORE_VERSION = 2; diff --git a/lib/src/version.dart b/lib/src/version.dart index 7369037d..3a7829ac 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '2.1.8'; +const packageVersion = '2.1.9'; diff --git a/pubspec.yaml b/pubspec.yaml index 9d51363c..1cf63b27 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.1.8 +version: 2.1.9 repository: https://github.com/WalletConnect/WalletConnectFlutterV2 environment: @@ -18,7 +18,6 @@ dependencies: x25519: ^0.1.1 bs58: ^1.0.2 ed25519_edwards: ^0.3.1 - # json_rpc_2: ^3.0.2 event: ^2.1.2 stream_channel: ^2.1.0 shared_preferences: ^2.0.17 diff --git a/test/shared/shared_test_utils.mocks.dart b/test/shared/shared_test_utils.mocks.dart index b1851704..1350ef56 100644 --- a/test/shared/shared_test_utils.mocks.dart +++ b/test/shared/shared_test_utils.mocks.dart @@ -3,19 +3,19 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i19; -import 'dart:typed_data' as _i18; +import 'dart:async' as _i20; +import 'dart:typed_data' as _i19; import 'package:event/event.dart' as _i8; import 'package:http/http.dart' as _i9; -import 'package:logger/logger.dart' as _i16; +import 'package:logger/logger.dart' as _i17; import 'package:mockito/mockito.dart' as _i1; -import 'package:walletconnect_flutter_v2/apis/core/core.dart' as _i24; -import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart' as _i20; +import 'package:walletconnect_flutter_v2/apis/core/core.dart' as _i25; +import 'package:walletconnect_flutter_v2/apis/core/crypto/crypto.dart' as _i21; 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 _i17; + as _i18; 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' @@ -33,16 +33,18 @@ 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 _i21; + as _i22; import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/http_client.dart' - as _i23; + as _i24; import 'package:walletconnect_flutter_v2/apis/core/relay_client/websocket/websocket_handler.dart' - as _i25; + as _i26; 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 _i22; + as _i23; +import 'package:walletconnect_flutter_v2/apis/core/verify/i_verify.dart' + as _i16; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -219,8 +221,18 @@ class _FakeIHeartBeat_15 extends _i1.SmartFake implements _i15.IHeartBeat { ); } -class _FakeLogger_16 extends _i1.SmartFake implements _i16.Logger { - _FakeLogger_16( +class _FakeIVerify_16 extends _i1.SmartFake implements _i16.IVerify { + _FakeIVerify_16( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLogger_17 extends _i1.SmartFake implements _i17.Logger { + _FakeLogger_17( Object parent, Invocation parentInvocation, ) : super( @@ -232,7 +244,7 @@ class _FakeLogger_16 extends _i1.SmartFake implements _i16.Logger { /// A class which mocks [CryptoUtils]. /// /// See the documentation for Mockito's code generation for more information. -class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { +class MockCryptoUtils extends _i1.Mock implements _i18.CryptoUtils { MockCryptoUtils() { _i1.throwOnMissingStub(this); } @@ -252,13 +264,13 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { ), ) as _i2.CryptoKeyPair); @override - _i18.Uint8List randomBytes(int? length) => (super.noSuchMethod( + _i19.Uint8List randomBytes(int? length) => (super.noSuchMethod( Invocation.method( #randomBytes, [length], ), - returnValue: _i18.Uint8List(0), - ) as _i18.Uint8List); + returnValue: _i19.Uint8List(0), + ) as _i19.Uint8List); @override String generateRandomBytes32() => (super.noSuchMethod( Invocation.method( @@ -268,7 +280,7 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { returnValue: '', ) as String); @override - _i19.Future deriveSymKey( + _i20.Future deriveSymKey( String? privKeyA, String? pubKeyB, ) => @@ -280,8 +292,8 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { pubKeyB, ], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override String hashKey(String? key) => (super.noSuchMethod( Invocation.method( @@ -299,7 +311,7 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { returnValue: '', ) as String); @override - _i19.Future encrypt( + _i20.Future encrypt( String? message, String? symKey, { int? type, @@ -319,10 +331,10 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { #senderPublicKey: senderPublicKey, }, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future decrypt( + _i20.Future decrypt( String? symKey, String? encoded, ) => @@ -334,14 +346,14 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { encoded, ], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override String serialize( int? type, - _i18.Uint8List? sealed, - _i18.Uint8List? iv, { - _i18.Uint8List? senderPublicKey, + _i19.Uint8List? sealed, + _i19.Uint8List? iv, { + _i19.Uint8List? senderPublicKey, }) => (super.noSuchMethod( Invocation.method( @@ -431,7 +443,7 @@ class MockCryptoUtils extends _i1.Mock implements _i17.CryptoUtils { /// A class which mocks [Crypto]. /// /// See the documentation for Mockito's code generation for more information. -class MockCrypto extends _i1.Mock implements _i20.Crypto { +class MockCrypto extends _i1.Mock implements _i21.Crypto { MockCrypto() { _i1.throwOnMissingStub(this); } @@ -498,14 +510,14 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { returnValue: '', ) as String); @override - _i19.Future init() => (super.noSuchMethod( + _i20.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool hasKeys(String? tag) => (super.noSuchMethod( Invocation.method( @@ -515,23 +527,23 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { returnValue: false, ) as bool); @override - _i19.Future getClientId() => (super.noSuchMethod( + _i20.Future getClientId() => (super.noSuchMethod( Invocation.method( #getClientId, [], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future generateKeyPair() => (super.noSuchMethod( + _i20.Future generateKeyPair() => (super.noSuchMethod( Invocation.method( #generateKeyPair, [], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future generateSharedKey( + _i20.Future generateSharedKey( String? selfPublicKey, String? peerPublicKey, { String? overrideTopic, @@ -545,10 +557,10 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { ], {#overrideTopic: overrideTopic}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future setSymKey( + _i20.Future setSymKey( String? symKey, { String? overrideTopic, }) => @@ -558,28 +570,28 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { [symKey], {#overrideTopic: overrideTopic}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future deleteKeyPair(String? publicKey) => (super.noSuchMethod( + _i20.Future deleteKeyPair(String? publicKey) => (super.noSuchMethod( Invocation.method( #deleteKeyPair, [publicKey], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future deleteSymKey(String? topic) => (super.noSuchMethod( + _i20.Future deleteSymKey(String? topic) => (super.noSuchMethod( Invocation.method( #deleteSymKey, [topic], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future encode( + _i20.Future encode( String? topic, Map? payload, { _i2.EncodeOptions? options, @@ -593,10 +605,10 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { ], {#options: options}, ), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future decode( + _i20.Future decode( String? topic, String? encoded, { _i2.DecodeOptions? options, @@ -610,16 +622,16 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { ], {#options: options}, ), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future signJWT(String? aud) => (super.noSuchMethod( + _i20.Future signJWT(String? aud) => (super.noSuchMethod( Invocation.method( #signJWT, [aud], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override int getPayloadType(String? encoded) => (super.noSuchMethod( Invocation.method( @@ -647,7 +659,7 @@ class MockCrypto extends _i1.Mock implements _i20.Crypto { /// A class which mocks [MessageTracker]. /// /// See the documentation for Mockito's code generation for more information. -class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { +class MockMessageTracker extends _i1.Mock implements _i22.MessageTracker { MockMessageTracker() { _i1.throwOnMissingStub(this); } @@ -671,40 +683,40 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { ), ) as _i7.IStore); @override - _i8.Event<_i22.StoreCreateEvent>> get onCreate => + _i8.Event<_i23.StoreCreateEvent>> get onCreate => (super.noSuchMethod( Invocation.getter(#onCreate), - returnValue: _FakeEvent_8<_i22.StoreCreateEvent>>( + returnValue: _FakeEvent_8<_i23.StoreCreateEvent>>( this, Invocation.getter(#onCreate), ), - ) as _i8.Event<_i22.StoreCreateEvent>>); + ) as _i8.Event<_i23.StoreCreateEvent>>); @override - _i8.Event<_i22.StoreUpdateEvent>> get onUpdate => + _i8.Event<_i23.StoreUpdateEvent>> get onUpdate => (super.noSuchMethod( Invocation.getter(#onUpdate), - returnValue: _FakeEvent_8<_i22.StoreUpdateEvent>>( + returnValue: _FakeEvent_8<_i23.StoreUpdateEvent>>( this, Invocation.getter(#onUpdate), ), - ) as _i8.Event<_i22.StoreUpdateEvent>>); + ) as _i8.Event<_i23.StoreUpdateEvent>>); @override - _i8.Event<_i22.StoreDeleteEvent>> get onDelete => + _i8.Event<_i23.StoreDeleteEvent>> get onDelete => (super.noSuchMethod( Invocation.getter(#onDelete), - returnValue: _FakeEvent_8<_i22.StoreDeleteEvent>>( + returnValue: _FakeEvent_8<_i23.StoreDeleteEvent>>( this, Invocation.getter(#onDelete), ), - ) as _i8.Event<_i22.StoreDeleteEvent>>); + ) as _i8.Event<_i23.StoreDeleteEvent>>); @override - _i8.Event<_i22.StoreSyncEvent> get onSync => (super.noSuchMethod( + _i8.Event<_i23.StoreSyncEvent> get onSync => (super.noSuchMethod( Invocation.getter(#onSync), - returnValue: _FakeEvent_8<_i22.StoreSyncEvent>( + returnValue: _FakeEvent_8<_i23.StoreSyncEvent>( this, Invocation.getter(#onSync), ), - ) as _i8.Event<_i22.StoreSyncEvent>); + ) as _i8.Event<_i23.StoreSyncEvent>); @override Map> get data => (super.noSuchMethod( Invocation.getter(#data), @@ -737,7 +749,7 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { returnValue: '', ) as String); @override - _i19.Future recordMessageEvent( + _i20.Future recordMessageEvent( String? topic, String? message, ) => @@ -749,9 +761,9 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { message, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool messageIsRecorded( String? topic, @@ -768,14 +780,14 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { returnValue: false, ) as bool); @override - _i19.Future init() => (super.noSuchMethod( + _i20.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool has(String? key) => (super.noSuchMethod( Invocation.method( @@ -799,7 +811,7 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { returnValue: >[], ) as List>); @override - _i19.Future set( + _i20.Future set( String? key, Map? value, ) => @@ -811,36 +823,36 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { value, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future delete(String? key) => (super.noSuchMethod( + _i20.Future delete(String? key) => (super.noSuchMethod( Invocation.method( #delete, [key], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future persist() => (super.noSuchMethod( + _i20.Future persist() => (super.noSuchMethod( Invocation.method( #persist, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future restore() => (super.noSuchMethod( + _i20.Future restore() => (super.noSuchMethod( Invocation.method( #restore, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override void checkInitialized() => super.noSuchMethod( Invocation.method( @@ -854,13 +866,13 @@ class MockMessageTracker extends _i1.Mock implements _i21.MessageTracker { /// A class which mocks [HttpWrapper]. /// /// See the documentation for Mockito's code generation for more information. -class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { +class MockHttpWrapper extends _i1.Mock implements _i24.HttpWrapper { MockHttpWrapper() { _i1.throwOnMissingStub(this); } @override - _i19.Future<_i9.Response> get( + _i20.Future<_i9.Response> get( Uri? url, { Map? headers, }) => @@ -870,7 +882,7 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { [url], {#headers: headers}, ), - returnValue: _i19.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i20.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #get, @@ -878,9 +890,9 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { {#headers: headers}, ), )), - ) as _i19.Future<_i9.Response>); + ) as _i20.Future<_i9.Response>); @override - _i19.Future<_i9.Response> delete( + _i20.Future<_i9.Response> delete( Uri? url, { Map? headers, }) => @@ -890,7 +902,7 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { [url], {#headers: headers}, ), - returnValue: _i19.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i20.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #delete, @@ -898,9 +910,9 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { {#headers: headers}, ), )), - ) as _i19.Future<_i9.Response>); + ) as _i20.Future<_i9.Response>); @override - _i19.Future<_i9.Response> post( + _i20.Future<_i9.Response> post( Uri? url, { Map? headers, Object? body, @@ -914,7 +926,7 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { #body: body, }, ), - returnValue: _i19.Future<_i9.Response>.value(_FakeResponse_9( + returnValue: _i20.Future<_i9.Response>.value(_FakeResponse_9( this, Invocation.method( #post, @@ -925,17 +937,22 @@ class MockHttpWrapper extends _i1.Mock implements _i23.HttpWrapper { }, ), )), - ) as _i19.Future<_i9.Response>); + ) as _i20.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 _i24.Core { +class MockCore extends _i1.Mock implements _i25.Core { MockCore() { _i1.throwOnMissingStub(this); } + @override + String get projectId => (super.noSuchMethod( + Invocation.getter(#projectId), + returnValue: '', + ) as String); @override String get relayUrl => (super.noSuchMethod( Invocation.getter(#relayUrl), @@ -950,16 +967,19 @@ class MockCore extends _i1.Mock implements _i24.Core { returnValueForMissingStub: null, ); @override - String get projectId => (super.noSuchMethod( - Invocation.getter(#projectId), - returnValue: '', - ) as String); - @override String get pushUrl => (super.noSuchMethod( Invocation.getter(#pushUrl), returnValue: '', ) as String); @override + set pushUrl(String? _pushUrl) => super.noSuchMethod( + Invocation.setter( + #pushUrl, + _pushUrl, + ), + returnValueForMissingStub: null, + ); + @override _i10.ICrypto get crypto => (super.noSuchMethod( Invocation.getter(#crypto), returnValue: _FakeICrypto_10( @@ -1056,6 +1076,22 @@ class MockCore extends _i1.Mock implements _i24.Core { returnValueForMissingStub: null, ); @override + _i16.IVerify get verify => (super.noSuchMethod( + Invocation.getter(#verify), + returnValue: _FakeIVerify_16( + this, + Invocation.getter(#verify), + ), + ) as _i16.IVerify); + @override + set verify(_i16.IVerify? _verify) => super.noSuchMethod( + Invocation.setter( + #verify, + _verify, + ), + returnValueForMissingStub: null, + ); + @override _i7.IStore> get storage => (super.noSuchMethod( Invocation.getter(#storage), returnValue: _FakeIStore_7>( @@ -1082,63 +1118,63 @@ class MockCore extends _i1.Mock implements _i24.Core { returnValue: '', ) as String); @override - _i16.Logger get logger => (super.noSuchMethod( + _i17.Logger get logger => (super.noSuchMethod( Invocation.getter(#logger), - returnValue: _FakeLogger_16( + returnValue: _FakeLogger_17( this, Invocation.getter(#logger), ), - ) as _i16.Logger); + ) as _i17.Logger); @override - _i19.Future start() => (super.noSuchMethod( + _i20.Future start() => (super.noSuchMethod( Invocation.method( #start, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); } /// A class which mocks [WebSocketHandler]. /// /// See the documentation for Mockito's code generation for more information. -class MockWebSocketHandler extends _i1.Mock implements _i25.WebSocketHandler { +class MockWebSocketHandler extends _i1.Mock implements _i26.WebSocketHandler { MockWebSocketHandler() { _i1.throwOnMissingStub(this); } @override - _i19.Future get ready => (super.noSuchMethod( + _i20.Future get ready => (super.noSuchMethod( Invocation.getter(#ready), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future setup({required String? url}) => (super.noSuchMethod( + _i20.Future setup({required String? url}) => (super.noSuchMethod( Invocation.method( #setup, [], {#url: url}, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future connect() => (super.noSuchMethod( + _i20.Future connect() => (super.noSuchMethod( Invocation.method( #connect, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future close() => (super.noSuchMethod( + _i20.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); } From e6d67f8f873621693c851e3f6b19290b9ae3e832 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Tue, 7 Nov 2023 15:47:32 +0100 Subject: [PATCH 3/4] change in example's bundleId --- example/dapp/lib/pages/connect_page.dart | 6 ++++-- example/wallet/android/app/build.gradle | 4 ++-- .../wallet/android/app/src/main/AndroidManifest.xml | 2 +- .../main/kotlin/com/example/wallet/MainActivity.kt | 2 +- example/wallet/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- example/wallet/ios/Runner/Info.plist | 12 ++++++------ .../wallet/lib/dependencies/web3wallet_service.dart | 1 - 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/example/dapp/lib/pages/connect_page.dart b/example/dapp/lib/pages/connect_page.dart index a8b0462f..e3f98110 100644 --- a/example/dapp/lib/pages/connect_page.dart +++ b/example/dapp/lib/pages/connect_page.dart @@ -160,8 +160,10 @@ class ConnectPageState extends State { ); } - Future _onConnect(List chains, - {Function(String message)? showToast}) async { + Future _onConnect( + List chains, { + Function(String message)? showToast, + }) async { // Use the chain metadata to build the required namespaces: // Get the methods, get the events final Map requiredNamespaces = {}; diff --git a/example/wallet/android/app/build.gradle b/example/wallet/android/app/build.gradle index 2c257f48..0e171649 100644 --- a/example/wallet/android/app/build.gradle +++ b/example/wallet/android/app/build.gradle @@ -44,7 +44,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.walletconnect.flutter_wallet" + applicationId "com.walletconnect.flutterwallet" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 21 @@ -60,7 +60,7 @@ android { signingConfig signingConfigs.debug } } - namespace 'com.example.wallet' + namespace 'com.walletconnect.flutterwallet' } flutter { diff --git a/example/wallet/android/app/src/main/AndroidManifest.xml b/example/wallet/android/app/src/main/AndroidManifest.xml index 83cb3c1b..636a1ade 100644 --- a/example/wallet/android/app/src/main/AndroidManifest.xml +++ b/example/wallet/android/app/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -24,6 +26,10 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSCameraUsageDescription + This app needs camera access to scan QR codes + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -43,11 +49,5 @@ UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - NSCameraUsageDescription - This app needs camera access to scan QR codes diff --git a/example/wallet/lib/dependencies/web3wallet_service.dart b/example/wallet/lib/dependencies/web3wallet_service.dart index 4ad40cca..8a570ae3 100644 --- a/example/wallet/lib/dependencies/web3wallet_service.dart +++ b/example/wallet/lib/dependencies/web3wallet_service.dart @@ -49,7 +49,6 @@ class Web3WalletService extends IWeb3WalletService { icons: [ 'https://github.com/WalletConnect/Web3ModalFlutter/blob/master/assets/png/logo_wc.png' ], - // verifyUrl: 'https://your_verify_url.here', ), ); From 398310178cff2721c91fcfb3125a4c8d916f74be Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Tue, 7 Nov 2023 16:30:41 +0100 Subject: [PATCH 4/4] minor comment --- lib/apis/core/verify/verify.dart | 2 ++ lib/apis/utils/constants.dart | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/apis/core/verify/verify.dart b/lib/apis/core/verify/verify.dart index 7f3b117a..98ccd0be 100644 --- a/lib/apis/core/verify/verify.dart +++ b/lib/apis/core/verify/verify.dart @@ -20,6 +20,8 @@ class Verify implements IVerify { @override Future init({String? verifyUrl}) async { + // TODO custom verifyUrl is not yet allowed. + // Always using walletconnect urls for now _verifyUrl = _setVerifyUrl(verifyUrl: verifyUrl); } diff --git a/lib/apis/utils/constants.dart b/lib/apis/utils/constants.dart index 5c7b500d..53701997 100644 --- a/lib/apis/utils/constants.dart +++ b/lib/apis/utils/constants.dart @@ -23,7 +23,6 @@ class WalletConnectConstants { static const DEFAULT_PUSH_URL = 'https://echo.walletconnect.com'; - static const VERIFY_CONTEXT = 'verify-api'; 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];