From 461fe1c85990e94d4e18329c2ea9813ce4dbb197 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 23 May 2024 16:21:51 +0100 Subject: [PATCH 1/7] fix: Desktop resize bug (#1461) * fix: Desktop resize bug * Change default spl tokens * Minor enhancements [skip ci] * minor enhancements [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> --- cw_solana/lib/default_spl_tokens.dart | 87 ++++++++-------- lib/src/screens/dashboard/dashboard_page.dart | 98 ++++++++++++------- lib/utils/responsive_layout_util.dart | 6 +- 3 files changed, 114 insertions(+), 77 deletions(-) diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart index 7acad78e0..21b5ef79d 100644 --- a/cw_solana/lib/default_spl_tokens.dart +++ b/cw_solana/lib/default_spl_tokens.dart @@ -19,30 +19,6 @@ class DefaultSPLTokens { mint: 'usdcsol', enabled: true, ), - SPLToken( - name: 'Wrapped Ethereum (Sollet)', - symbol: 'soETH', - mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', - decimal: 6, - mint: 'soEth', - iconPath: 'assets/images/eth_icon.png', - ), - SPLToken( - name: 'Wrapped SOL', - symbol: 'WSOL', - mintAddress: 'So11111111111111111111111111111111111111112', - decimal: 9, - mint: 'WSOL', - iconPath: 'assets/images/sol_icon.png', - ), - SPLToken( - name: 'Wrapped Bitcoin (Sollet)', - symbol: 'BTC', - mintAddress: '9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E', - decimal: 6, - mint: 'btcsol', - iconPath: 'assets/images/btc.png', - ), SPLToken( name: 'Bonk', symbol: 'Bonk', @@ -50,21 +26,7 @@ class DefaultSPLTokens { decimal: 5, mint: 'Bonk', iconPath: 'assets/images/bonk_icon.png', - ), - SPLToken( - name: 'Helium Network Token', - symbol: 'HNT', - mintAddress: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', - decimal: 8, - mint: 'hnt', - iconPath: 'assets/images/hnt_icon.png', - ), - SPLToken( - name: 'Pyth Network', - symbol: 'PYTH', - mintAddress: 'HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3', - decimal: 6, - mint: 'pyth', + enabled: true, ), SPLToken( name: 'Raydium', @@ -73,6 +35,51 @@ class DefaultSPLTokens { decimal: 6, mint: 'ray', iconPath: 'assets/images/ray_icon.png', + enabled: true, + ), + SPLToken( + name: 'Wrapped Ethereum (Sollet)', + symbol: 'soETH', + mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', + decimal: 6, + mint: 'soEth', + iconPath: 'assets/images/eth_icon.png', + enabled: false, + ), + SPLToken( + name: 'Wrapped SOL', + symbol: 'WSOL', + mintAddress: 'So11111111111111111111111111111111111111112', + decimal: 9, + mint: 'WSOL', + iconPath: 'assets/images/sol_icon.png', + enabled: false, + ), + SPLToken( + name: 'Wrapped Bitcoin (Sollet)', + symbol: 'BTC', + mintAddress: '9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E', + decimal: 6, + mint: 'btcsol', + iconPath: 'assets/images/btc.png', + enabled: false, + ), + SPLToken( + name: 'Helium Network Token', + symbol: 'HNT', + mintAddress: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', + decimal: 8, + mint: 'hnt', + iconPath: 'assets/images/hnt_icon.png', + enabled: false, + ), + SPLToken( + name: 'Pyth Network', + symbol: 'PYTH', + mintAddress: 'HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3', + decimal: 6, + mint: 'pyth', + enabled: false, ), SPLToken( name: 'GMT', @@ -81,6 +88,7 @@ class DefaultSPLTokens { decimal: 6, mint: 'ray', iconPath: 'assets/images/gmt_icon.png', + enabled: false, ), SPLToken( name: 'AvocadoCoin', @@ -89,6 +97,7 @@ class DefaultSPLTokens { decimal: 8, mint: 'avdo', iconPath: 'assets/images/avdo_icon.png', + enabled: false, ), ]; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 8d9dc9829..ec97d191f 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -36,7 +36,7 @@ import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart' import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; -class DashboardPage extends StatelessWidget { +class DashboardPage extends StatefulWidget { DashboardPage({ required this.bottomSheetService, required this.balancePage, @@ -50,43 +50,71 @@ class DashboardPage extends StatelessWidget { final WalletAddressListViewModel addressListViewModel; @override - Widget build(BuildContext context) { - final screenHeight = MediaQuery.of(context).size.height; - return Scaffold( - body: Builder( - builder: (_) { - final dashboardPageView = RefreshIndicator( - displacement: screenHeight * 0.1, - onRefresh: () async => await dashboardViewModel.refreshDashboard(), - child: SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: Container( - height: screenHeight, - child: _DashboardPageView( - balancePage: balancePage, - bottomSheetService: bottomSheetService, - dashboardViewModel: dashboardViewModel, - addressListViewModel: addressListViewModel, - ), - ), - ), - ); + State<DashboardPage> createState() => _DashboardPageState(); +} - if (DeviceInfo.instance.isDesktop) { - if (responsiveLayoutUtil.screenWidth > - ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { - return getIt.get<DesktopSidebarWrapper>(); - } else { - return dashboardPageView; - } - } else if (responsiveLayoutUtil.shouldRenderMobileUI) { - return dashboardPageView; - } else { - return getIt.get<DesktopSidebarWrapper>(); - } - }, +class _DashboardPageState extends State<DashboardPage> { + @override + void initState() { + super.initState(); + + bool isMobileLayout = + responsiveLayoutUtil.screenWidth < ResponsiveLayoutUtilBase.kMobileThreshold; + + reaction((_) => responsiveLayoutUtil.screenWidth, (screenWidth) { + // Check if it was previously in mobile layout, and now changing to desktop + if (isMobileLayout && + screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + setState(() { + isMobileLayout = false; + }); + } + + // Check if it was previously in desktop layout, and now changing to mobile + if (!isMobileLayout && + screenWidth <= ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + setState(() { + isMobileLayout = true; + }); + } + }); + } + + @override + Widget build(BuildContext context) { + Widget dashboardChild; + + final dashboardPageView = RefreshIndicator( + displacement: responsiveLayoutUtil.screenHeight * 0.1, + onRefresh: () async => await widget.dashboardViewModel.refreshDashboard(), + child: SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: Container( + height: responsiveLayoutUtil.screenHeight, + child: _DashboardPageView( + balancePage: widget.balancePage, + bottomSheetService: widget.bottomSheetService, + dashboardViewModel: widget.dashboardViewModel, + addressListViewModel: widget.addressListViewModel, + ), + ), ), ); + + if (DeviceInfo.instance.isDesktop) { + if (responsiveLayoutUtil.screenWidth > + ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + dashboardChild = getIt.get<DesktopSidebarWrapper>(); + } else { + dashboardChild = dashboardPageView; + } + } else if (responsiveLayoutUtil.shouldRenderMobileUI) { + dashboardChild = dashboardPageView; + } else { + dashboardChild = getIt.get<DesktopSidebarWrapper>(); + } + + return Scaffold(body: dashboardChild); } } diff --git a/lib/utils/responsive_layout_util.dart b/lib/utils/responsive_layout_util.dart index 86a4a3776..aa30b3f07 100644 --- a/lib/utils/responsive_layout_util.dart +++ b/lib/utils/responsive_layout_util.dart @@ -6,7 +6,7 @@ part 'responsive_layout_util.g.dart'; class _ResponsiveLayoutUtil = ResponsiveLayoutUtilBase with _$_ResponsiveLayoutUtil; abstract class ResponsiveLayoutUtilBase with Store, WidgetsBindingObserver { - static const double _kMobileThreshold = 550; + static const double kMobileThreshold = 550; static const double kDesktopMaxWidthConstraint = 400; static const double kDesktopMaxDashBoardWidthConstraint = 900; static const double kPopupWidth = 400; @@ -42,13 +42,13 @@ abstract class ResponsiveLayoutUtilBase with Store, WidgetsBindingObserver { @computed bool get shouldRenderMobileUI { - return (screenWidth <= _kMobileThreshold) || + return (screenWidth <= kMobileThreshold) || (orientation == Orientation.portrait && screenWidth < screenHeight) || (orientation == Orientation.landscape && screenWidth < screenHeight); } bool get shouldRenderTabletUI { - return screenWidth > _kMobileThreshold && screenWidth < kDesktopMaxDashBoardWidthConstraint; + return screenWidth > kMobileThreshold && screenWidth < kDesktopMaxDashBoardWidthConstraint; } } From 7d0720b21d0492951e508614384bef77808d591c Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Thu, 23 May 2024 19:43:05 +0300 Subject: [PATCH 2/7] Generic enhancements (#1464) * Fix wallet not considering seed length for Tron, Polygon and Solana * Change Trocador to be prioritized if same rate [skip ci] --- lib/core/wallet_creation_service.dart | 21 ++++++++++++++++++- .../exchange/exchange_view_model.dart | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index a55e9ee3f..1fa50a6be 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -58,7 +58,7 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; - if (type == WalletType.bitcoinCash || type == WalletType.ethereum) { + if (_hasSeedPhraseLengthOption) { credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; } await keyService.saveWalletPassword(password: password, walletName: credentials.name); @@ -72,6 +72,25 @@ class WalletCreationService { return wallet; } + bool get _hasSeedPhraseLengthOption { + switch (type) { + case WalletType.ethereum: + case WalletType.bitcoinCash: + case WalletType.polygon: + case WalletType.solana: + case WalletType.tron: + return true; + case WalletType.monero: + case WalletType.none: + case WalletType.bitcoin: + case WalletType.litecoin: + case WalletType.haven: + case WalletType.nano: + case WalletType.banano: + return false; + } + } + Future<WalletBase> restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 1560a4be0..5e0443bf8 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -154,11 +154,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with ChangeNowExchangeProvider(settingsStore: _settingsStore), SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), - TrocadorExchangeProvider( - useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates), ThorChainExchangeProvider(tradesStore: trades), if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(), QuantexExchangeProvider(), + TrocadorExchangeProvider( + useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates), ]; @observable From 0dc53895c60f8e8317fc7dd4b29d1c93a49258ba Mon Sep 17 00:00:00 2001 From: tuxsudo <tuxsudo@tux.pizza> Date: Sat, 25 May 2024 10:57:30 -0400 Subject: [PATCH 3/7] Fix connection leak when service bulletin is disabled (#1465) * Fix connection leak when service bulletin disabled * Update dashboard_view_model.dart --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --- .../dashboard/dashboard_view_model.dart | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index bd8ae6dda..f438c5724 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -535,24 +535,29 @@ abstract class DashboardViewModelBase with Store { Future<ServicesResponse> getServicesStatus() async { try { - final res = await http.get(Uri.parse("https://service-api.cakewallet.com/v1/active-notices")); + if (isEnabledBulletinAction) { + final res = await http.get(Uri.parse("https://service-api.cakewallet.com/v1/active-notices")); - if (res.statusCode < 200 || res.statusCode >= 300) { - throw res.body; + if (res.statusCode < 200 || res.statusCode >= 300) { + throw res.body; + } + + final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey); + + final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body)); + final currentSha = bytesToHex(hash.bytes); + + final hasUpdates = oldSha != currentSha; + + return ServicesResponse.fromJson( + json.decode(res.body) as Map<String, dynamic>, + hasUpdates, + currentSha, + ); } - - final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey); - - final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body)); - final currentSha = bytesToHex(hash.bytes); - - final hasUpdates = oldSha != currentSha; - - return ServicesResponse.fromJson( - json.decode(res.body) as Map<String, dynamic>, - hasUpdates, - currentSha, - ); + else { + return ServicesResponse([], false, ''); + } } catch (_) { return ServicesResponse([], false, ''); } From 8c1206ea04ac64ff43a35ffac7d3a73ec564d7fb Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich <konstantinullrich12@gmail.com> Date: Sat, 25 May 2024 16:59:29 +0200 Subject: [PATCH 4/7] Hide "Show Seed" Option on Hardware Wallets (#1463) --- lib/di.dart | 14 ++++++------ .../settings/security_backup_page.dart | 22 ++++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index c039b68f4..6a97cf62c 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -14,6 +14,7 @@ import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cake_wallet/core/key_service.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; @@ -26,10 +27,6 @@ import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; -import 'package:cake_wallet/view_model/link_view_model.dart'; -import 'package:cake_wallet/tron/tron.dart'; -import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; -import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; @@ -124,6 +121,7 @@ import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; @@ -147,6 +145,7 @@ import 'package:cake_wallet/store/templates/send_template_store.dart'; import 'package:cake_wallet/store/wallet_list_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -179,6 +178,7 @@ import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model. import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; +import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; @@ -222,6 +222,7 @@ import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/nano_account.dart'; import 'package:cw_core/node.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_info.dart'; @@ -233,7 +234,6 @@ import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:cake_wallet/core/secure_storage.dart'; import 'buy/dfx/dfx_buy_provider.dart'; import 'core/totp_request_details.dart'; @@ -795,8 +795,8 @@ Future<void> setup({ getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>())); - getIt.registerFactory( - () => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(), getIt.get<AuthService>())); + getIt.registerFactory(() => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(), + getIt.get<AuthService>(), getIt.get<AppStore>().wallet!.isHardwareWallet)); getIt.registerFactory(() => PrivacyPage(getIt.get<PrivacySettingsViewModel>())); diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 1f0f58ad4..470f49190 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -9,14 +9,13 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class SecurityBackupPage extends BasePage { - SecurityBackupPage(this._securitySettingsViewModel, this._authService); + SecurityBackupPage(this._securitySettingsViewModel, this._authService, [this._isHardwareWallet = false]); final AuthService _authService; @@ -25,20 +24,23 @@ class SecurityBackupPage extends BasePage { final SecuritySettingsViewModel _securitySettingsViewModel; + final bool _isHardwareWallet; + @override Widget body(BuildContext context) { return Container( padding: EdgeInsets.only(top: 10), child: Column(mainAxisSize: MainAxisSize.min, children: [ - SettingsCellWithArrow( - title: S.current.show_keys, - handler: (_) => _authService.authenticateAction( - context, - route: Routes.showKeys, - conditionToDetermineIfToUse2FA: _securitySettingsViewModel - .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + if (!_isHardwareWallet) + SettingsCellWithArrow( + title: S.current.show_keys, + handler: (_) => _authService.authenticateAction( + context, + route: Routes.showKeys, + conditionToDetermineIfToUse2FA: + _securitySettingsViewModel.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + ), ), - ), SettingsCellWithArrow( title: S.current.create_backup, handler: (_) => _authService.authenticateAction( From 058522caf1f1250c61ff9ad0408cae0e8e1e2150 Mon Sep 17 00:00:00 2001 From: Omar Hatem <omarh.ismail1@gmail.com> Date: Sun, 26 May 2024 18:09:39 +0300 Subject: [PATCH 5/7] Fix Contact page reaction excuted more than once (#1467) --- lib/src/screens/contact/contact_page.dart | 29 ++++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/src/screens/contact/contact_page.dart b/lib/src/screens/contact/contact_page.dart index 099be41d5..7dea970ec 100644 --- a/lib/src/screens/contact/contact_page.dart +++ b/lib/src/screens/contact/contact_page.dart @@ -46,6 +46,7 @@ class ContactPage extends BasePage { final TextEditingController _nameController; final TextEditingController _currencyTypeController; final TextEditingController _addressController; + bool _isEffectsApplied = false; @override Widget body(BuildContext context) { @@ -53,15 +54,7 @@ class ContactPage extends BasePage { color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor, height: 8); - reaction((_) => contactViewModel.state, (ExecutionState state) { - if (state is FailureState) { - _onContactSavingFailure(context, state.error); - } - - if (state is ExecutedSuccessfullyState) { - _onContactSavedSuccessfully(context); - } - }); + _setEffects(context); return Observer( builder: (_) => ScrollableWithBottomSection( @@ -177,4 +170,22 @@ class ContactPage extends BasePage { void _onContactSavedSuccessfully(BuildContext context) => Navigator.of(context).pop(); + + void _setEffects(BuildContext context) { + if (_isEffectsApplied) { + return; + } + + _isEffectsApplied = true; + + reaction((_) => contactViewModel.state, (ExecutionState state) { + if (state is FailureState) { + _onContactSavingFailure(context, state.error); + } + + if (state is ExecutedSuccessfullyState) { + _onContactSavedSuccessfully(context); + } + }); + } } From 24f6541fa696c756c12aa2d9afa94d13aff6a0a8 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 28 May 2024 14:32:36 +0100 Subject: [PATCH 6/7] CW-647-Birdpay-Trc20 (#1469) * fix: Desktop resize bug * fix: Birdpay working for trc20 and adjust transaction fee currency * fix: Filter logic * fix: Solana token balance not fully displaying * fix: Minor enhancements --- cw_core/lib/crypto_currency.dart | 2 +- cw_solana/lib/solana_balance.dart | 4 ++-- lib/view_model/send/send_view_model.dart | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index fabc84051..fb702eca1 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -253,7 +253,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) { try { return CryptoCurrency.all.firstWhere((element) => - element.title.toLowerCase() == name && + element.title.toLowerCase() == name.toLowerCase() && (element.tag == null || element.tag == walletCurrency?.title || element.tag == walletCurrency?.tag)); diff --git a/cw_solana/lib/solana_balance.dart b/cw_solana/lib/solana_balance.dart index b1f0ef153..e88a510dd 100644 --- a/cw_solana/lib/solana_balance.dart +++ b/cw_solana/lib/solana_balance.dart @@ -15,8 +15,8 @@ class SolanaBalance extends Balance { String _balanceFormatted() { String stringBalance = balance.toString(); - if (stringBalance.toString().length >= 6) { - stringBalance = stringBalance.substring(0, 6); + if (stringBalance.toString().length >= 12) { + stringBalance = stringBalance.substring(0, 12); } return stringBalance; } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 4b30ecef3..534e501dd 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -139,8 +139,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor String get pendingTransactionFeeFiatAmount { try { if (pendingTransaction != null) { - final currency = - isEVMCompatibleChain(walletType) ? wallet.currency : selectedCryptoCurrency; + final currency = pendingTransactionFeeCurrency(walletType); final fiat = calculateFiatAmount( price: _fiatConversationStore.prices[currency]!, cryptoAmount: pendingTransaction!.feeFormatted); @@ -153,6 +152,18 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } } + CryptoCurrency pendingTransactionFeeCurrency(WalletType type) { + switch (type) { + case WalletType.ethereum: + case WalletType.polygon: + case WalletType.tron: + case WalletType.solana: + return wallet.currency; + default: + return selectedCryptoCurrency; + } + } + FiatCurrency get fiat => _settingsStore.fiatCurrency; TransactionPriority get transactionPriority { From faa49d21e8ab99303d756e98447c908669141515 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich <konstantinullrich12@gmail.com> Date: Tue, 28 May 2024 15:32:48 +0200 Subject: [PATCH 7/7] Potential fix for missing polyseeds in the future (#1468) --- cw_monero/ios/Classes/monero_api.cpp | 11 ++ cw_monero/lib/api/signatures.dart | 4 + cw_monero/lib/api/types.dart | 4 + cw_monero/lib/api/wallet.dart | 145 ++++++++++++++------------- 4 files changed, 94 insertions(+), 70 deletions(-) diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 87be785ac..01a8d9a51 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -399,6 +399,7 @@ extern "C" return false; } + wallet->store(std::string(path)); change_current_wallet(wallet); return true; } @@ -464,6 +465,16 @@ extern "C" return strdup(get_current_wallet()->address(account_index, address_index).c_str()); } + char *get_cache_attribute(char *name) + { + return strdup(get_current_wallet()->getCacheAttribute(std::string(name)).c_str()); + } + + bool set_cache_attribute(char *name, char *value) + { + get_current_wallet()->setCacheAttribute(std::string(name), std::string(value)); + return true; + } const char *seed() { diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index bba7b5528..40f338c8c 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -154,3 +154,7 @@ typedef freeze_coin = Void Function(Int32 index); typedef thaw_coin = Void Function(Int32 index); typedef sign_message = Pointer<Utf8> Function(Pointer<Utf8> message, Pointer<Utf8> address); + +typedef get_cache_attribute = Pointer<Utf8> Function(Pointer<Utf8> name); + +typedef set_cache_attribute = Int8 Function(Pointer<Utf8> name, Pointer<Utf8> value); diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 87d8a153e..6b36ab5e3 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -154,3 +154,7 @@ typedef FreezeCoin = void Function(int); typedef ThawCoin = void Function(int); typedef SignMessage = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>); + +typedef GetCacheAttribute = Pointer<Utf8> Function(Pointer<Utf8>); + +typedef SetCacheAttribute = int Function(Pointer<Utf8>, Pointer<Utf8>); diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index ffa5fe13b..448c661e6 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -1,26 +1,24 @@ import 'dart:async'; import 'dart:ffi'; -import 'package:ffi/ffi.dart'; -import 'package:cw_monero/api/structs/ut8_box.dart'; + import 'package:cw_monero/api/convert_utf8_to_string.dart'; -import 'package:cw_monero/api/signatures.dart'; -import 'package:cw_monero/api/types.dart'; -import 'package:cw_monero/api/monero_api.dart'; import 'package:cw_monero/api/exceptions/setup_wallet_exception.dart'; +import 'package:cw_monero/api/monero_api.dart'; +import 'package:cw_monero/api/signatures.dart'; +import 'package:cw_monero/api/structs/ut8_box.dart'; +import 'package:cw_monero/api/types.dart'; +import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; int _boolToInt(bool value) => value ? 1 : 0; -final getFileNameNative = moneroApi - .lookup<NativeFunction<get_filename>>('get_filename') - .asFunction<GetFilename>(); +final getFileNameNative = + moneroApi.lookup<NativeFunction<get_filename>>('get_filename').asFunction<GetFilename>(); -final getSeedNative = - moneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>(); +final getSeedNative = moneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>(); -final getAddressNative = moneroApi - .lookup<NativeFunction<get_address>>('get_address') - .asFunction<GetAddress>(); +final getAddressNative = + moneroApi.lookup<NativeFunction<get_address>>('get_address').asFunction<GetAddress>(); final getFullBalanceNative = moneroApi .lookup<NativeFunction<get_full_balanace>>('get_full_balance') @@ -38,41 +36,34 @@ final getNodeHeightNative = moneroApi .lookup<NativeFunction<get_node_height>>('get_node_height') .asFunction<GetNodeHeight>(); -final isConnectedNative = moneroApi - .lookup<NativeFunction<is_connected>>('is_connected') - .asFunction<IsConnected>(); +final isConnectedNative = + moneroApi.lookup<NativeFunction<is_connected>>('is_connected').asFunction<IsConnected>(); -final setupNodeNative = moneroApi - .lookup<NativeFunction<setup_node>>('setup_node') - .asFunction<SetupNode>(); +final setupNodeNative = + moneroApi.lookup<NativeFunction<setup_node>>('setup_node').asFunction<SetupNode>(); -final startRefreshNative = moneroApi - .lookup<NativeFunction<start_refresh>>('start_refresh') - .asFunction<StartRefresh>(); +final startRefreshNative = + moneroApi.lookup<NativeFunction<start_refresh>>('start_refresh').asFunction<StartRefresh>(); final connecToNodeNative = moneroApi .lookup<NativeFunction<connect_to_node>>('connect_to_node') .asFunction<ConnectToNode>(); final setRefreshFromBlockHeightNative = moneroApi - .lookup<NativeFunction<set_refresh_from_block_height>>( - 'set_refresh_from_block_height') + .lookup<NativeFunction<set_refresh_from_block_height>>('set_refresh_from_block_height') .asFunction<SetRefreshFromBlockHeight>(); final setRecoveringFromSeedNative = moneroApi - .lookup<NativeFunction<set_recovering_from_seed>>( - 'set_recovering_from_seed') + .lookup<NativeFunction<set_recovering_from_seed>>('set_recovering_from_seed') .asFunction<SetRecoveringFromSeed>(); -final storeNative = - moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>(); +final storeNative = moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>(); final setPasswordNative = moneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>(); -final setListenerNative = moneroApi - .lookup<NativeFunction<set_listener>>('set_listener') - .asFunction<SetListener>(); +final setListenerNative = + moneroApi.lookup<NativeFunction<set_listener>>('set_listener').asFunction<SetListener>(); final getSyncingHeightNative = moneroApi .lookup<NativeFunction<get_syncing_height>>('get_syncing_height') @@ -83,8 +74,7 @@ final isNeededToRefreshNative = moneroApi .asFunction<IsNeededToRefresh>(); final isNewTransactionExistNative = moneroApi - .lookup<NativeFunction<is_new_transaction_exist>>( - 'is_new_transaction_exist') + .lookup<NativeFunction<is_new_transaction_exist>>('is_new_transaction_exist') .asFunction<IsNewTransactionExist>(); final getSecretViewKeyNative = moneroApi @@ -107,9 +97,8 @@ final closeCurrentWalletNative = moneroApi .lookup<NativeFunction<close_current_wallet>>('close_current_wallet') .asFunction<CloseCurrentWallet>(); -final onStartupNative = moneroApi - .lookup<NativeFunction<on_startup>>('on_startup') - .asFunction<OnStartup>(); +final onStartupNative = + moneroApi.lookup<NativeFunction<on_startup>>('on_startup').asFunction<OnStartup>(); final rescanBlockchainAsyncNative = moneroApi .lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain') @@ -123,13 +112,19 @@ final setTrustedDaemonNative = moneroApi .lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon') .asFunction<SetTrustedDaemon>(); -final trustedDaemonNative = moneroApi - .lookup<NativeFunction<trusted_daemon>>('trusted_daemon') - .asFunction<TrustedDaemon>(); +final trustedDaemonNative = + moneroApi.lookup<NativeFunction<trusted_daemon>>('trusted_daemon').asFunction<TrustedDaemon>(); -final signMessageNative = moneroApi - .lookup<NativeFunction<sign_message>>('sign_message') - .asFunction<SignMessage>(); +final signMessageNative = + moneroApi.lookup<NativeFunction<sign_message>>('sign_message').asFunction<SignMessage>(); + +final getCacheAttributeNative = moneroApi + .lookup<NativeFunction<get_cache_attribute>>('get_cache_attribute') + .asFunction<GetCacheAttribute>(); + +final setCacheAttributeNative = moneroApi + .lookup<NativeFunction<set_cache_attribute>>('set_cache_attribute') + .asFunction<SetCacheAttribute>(); int getSyncingHeight() => getSyncingHeightNative(); @@ -144,11 +139,9 @@ String getSeed() => convertUTF8ToString(pointer: getSeedNative()); String getAddress({int accountIndex = 0, int addressIndex = 0}) => convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex)); -int getFullBalance({int accountIndex = 0}) => - getFullBalanceNative(accountIndex); +int getFullBalance({int accountIndex = 0}) => getFullBalanceNative(accountIndex); -int getUnlockedBalance({int accountIndex = 0}) => - getUnlockedBalanceNative(accountIndex); +int getUnlockedBalance({int accountIndex = 0}) => getUnlockedBalanceNative(accountIndex); int getCurrentHeight() => getCurrentHeightNative(); @@ -187,7 +180,7 @@ bool setupNodeSync( passwordPointer, _boolToInt(useSSL), _boolToInt(isLightWallet), - socksProxyAddressPointer, + socksProxyAddressPointer, errorMessagePointer) != 0; @@ -202,8 +195,7 @@ bool setupNodeSync( } if (!isSetupNode) { - throw SetupWalletException( - message: convertUTF8ToString(pointer: errorMessagePointer)); + throw SetupWalletException(message: convertUTF8ToString(pointer: errorMessagePointer)); } return isSetupNode; @@ -213,8 +205,7 @@ void startRefreshSync() => startRefreshNative(); Future<bool> connectToNode() async => connecToNodeNative() != 0; -void setRefreshFromBlockHeight({required int height}) => - setRefreshFromBlockHeightNative(height); +void setRefreshFromBlockHeight({required int height}) => setRefreshFromBlockHeightNative(height); void setRecoveringFromSeed({required bool isRecovery}) => setRecoveringFromSeedNative(_boolToInt(isRecovery)); @@ -230,7 +221,7 @@ void setPasswordSync(String password) { final errorMessagePointer = calloc<Utf8Box>(); final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0; calloc.free(passwordPointer); - + if (!changed) { final message = errorMessagePointer.ref.getValue(); calloc.free(errorMessagePointer); @@ -242,24 +233,19 @@ void setPasswordSync(String password) { void closeCurrentWallet() => closeCurrentWalletNative(); -String getSecretViewKey() => - convertUTF8ToString(pointer: getSecretViewKeyNative()); +String getSecretViewKey() => convertUTF8ToString(pointer: getSecretViewKeyNative()); -String getPublicViewKey() => - convertUTF8ToString(pointer: getPublicViewKeyNative()); +String getPublicViewKey() => convertUTF8ToString(pointer: getPublicViewKeyNative()); -String getSecretSpendKey() => - convertUTF8ToString(pointer: getSecretSpendKeyNative()); +String getSecretSpendKey() => convertUTF8ToString(pointer: getSecretSpendKeyNative()); -String getPublicSpendKey() => - convertUTF8ToString(pointer: getPublicSpendKeyNative()); +String getPublicSpendKey() => convertUTF8ToString(pointer: getPublicSpendKeyNative()); class SyncListener { - SyncListener(this.onNewBlock, this.onNewTransaction) - : _cachedBlockchainHeight = 0, - _lastKnownBlockHeight = 0, - _initialSyncHeight = 0; - + SyncListener(this.onNewBlock, this.onNewTransaction) + : _cachedBlockchainHeight = 0, + _lastKnownBlockHeight = 0, + _initialSyncHeight = 0; void Function(int, int, double) onNewBlock; void Function() onNewTransaction; @@ -281,8 +267,7 @@ class SyncListener { _cachedBlockchainHeight = 0; _lastKnownBlockHeight = 0; _initialSyncHeight = 0; - _updateSyncInfoTimer ??= - Timer.periodic(Duration(milliseconds: 1200), (_) async { + _updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async { if (isNewTransactionExist()) { onNewTransaction(); } @@ -321,8 +306,8 @@ class SyncListener { void stop() => _updateSyncInfoTimer?.cancel(); } -SyncListener setListeners(void Function(int, int, double) onNewBlock, - void Function() onNewTransaction) { +SyncListener setListeners( + void Function(int, int, double) onNewBlock, void Function() onNewTransaction) { final listener = SyncListener(onNewBlock, onNewTransaction); setListenerNative(); return listener; @@ -364,7 +349,7 @@ Future<void> setupNode( bool isLightWallet = false}) => compute<Map<String, Object?>, void>(_setupNodeSync, { 'address': address, - 'login': login , + 'login': login, 'password': password, 'useSSL': useSSL, 'isLightWallet': isLightWallet, @@ -397,3 +382,23 @@ String signMessage(String message, {String address = ""}) { return signature; } + +bool setCacheAttribute(String name, String value) { + final namePointer = name.toNativeUtf8(); + final valuePointer = value.toNativeUtf8(); + + final isSet = setCacheAttributeNative(namePointer, valuePointer); + calloc.free(namePointer); + calloc.free(valuePointer); + + return isSet == 1; +} + +String getCacheAttribute(String name) { + final namePointer = name.toNativeUtf8(); + + final value = convertUTF8ToString(pointer: getCacheAttributeNative(namePointer)); + calloc.free(namePointer); + + return value; +}