From 24dbbbb23b1fe04ebb4f367a860eca080c421d4d Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Fri, 19 Apr 2024 18:33:18 +0200 Subject: [PATCH 1/3] some files replacements --- lib/models/listing.dart | 130 ++++++++++ lib/models/w3m_wallet_info.dart | 2 +- .../explorer_service/explorer_service.dart | 3 + .../explorer_service/models/api_response.dart | 228 +----------------- .../models/native_app_data.dart | 31 +++ .../models/request_params.dart | 64 +++++ .../models/wc_sample_wallets.dart | 3 +- .../magic_service/models/frame_message.dart | 7 +- lib/widgets/qr_code_view.dart | 1 - lib/widgets/w3m_account_button.dart | 5 +- .../widget_stack/transition_container.dart | 1 - test/test_data.dart | 1 + 12 files changed, 237 insertions(+), 239 deletions(-) create mode 100644 lib/models/listing.dart create mode 100644 lib/services/explorer_service/models/native_app_data.dart create mode 100644 lib/services/explorer_service/models/request_params.dart diff --git a/lib/models/listing.dart b/lib/models/listing.dart new file mode 100644 index 00000000..dfeb6f10 --- /dev/null +++ b/lib/models/listing.dart @@ -0,0 +1,130 @@ +import 'dart:convert'; + +class Listing { + final String id; + final String name; + final String homepage; + final String imageId; + final int order; + final String? mobileLink; + final String? desktopLink; + final String? webappLink; + final String? appStore; + final String? playStore; + final String? rdns; + final List? injected; + + Listing({ + required this.id, + required this.name, + required this.homepage, + required this.imageId, + required this.order, + this.mobileLink, + this.desktopLink, + this.webappLink, + this.appStore, + this.playStore, + this.rdns, + this.injected, + }); + + Listing copyWith({ + String? id, + String? name, + String? homepage, + String? imageId, + int? order, + String? mobileLink, + String? desktopLink, + String? webappLink, + String? appStore, + String? playStore, + String? rdns, + List? injected, + }) => + Listing( + id: id ?? this.id, + name: name ?? this.name, + homepage: homepage ?? this.homepage, + imageId: imageId ?? this.imageId, + order: order ?? this.order, + mobileLink: mobileLink ?? this.mobileLink, + desktopLink: desktopLink ?? this.desktopLink, + webappLink: webappLink ?? this.webappLink, + appStore: appStore ?? this.appStore, + playStore: playStore ?? this.playStore, + rdns: rdns ?? this.rdns, + injected: injected ?? this.injected, + ); + + factory Listing.fromRawJson(String str) => Listing.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Listing.fromJson(Object? json) { + final j = json as Map? ?? {}; + return Listing( + id: j['id'], + name: j['name'], + homepage: j['homepage'], + imageId: j['image_id'], + order: j['order'], + mobileLink: j['mobile_link'], + desktopLink: j['desktop_link'], + webappLink: j['webapp_link'], + appStore: j['app_store'], + playStore: j['play_store'], + rdns: j['rdns'], + injected: j['injected'] == null + ? [] + : List.from( + j['injected']!.map((x) => Injected.fromJson(x)), + ), + ); + } + + Map toJson() => { + 'id': id, + 'name': name, + 'homepage': homepage, + 'image_id': imageId, + 'order': order, + 'mobile_link': mobileLink, + 'desktop_link': desktopLink, + 'webapp_link': webappLink, + 'app_store': appStore, + 'play_store': playStore, + 'rdns': rdns, + 'injected': injected == null + ? [] + : List.from(injected!.map((x) => x.toJson())), + }; +} + +class Injected { + final String namespace; + final String injectedId; + + Injected({required this.namespace, required this.injectedId}); + + Injected copyWith({String? namespace, String? injectedId}) => Injected( + namespace: namespace ?? this.namespace, + injectedId: injectedId ?? this.injectedId, + ); + + factory Injected.fromRawJson(String str) => + Injected.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Injected.fromJson(Map json) => Injected( + namespace: json['namespace'], + injectedId: json['injected_id'], + ); + + Map toJson() => { + 'namespace': namespace, + 'injected_id': injectedId, + }; +} diff --git a/lib/models/w3m_wallet_info.dart b/lib/models/w3m_wallet_info.dart index f41eb5cb..d55a3674 100644 --- a/lib/models/w3m_wallet_info.dart +++ b/lib/models/w3m_wallet_info.dart @@ -1,5 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:web3modal_flutter/services/explorer_service/models/api_response.dart'; +import 'package:web3modal_flutter/models/listing.dart'; part 'w3m_wallet_info.freezed.dart'; part 'w3m_wallet_info.g.dart'; diff --git a/lib/services/explorer_service/explorer_service.dart b/lib/services/explorer_service/explorer_service.dart index c8feb4eb..02512bcf 100644 --- a/lib/services/explorer_service/explorer_service.dart +++ b/lib/services/explorer_service/explorer_service.dart @@ -5,8 +5,11 @@ import 'dart:math'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; +import 'package:web3modal_flutter/models/listing.dart'; import 'package:web3modal_flutter/services/coinbase_service/coinbase_service.dart'; +import 'package:web3modal_flutter/services/explorer_service/models/native_app_data.dart'; import 'package:web3modal_flutter/services/explorer_service/models/redirect.dart'; +import 'package:web3modal_flutter/services/explorer_service/models/request_params.dart'; import 'package:web3modal_flutter/services/explorer_service/models/wc_sample_wallets.dart'; import 'package:web3modal_flutter/utils/debouncer.dart'; import 'package:web3modal_flutter/utils/url/url_utils_singleton.dart'; diff --git a/lib/services/explorer_service/models/api_response.dart b/lib/services/explorer_service/models/api_response.dart index ac6a6348..95c8d18f 100644 --- a/lib/services/explorer_service/models/api_response.dart +++ b/lib/services/explorer_service/models/api_response.dart @@ -1,6 +1,6 @@ -import 'dart:convert'; +import 'package:web3modal_flutter/models/listing.dart'; +import 'package:web3modal_flutter/services/explorer_service/models/native_app_data.dart'; -// TODO this should be placed somewhere else class ApiResponse { final int count; final List data; @@ -37,227 +37,3 @@ class ApiResponse { )), }; } - -class Listing { - final String id; - final String name; - final String homepage; - final String imageId; - final int order; - final String? mobileLink; - final String? desktopLink; - final String? webappLink; - final String? appStore; - final String? playStore; - final String? rdns; - final List? injected; - - Listing({ - required this.id, - required this.name, - required this.homepage, - required this.imageId, - required this.order, - this.mobileLink, - this.desktopLink, - this.webappLink, - this.appStore, - this.playStore, - this.rdns, - this.injected, - }); - - Listing copyWith({ - String? id, - String? name, - String? homepage, - String? imageId, - int? order, - String? mobileLink, - String? desktopLink, - String? webappLink, - String? appStore, - String? playStore, - String? rdns, - List? injected, - }) => - Listing( - id: id ?? this.id, - name: name ?? this.name, - homepage: homepage ?? this.homepage, - imageId: imageId ?? this.imageId, - order: order ?? this.order, - mobileLink: mobileLink ?? this.mobileLink, - desktopLink: desktopLink ?? this.desktopLink, - webappLink: webappLink ?? this.webappLink, - appStore: appStore ?? this.appStore, - playStore: playStore ?? this.playStore, - rdns: rdns ?? this.rdns, - injected: injected ?? this.injected, - ); - - factory Listing.fromRawJson(String str) => Listing.fromJson(json.decode(str)); - - String toRawJson() => json.encode(toJson()); - - factory Listing.fromJson(Object? json) { - final j = json as Map? ?? {}; - return Listing( - id: j['id'], - name: j['name'], - homepage: j['homepage'], - imageId: j['image_id'], - order: j['order'], - mobileLink: j['mobile_link'], - desktopLink: j['desktop_link'], - webappLink: j['webapp_link'], - appStore: j['app_store'], - playStore: j['play_store'], - rdns: j['rdns'], - injected: j['injected'] == null - ? [] - : List.from( - j['injected']!.map((x) => Injected.fromJson(x)), - ), - ); - } - - Map toJson() => { - 'id': id, - 'name': name, - 'homepage': homepage, - 'image_id': imageId, - 'order': order, - 'mobile_link': mobileLink, - 'desktop_link': desktopLink, - 'webapp_link': webappLink, - 'app_store': appStore, - 'play_store': playStore, - 'rdns': rdns, - 'injected': injected == null - ? [] - : List.from(injected!.map((x) => x.toJson())), - }; -} - -class Injected { - final String namespace; - final String injectedId; - - Injected({required this.namespace, required this.injectedId}); - - Injected copyWith({String? namespace, String? injectedId}) => Injected( - namespace: namespace ?? this.namespace, - injectedId: injectedId ?? this.injectedId, - ); - - factory Injected.fromRawJson(String str) => - Injected.fromJson(json.decode(str)); - - String toRawJson() => json.encode(toJson()); - - factory Injected.fromJson(Map json) => Injected( - namespace: json['namespace'], - injectedId: json['injected_id'], - ); - - Map toJson() => { - 'namespace': namespace, - 'injected_id': injectedId, - }; -} - -class NativeAppData { - final String id; - final String? schema; - - NativeAppData({required this.id, this.schema}); - - NativeAppData copyWith({String? id, String? schema}) => NativeAppData( - id: id ?? this.id, - schema: schema ?? this.schema, - ); - - factory NativeAppData.fromRawJson(String str) => - NativeAppData.fromJson(json.decode(str)); - - String toRawJson() => json.encode(toJson()); - - factory NativeAppData.fromJson(Object? json) { - final j = json as Map? ?? {}; - return NativeAppData( - id: j['id'], - schema: (j['ios_schema'] ?? j['android_app_id'])?.toString().trim() ?? '', - ); - } - - Map toJson() => { - 'id': id, - 'schema': schema, - }; -} - -class RequestParams { - final int page; // eg. 1 - final int entries; // eg. 100 - final String? search; // eg. MetaMa... - final String? include; // eg. id1,id2,id3 - final String? exclude; // eg. id1,id2,id3 - final String? platform; // 'ios' | 'android' - - const RequestParams({ - required this.page, - required this.entries, - this.search, - this.include, - this.exclude, - this.platform, - }); - - Map toJson({bool short = false}) { - Map params = { - 'page': page.toString(), - 'entries': entries.toString(), - }; - if ((search ?? '').isNotEmpty) { - params['search'] = search; - } - if ((include ?? '').isNotEmpty && !short) { - params['include'] = include; - } - if ((exclude ?? '').isNotEmpty && !short) { - params['exclude'] = exclude; - } - if ((platform ?? '').isNotEmpty) { - params['platform'] = platform; - } - - return params; - } - - RequestParams copyWith({ - int? page, - int? entries, - String? search, - String? include, - String? exclude, - String? platform, - }) => - RequestParams( - page: page ?? this.page, - entries: entries ?? this.entries, - search: search ?? this.search, - include: include ?? this.include, - exclude: exclude ?? this.exclude, - platform: platform ?? this.platform, - ); - - RequestParams nextPage() => RequestParams( - page: page + 1, - entries: entries, - search: search, - include: include, - exclude: exclude, - platform: platform, - ); -} diff --git a/lib/services/explorer_service/models/native_app_data.dart b/lib/services/explorer_service/models/native_app_data.dart new file mode 100644 index 00000000..87ef9bc4 --- /dev/null +++ b/lib/services/explorer_service/models/native_app_data.dart @@ -0,0 +1,31 @@ +import 'dart:convert'; + +class NativeAppData { + final String id; + final String? schema; + + NativeAppData({required this.id, this.schema}); + + NativeAppData copyWith({String? id, String? schema}) => NativeAppData( + id: id ?? this.id, + schema: schema ?? this.schema, + ); + + factory NativeAppData.fromRawJson(String str) => + NativeAppData.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory NativeAppData.fromJson(Object? json) { + final j = json as Map? ?? {}; + return NativeAppData( + id: j['id'], + schema: (j['ios_schema'] ?? j['android_app_id'])?.toString().trim() ?? '', + ); + } + + Map toJson() => { + 'id': id, + 'schema': schema, + }; +} diff --git a/lib/services/explorer_service/models/request_params.dart b/lib/services/explorer_service/models/request_params.dart new file mode 100644 index 00000000..a495855b --- /dev/null +++ b/lib/services/explorer_service/models/request_params.dart @@ -0,0 +1,64 @@ +class RequestParams { + final int page; // eg. 1 + final int entries; // eg. 100 + final String? search; // eg. MetaMa... + final String? include; // eg. id1,id2,id3 + final String? exclude; // eg. id1,id2,id3 + final String? platform; // 'ios' | 'android' + + const RequestParams({ + required this.page, + required this.entries, + this.search, + this.include, + this.exclude, + this.platform, + }); + + Map toJson({bool short = false}) { + Map params = { + 'page': page.toString(), + 'entries': entries.toString(), + }; + if ((search ?? '').isNotEmpty) { + params['search'] = search; + } + if ((include ?? '').isNotEmpty && !short) { + params['include'] = include; + } + if ((exclude ?? '').isNotEmpty && !short) { + params['exclude'] = exclude; + } + if ((platform ?? '').isNotEmpty) { + params['platform'] = platform; + } + + return params; + } + + RequestParams copyWith({ + int? page, + int? entries, + String? search, + String? include, + String? exclude, + String? platform, + }) => + RequestParams( + page: page ?? this.page, + entries: entries ?? this.entries, + search: search ?? this.search, + include: include ?? this.include, + exclude: exclude ?? this.exclude, + platform: platform ?? this.platform, + ); + + RequestParams nextPage() => RequestParams( + page: page + 1, + entries: entries, + search: search, + include: include, + exclude: exclude, + platform: platform, + ); +} diff --git a/lib/services/explorer_service/models/wc_sample_wallets.dart b/lib/services/explorer_service/models/wc_sample_wallets.dart index 896e148c..465bea7a 100644 --- a/lib/services/explorer_service/models/wc_sample_wallets.dart +++ b/lib/services/explorer_service/models/wc_sample_wallets.dart @@ -1,4 +1,5 @@ -import 'package:web3modal_flutter/services/explorer_service/models/api_response.dart'; +import 'package:web3modal_flutter/models/listing.dart'; +import 'package:web3modal_flutter/services/explorer_service/models/native_app_data.dart'; import 'package:web3modal_flutter/web3modal_flutter.dart'; class WCSampleWallets { diff --git a/lib/services/magic_service/models/frame_message.dart b/lib/services/magic_service/models/frame_message.dart index 3352939f..593af72e 100644 --- a/lib/services/magic_service/models/frame_message.dart +++ b/lib/services/magic_service/models/frame_message.dart @@ -5,8 +5,6 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/utils/util.dart'; import 'package:web3modal_flutter/web3modal_flutter.dart'; -import 'package:convert/convert.dart'; - class FrameMessage { static const _origin = 'secure.walletconnect.com'; @@ -217,10 +215,9 @@ class RpcRequest extends MessageData { final p = params.map((i) => '$i').toList(); if (method == 'personal_sign') { - final bytes = utf8.encode(p.first); - final data = hex.encode(bytes); + final data = p.first; final address = p.last; - return '{$t,payload:{$m,params:[\'0x$data\',\'$address\']}}'; + return '{$t,payload:{$m,params:[\'$data\',\'$address\']}}'; } if (method == 'eth_signTypedData_v4' || method == 'eth_signTypedData_v3' || diff --git a/lib/widgets/qr_code_view.dart b/lib/widgets/qr_code_view.dart index 21a5a170..29878182 100644 --- a/lib/widgets/qr_code_view.dart +++ b/lib/widgets/qr_code_view.dart @@ -8,7 +8,6 @@ import 'package:web3modal_flutter/web3modal_flutter.dart'; import 'package:web3modal_flutter/widgets/miscellaneous/content_loading.dart'; import 'package:web3modal_flutter/widgets/miscellaneous/responsive_container.dart'; -// TODO This file should be called qr_code_view.dart class QRCodeView extends StatelessWidget { const QRCodeView({ super.key, diff --git a/lib/widgets/w3m_account_button.dart b/lib/widgets/w3m_account_button.dart index da179d9a..a882afe0 100644 --- a/lib/widgets/w3m_account_button.dart +++ b/lib/widgets/w3m_account_button.dart @@ -90,10 +90,7 @@ class _W3MAccountButtonState extends State { if (widget.service.isOpen) { widgetStack.instance.popAllAndPush(ConfirmEmailPage()); } else { - widget.service.openModal( - widget.context ?? context, - ConfirmEmailPage(), - ); + widget.service.openModal(widget.context ?? context, ConfirmEmailPage()); } } diff --git a/lib/widgets/widget_stack/transition_container.dart b/lib/widgets/widget_stack/transition_container.dart index d5264fd7..4c97873b 100644 --- a/lib/widgets/widget_stack/transition_container.dart +++ b/lib/widgets/widget_stack/transition_container.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/widgets/widget_stack/widget_stack_singleton.dart'; -// TODO change transition type to reflect Web implementation class TransitionContainer extends StatefulWidget { const TransitionContainer({ super.key, diff --git a/test/test_data.dart b/test/test_data.dart index c09d479f..83f53334 100644 --- a/test/test_data.dart +++ b/test/test_data.dart @@ -1,3 +1,4 @@ +import 'package:web3modal_flutter/models/listing.dart'; import 'package:web3modal_flutter/web3modal_flutter.dart'; import 'package:web3modal_flutter/services/explorer_service/models/api_response.dart'; From 59fd613dc340e7d79182ed9a2ad76a3838730254 Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Mon, 22 Apr 2024 18:15:51 +0200 Subject: [PATCH 2/3] improvements for when explorer api fails --- example/ios/Runner.xcodeproj/project.pbxproj | 7 +- example/lib/home_page.dart | 81 +++++++-------- lib/pages/wallets_list_long_page.dart | 7 +- lib/pages/wallets_list_short_page.dart | 47 +++++---- .../explorer_service/explorer_service.dart | 98 +++++++++++-------- lib/utils/w3m_chains_presets.dart | 30 ++++++ 6 files changed, 159 insertions(+), 111 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 42e42eae..9a10b847 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -684,11 +684,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 53; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; + DEVELOPMENT_TEAM = W5R8AG9K22; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; @@ -699,7 +697,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.web3modal.flutterExample; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = FlutterAppStoreProfileWithPush; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 4f0c7b24..f1f59231 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -41,7 +41,7 @@ class _MyHomePageState extends State { void _initializeService() async { // See https://docs.walletconnect.com/web3modal/flutter/custom-chains - W3MChainPresets.chains.putIfAbsent(_sepolia.chainId, () => _sepolia); + W3MChainPresets.chains.addAll(W3MChainPresets.testChains); _w3mService = W3MService( projectId: DartDefines.projectId, @@ -69,7 +69,11 @@ class _MyHomePageState extends State { // 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', // Metamask // '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369', // Rainbow // 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', // Coinbase Wallet - // 'be49f0a78d6ea1beed3804c3a6b62ea71f568d58d9df8097f3d61c7c9baf273d', // Uniswap + // 'c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a', // Uniswap + // '18450873727504ae9315a084fa7624b5297d2fe5880f0982979c17345a138277', // Kraken Wallet + // '38f5d18bd8522c244bdd70cb4a68e0e718865155811c043f052fb9f1c51de662', // Bitget + // '19177a98252e07ddfc9af2083ba8e07ef627cb6103467ffebb3f8f4205fd7927', // Ledger Live + // '4457c130df49fb3cb1f8b99574b97b35208bd3d0d13b8d25d2b5884ed2cad13a', // Shapeshift // }, // featuredWalletIds: { // '18450873727504ae9315a084fa7624b5297d2fe5880f0982979c17345a138277', // Kraken Wallet @@ -129,38 +133,37 @@ class _MyHomePageState extends State { } final polygon = W3MChainPresets.chains['137']!; final approvedChains = _w3mService.getApprovedChains() ?? []; - if (approvedChains.contains(polygon.namespace)) { - return; + if (!approvedChains.contains(polygon.namespace)) { + Future.delayed( + const Duration(milliseconds: 500), + () { + showDialog( + context: context, + builder: (_) { + return AlertDialog( + content: const Text('Switch to Polygon?'), + actions: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Cancel'), + ), + ElevatedButton( + onPressed: () async { + _w3mService.requestSwitchToChain(polygon); + _w3mService.launchConnectedWallet(); + Navigator.of(context).pop(); + }, + child: const Text('Switch'), + ), + ], + ); + }, + ); + }, + ); } - Future.delayed( - const Duration(milliseconds: 500), - () { - showDialog( - context: context, - builder: (_) { - return AlertDialog( - content: const Text('Switch to Polygon?'), - actions: [ - ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('Cancel'), - ), - ElevatedButton( - onPressed: () async { - _w3mService.requestSwitchToChain(polygon); - _w3mService.launchConnectedWallet(); - Navigator.of(context).pop(); - }, - child: const Text('Switch'), - ), - ], - ); - }, - ); - }, - ); } void _onModalNetworkChange(ModalNetworkChange? event) { @@ -340,18 +343,6 @@ class _ConnectedView extends StatelessWidget { } } -final _sepolia = W3MChainInfo( - chainName: 'Sepolia Testnet', - chainId: '11155111', - namespace: 'eip155:11155111', - tokenName: 'SEP', - rpcUrl: 'https://ethereum-sepolia.publicnode.com', - blockExplorer: W3MBlockExplorer( - name: 'Sepolia Etherscan', - url: 'https://sepolia.etherscan.io/', - ), -); - ButtonStyle buttonStyle(BuildContext context) { final themeColors = Web3ModalTheme.colorsOf(context); return ButtonStyle( diff --git a/lib/pages/wallets_list_long_page.dart b/lib/pages/wallets_list_long_page.dart index 8d0f7b00..08bd6378 100644 --- a/lib/pages/wallets_list_long_page.dart +++ b/lib/pages/wallets_list_long_page.dart @@ -53,10 +53,11 @@ class _WalletsListLongPageState extends State { final service = Web3ModalProvider.of(context).service; final totalListings = explorerService.instance.totalListings.value; final rows = (totalListings / 4.0).ceil(); + final isSearchAvailable = totalListings >= kShortWalletListCount; final maxHeight = (rows * kGridItemHeight) + - (kPadding16 * 2.0) + + (kPadding16 * 4.0) + + (isSearchAvailable ? kSearchFieldHeight : 0.0) + ResponsiveData.paddingBottomOf(context); - final isSearchAvailable = totalListings >= 20; return Web3ModalNavbar( title: 'All wallets', onTapTitle: () => _controller.animateTo( @@ -76,7 +77,7 @@ class _WalletsListLongPageState extends State { constraints: BoxConstraints( maxHeight: !isSearchAvailable ? maxHeight - : ResponsiveData.maxHeightOf(context), + : min(maxHeight, ResponsiveData.maxHeightOf(context)), ), child: Column( children: [ diff --git a/lib/pages/wallets_list_short_page.dart b/lib/pages/wallets_list_short_page.dart index 48f1768e..db926491 100644 --- a/lib/pages/wallets_list_short_page.dart +++ b/lib/pages/wallets_list_short_page.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:web3modal_flutter/pages/about_wallets.dart'; import 'package:web3modal_flutter/pages/confirm_email_page.dart'; import 'package:web3modal_flutter/pages/connect_wallet_page.dart'; +import 'package:web3modal_flutter/pages/qr_code_page.dart'; import 'package:web3modal_flutter/services/analytics_service/analytics_service_singleton.dart'; import 'package:web3modal_flutter/services/analytics_service/models/analytics_event.dart'; import 'package:web3modal_flutter/services/explorer_service/explorer_service_singleton.dart'; @@ -71,7 +72,7 @@ class _WalletsListShortPageState extends State { safeAreaRight: true, body: ExplorerServiceItemsListener( builder: (context, initialised, items, _) { - if (!initialised || items.isEmpty) { + if (!initialised) { return ConstrainedBox( constraints: BoxConstraints(maxHeight: maxHeight), child: const WalletsList( @@ -80,15 +81,15 @@ class _WalletsListShortPageState extends State { ), ); } - final emailEnabled = magicService.instance.isEnabled.value; final itemsCount = min(kShortWalletListCount, items.length); - final itemsToShow = items.getRange(0, itemsCount); - if (itemsCount < kShortWalletListCount && isPortrait) { - maxHeight = kListItemHeight * (itemsCount + 1); + if (itemsCount < kShortWalletListCount) { + maxHeight = kListItemHeight * (itemsCount + 1.5); } + final emailEnabled = magicService.instance.isEnabled.value; if (emailEnabled) { maxHeight += (kSearchFieldHeight * 2); } + final itemsToShow = items.getRange(0, itemsCount); return ConstrainedBox( constraints: BoxConstraints(maxHeight: maxHeight), child: WalletsList( @@ -129,25 +130,35 @@ class _WalletsListShortPageState extends State { ) : null, itemList: itemsToShow.toList(), - bottomItems: (itemsCount < kShortWalletListCount) - ? [] - : [ - AllWalletsItem( - trailing: ValueListenableBuilder( + bottomItems: [ + AllWalletsItem( + trailing: itemsCount < kShortWalletListCount + ? null + : ValueListenableBuilder( valueListenable: explorerService.instance.totalListings, builder: (context, value, _) { return WalletItemChip(value: value.lazyCount); }, ), - onTap: () { - widgetStack.instance.push( - const WalletsListLongPage(), - event: ClickAllWalletsEvent(), - ); - }, - ), - ], + onTap: () { + if (itemsCount < kShortWalletListCount) { + widgetStack.instance.push( + const QRCodePage(), + event: SelectWalletEvent( + name: 'WalletConnect', + platform: AnalyticsPlatform.qrcode, + ), + ); + } else { + widgetStack.instance.push( + const WalletsListLongPage(), + event: ClickAllWalletsEvent(), + ); + } + }, + ), + ], ), ); }, diff --git a/lib/services/explorer_service/explorer_service.dart b/lib/services/explorer_service/explorer_service.dart index 02512bcf..5e11439b 100644 --- a/lib/services/explorer_service/explorer_service.dart +++ b/lib/services/explorer_service/explorer_service.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:math'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; @@ -11,6 +10,7 @@ import 'package:web3modal_flutter/services/explorer_service/models/native_app_da import 'package:web3modal_flutter/services/explorer_service/models/redirect.dart'; import 'package:web3modal_flutter/services/explorer_service/models/request_params.dart'; import 'package:web3modal_flutter/services/explorer_service/models/wc_sample_wallets.dart'; +import 'package:web3modal_flutter/services/logger_service/logger_service_singleton.dart'; import 'package:web3modal_flutter/utils/debouncer.dart'; import 'package:web3modal_flutter/utils/url/url_utils_singleton.dart'; import 'package:web3modal_flutter/constants/string_constants.dart'; @@ -20,7 +20,6 @@ import 'package:web3modal_flutter/services/storage_service/storage_service_singl import 'package:web3modal_flutter/utils/core/core_utils_singleton.dart'; import 'package:web3modal_flutter/utils/platform/i_platform_utils.dart'; import 'package:web3modal_flutter/utils/platform/platform_utils_singleton.dart'; -import 'package:web3modal_flutter/utils/w3m_logger.dart'; import 'package:web3modal_flutter/web3modal_flutter.dart'; const int _defaultEntriesCount = 48; @@ -106,14 +105,14 @@ class ExplorerService implements IExplorerService { return; } - W3MLoggerUtil.logger.t('[$runtimeType] init()'); + loggerService.instance.p('[$runtimeType] init()'); _apiUrl = await coreUtils.instance.getApiUrl(); await _setInstalledWalletIdsParam(); await _fetchInitialWallets(); initialized.value = true; - W3MLoggerUtil.logger.t('[$runtimeType] init() done'); + loggerService.instance.p('[$runtimeType] init() done'); } Future _setInstalledWalletIdsParam() async { @@ -199,25 +198,32 @@ class ExplorerService implements IExplorerService { } Future> _fetchNativeAppData() async { + final apiUrl = await coreUtils.instance.getApiUrl(); + final headers = coreUtils.instance.getAPIHeaders(projectId, _referer); + final uri = Platform.isIOS + ? Uri.parse('$apiUrl/getIosData') + : Uri.parse('$apiUrl/getAndroidData'); try { - final apiUrl = await coreUtils.instance.getApiUrl(); - final headers = coreUtils.instance.getAPIHeaders(projectId, _referer); - final uri = Platform.isIOS - ? Uri.parse('$apiUrl/getIosData') - : Uri.parse('$apiUrl/getAndroidData'); final response = await _client.get(uri, headers: headers); - final apiResponse = ApiResponse.fromJson( - jsonDecode(response.body), - (json) => NativeAppData.fromJson(json), - ); - return apiResponse.data.toList(); - } catch (e, s) { - W3MLoggerUtil.logger.e( - '[$runtimeType] Error fetching native apps data', + if (response.statusCode == 200 || response.statusCode == 202) { + final apiResponse = ApiResponse.fromJson( + jsonDecode(response.body), + (json) => NativeAppData.fromJson(json), + ); + return apiResponse.data.toList(); + } else { + loggerService.instance.d( + '⛔ [$runtimeType] error fetching native data $uri', + error: response.statusCode, + ); + return []; + } + } catch (e) { + loggerService.instance.e( + '[$runtimeType] error fetching native data $uri', error: e, - stackTrace: s, ); - throw Exception(e); + return []; } } @@ -270,24 +276,34 @@ class ExplorerService implements IExplorerService { bool updateCount = true, }) async { final p = params?.toJson() ?? {}; + final apiUrl = await coreUtils.instance.getApiUrl(); + final headers = coreUtils.instance.getAPIHeaders(projectId, _referer); + final uri = Uri.parse('$apiUrl/getWallets').replace(queryParameters: p); + loggerService.instance.d('[$runtimeType] fetching $uri'); try { - final apiUrl = await coreUtils.instance.getApiUrl(); - final headers = coreUtils.instance.getAPIHeaders(projectId, _referer); - final uri = Uri.parse('$apiUrl/getWallets').replace(queryParameters: p); final response = await _client.get(uri, headers: headers); - final apiResponse = ApiResponse.fromJson( - jsonDecode(response.body), - (json) => Listing.fromJson(json), - ); - if (updateCount) { - totalListings.value += apiResponse.count; + if (response.statusCode == 200 || response.statusCode == 202) { + final apiResponse = ApiResponse.fromJson( + jsonDecode(response.body), + (json) => Listing.fromJson(json), + ); + if (updateCount) { + totalListings.value += apiResponse.count; + } + return apiResponse.data.toList().toW3MWalletInfo(); + } else { + loggerService.instance.d( + '⛔ [$runtimeType] error fetching listings $uri', + error: response.statusCode, + ); + return []; } - W3MLoggerUtil.logger.t('[$runtimeType] _fetchListings() $uri $p'); - return apiResponse.data.toList().toW3MWalletInfo(); - } catch (error) { - W3MLoggerUtil.logger - .e('[$runtimeType] Error fetch wallets params: $p', error: error); - throw Exception(e); + } catch (e) { + loggerService.instance.d( + '[$runtimeType] error fetching listings: $uri', + error: e, + ); + return []; } } @@ -322,7 +338,7 @@ class ExplorerService implements IExplorerService { return W3MWalletInfo.fromJson(jsonDecode(walletString)); } } catch (e, s) { - W3MLoggerUtil.logger.e( + loggerService.instance.e( '[$runtimeType] error getConnectedWallet:', error: e, stackTrace: s, @@ -352,10 +368,12 @@ class ExplorerService implements IExplorerService { } _listings = currentListings; listings.value = _listings; - W3MLoggerUtil.logger.t('[$runtimeType] _updateRecentWalletId $walletId ' - '${walletInfo?.toJson()}'); + loggerService.instance.p( + '[$runtimeType] _updateRecentWalletId $walletId ' + '${walletInfo?.toJson()}', + ); } catch (e, s) { - W3MLoggerUtil.logger.e( + loggerService.instance.e( '[$runtimeType] _updateRecentWalletId', error: e, stackTrace: s, @@ -383,7 +401,7 @@ class ExplorerService implements IExplorerService { final excludedIds = (excludedWalletIds ?? {}); final exclude = excludedIds.isNotEmpty ? excludedIds.join(',') : null; - W3MLoggerUtil.logger.t('[$runtimeType] search $query'); + loggerService.instance.p('[$runtimeType] search $query'); _currentSearchValue = query; final newListins = await _fetchListings( params: RequestParams( @@ -398,7 +416,7 @@ class ExplorerService implements IExplorerService { ); listings.value = newListins; - W3MLoggerUtil.logger.t('[$runtimeType] _searchListings $query'); + loggerService.instance.p('[$runtimeType] _searchListings $query'); _debouncer.run(() => isSearching.value = false); } diff --git a/lib/utils/w3m_chains_presets.dart b/lib/utils/w3m_chains_presets.dart index 0e20bbb1..9beda43b 100644 --- a/lib/utils/w3m_chains_presets.dart +++ b/lib/utils/w3m_chains_presets.dart @@ -146,6 +146,36 @@ class W3MChainPresets { ), }; + static Map testChains = { + '11155111': W3MChainInfo( + chainName: 'Sepolia', + chainId: '11155111', + namespace: 'eip155:11155111', + tokenName: 'SEP', + rpcUrl: 'https://ethereum-sepolia.publicnode.com', + blockExplorer: W3MBlockExplorer( + name: 'Sepolia Etherscan', + url: 'https://sepolia.etherscan.io/', + ), + ), + '80001': W3MChainInfo( + chainName: 'Mumbai', + namespace: 'eip155:80001', + chainId: '80001', + tokenName: 'MATIC', + rpcUrl: 'https://polygon-mumbai-bor-rpc.publicnode.com', + extraRpcUrls: [ + 'https://rpc.ankr.com/polygon_mumbai', + 'https://polygon-testnet.public.blastapi.io', + 'https://polygon-mumbai.blockpi.network/v1/rpc/public', + ], + blockExplorer: W3MBlockExplorer( + name: 'Explorer', + url: 'https://mumbai.polygonscan.com', + ), + ), + }; + static Map extraChains = { '250': W3MChainInfo( chainName: 'Fantom', From 59a7e33516a5cf9675c04cd42fe9bdfd75aa7e4f Mon Sep 17 00:00:00 2001 From: Alfreedom <00tango.bromine@icloud.com> Date: Tue, 23 Apr 2024 12:18:10 +0200 Subject: [PATCH 3/3] update to walletconnect_flutter_v2: ^2.2.3 --- example/pubspec.lock | 20 ++++++------------- lib/pages/get_wallet_page.dart | 1 + .../explorer_service/explorer_service.dart | 1 + lib/services/magic_service/magic_service.dart | 1 + lib/services/w3m_service/w3m_service.dart | 7 ++++--- lib/utils/platform/platform_utils.dart | 3 ++- .../list_items/download_wallet_item.dart | 2 ++ pubspec.lock | 20 ++++++------------- pubspec.yaml | 2 +- 9 files changed, 24 insertions(+), 33 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 69da415a..edcfed41 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -612,18 +612,18 @@ packages: dependency: transitive description: name: package_info_plus - sha256: cb44f49b6e690fa766f023d5b22cac6b9affe741dd792b6ac7ad4fabe0d7b097 + sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "7.0.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" + sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" path: dependency: transitive description: @@ -981,14 +981,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - universal_io: - dependency: transitive - description: - name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" - url: "https://pub.dev" - source: hosted - version: "2.2.2" url_launcher: dependency: transitive description: @@ -1113,10 +1105,10 @@ packages: dependency: transitive description: name: walletconnect_flutter_v2 - sha256: "8502a7adc59475cad5e968e4f57e6ee5d6a538cce63ca93c7ac1abf5573d5ea5" + sha256: cc6fa6a537910a66258ee64bb510edbfc0dee01485ea1138651431087c94671b url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" watcher: dependency: transitive description: diff --git a/lib/pages/get_wallet_page.dart b/lib/pages/get_wallet_page.dart index b317025a..b8b1bfdd 100644 --- a/lib/pages/get_wallet_page.dart +++ b/lib/pages/get_wallet_page.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:math'; import 'package:flutter/material.dart'; diff --git a/lib/services/explorer_service/explorer_service.dart b/lib/services/explorer_service/explorer_service.dart index 5e11439b..6ea4e029 100644 --- a/lib/services/explorer_service/explorer_service.dart +++ b/lib/services/explorer_service/explorer_service.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; diff --git a/lib/services/magic_service/magic_service.dart b/lib/services/magic_service/magic_service.dart index a0e254fc..eee7ca26 100644 --- a/lib/services/magic_service/magic_service.dart +++ b/lib/services/magic_service/magic_service.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/services/w3m_service/w3m_service.dart b/lib/services/w3m_service/w3m_service.dart index 9825785c..e20381d4 100644 --- a/lib/services/w3m_service/w3m_service.dart +++ b/lib/services/w3m_service/w3m_service.dart @@ -366,9 +366,10 @@ class W3MService with ChangeNotifier, CoinbaseService implements IW3MService { } } - // bool get _isMM => (_currentSession?.peer?.metadata.name ?? '') - // .toLowerCase() - // .contains('metamask'); + // bool get _isMM { + // final walletName = _currentSession?.peer?.metadata.name ?? ''; + // return walletName.contains('metamask'); + // } /// Will get the list of available chains to add @override diff --git a/lib/utils/platform/platform_utils.dart b/lib/utils/platform/platform_utils.dart index e1c7f865..9d7d3c4d 100644 --- a/lib/utils/platform/platform_utils.dart +++ b/lib/utils/platform/platform_utils.dart @@ -1,7 +1,8 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:web3modal_flutter/utils/platform/i_platform_utils.dart'; -import 'package:web3modal_flutter/web3modal_flutter.dart'; class PlatformUtils extends IPlatformUtils { @override diff --git a/lib/widgets/lists/list_items/download_wallet_item.dart b/lib/widgets/lists/list_items/download_wallet_item.dart index 4beaaeef..f9899275 100644 --- a/lib/widgets/lists/list_items/download_wallet_item.dart +++ b/lib/widgets/lists/list_items/download_wallet_item.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher_string.dart'; diff --git a/pubspec.lock b/pubspec.lock index dbc5fe6f..326e3576 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -588,18 +588,18 @@ packages: dependency: transitive description: name: package_info_plus - sha256: cb44f49b6e690fa766f023d5b22cac6b9affe741dd792b6ac7ad4fabe0d7b097 + sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "7.0.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" + sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" path: dependency: transitive description: @@ -957,14 +957,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - universal_io: - dependency: transitive - description: - name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" - url: "https://pub.dev" - source: hosted - version: "2.2.2" url_launcher: dependency: "direct main" description: @@ -1089,10 +1081,10 @@ packages: dependency: "direct main" description: name: walletconnect_flutter_v2 - sha256: "8502a7adc59475cad5e968e4f57e6ee5d6a538cce63ca93c7ac1abf5573d5ea5" + sha256: cc6fa6a537910a66258ee64bb510edbfc0dee01485ea1138651431087c94671b url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0a8664e8..6e7c7e9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: shimmer: ^3.0.0 url_launcher: ^6.2.5 uuid: ^4.3.3 - walletconnect_flutter_v2: ^2.2.2 + walletconnect_flutter_v2: ^2.2.3 webview_flutter: ^4.7.0 webview_flutter_android: ^3.16.0 webview_flutter_wkwebview: ^3.13.0