From a164e5defcd311ed0d13b989b24ffacfea75d60a Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Sat, 4 Nov 2023 23:36:56 +0000 Subject: [PATCH 01/17] Updated FR translations (#1162) --- res/values/strings_fr.arb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index a65442850..d4d27ae0b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -720,15 +720,15 @@ "message": "Message", "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", "totp_auth_url": "URL D'AUTORISATION TOTP", - "awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement.", - "copyWalletConnectLink": "Copiez le lien WalletConnect depuis dApp et collez-le ici", + "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", + "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé de graines", - "enter_seed_phrase": "Entrez votre phrase de semence", + "seed_key": "Clé secrète (seed key)", + "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "add_contact": "Ajouter le contact", - "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Recherches de domaine", - "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", + "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer" } From fdeee8874a8d0bdd1fbaebb27d235c191ea019c0 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 14 Nov 2023 15:56:36 -0600 Subject: [PATCH 02/17] disable bio auth (#1172) * disable bio auth * enforce dark theme on desktop platforms --------- Co-authored-by: fossephate --- lib/core/backup_service.dart | 63 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 520447dd4..85fd8f588 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; @@ -254,7 +255,8 @@ class BackupService { final lookupsENS = data[PreferencesKey.lookupsENS] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncMode = data[PreferencesKey.syncModeKey] as int?; - final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; + final autoGenerateSubaddressStatus = + data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName); @@ -291,9 +293,12 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - if (allowBiometricalAuthentication != null && !Platform.isMacOS && !Platform.isLinux) + if (Platform.isMacOS || Platform.isLinux) { + await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false); + } else if (allowBiometricalAuthentication != null) { await _sharedPreferences.setBool( PreferencesKey.allowBiometricalAuthenticationKey, allowBiometricalAuthentication); + } if (currentBitcoinElectrumSererId != null) await _sharedPreferences.setInt( @@ -309,14 +314,19 @@ class BackupService { if (fiatApiMode != null) await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode); if (autoGenerateSubaddressStatus != null) - await _sharedPreferences.setInt(PreferencesKey.autoGenerateSubaddressStatusKey, - autoGenerateSubaddressStatus); + await _sharedPreferences.setInt( + PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus); if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); - if (currentTheme != null && DeviceInfo.instance.isMobile) + if (currentTheme != null && DeviceInfo.instance.isMobile) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme); + // enforce dark theme on desktop platforms until the design is ready: + } else if (DeviceInfo.instance.isDesktop) { + await _sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw); + } + if (exchangeStatus != null) await _sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus); @@ -389,19 +399,17 @@ class BackupService { await _sharedPreferences.setBool(PreferencesKey.lookupsYatService, lookupsYatService); if (lookupsUnstoppableDomains != null) - await _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains); + await _sharedPreferences.setBool( + PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains); if (lookupsOpenAlias != null) await _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, lookupsOpenAlias); - if (lookupsENS != null) - await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); + if (lookupsENS != null) await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); - if (syncAll != null) - await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); + if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); - if (syncMode != null) - await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode); + if (syncMode != null) await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode); await preferencesFile.delete(); } @@ -505,7 +513,8 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey), PreferencesKey.disableBuyKey: _sharedPreferences.getBool(PreferencesKey.disableBuyKey), PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey), - PreferencesKey.defaultBuyProvider: _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), + PreferencesKey.defaultBuyProvider: + _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), PreferencesKey.isDarkThemeLegacy: _sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy), PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength), @@ -547,28 +556,20 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets), PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings: _sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings), - PreferencesKey.sortBalanceBy: - _sharedPreferences.getInt(PreferencesKey.sortBalanceBy), + PreferencesKey.sortBalanceBy: _sharedPreferences.getInt(PreferencesKey.sortBalanceBy), PreferencesKey.pinNativeTokenAtTop: _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), - PreferencesKey.useEtherscan: - _sharedPreferences.getBool(PreferencesKey.useEtherscan), - PreferencesKey.lookupsTwitter: - _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), - PreferencesKey.lookupsMastodon: - _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), + PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan), + PreferencesKey.lookupsTwitter: _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), + PreferencesKey.lookupsMastodon: _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), PreferencesKey.lookupsYatService: - _sharedPreferences.getBool(PreferencesKey.lookupsYatService), + _sharedPreferences.getBool(PreferencesKey.lookupsYatService), PreferencesKey.lookupsUnstoppableDomains: - _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), - PreferencesKey.lookupsOpenAlias: - _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), - PreferencesKey.lookupsENS: - _sharedPreferences.getBool(PreferencesKey.lookupsENS), - PreferencesKey.syncModeKey: - _sharedPreferences.getInt(PreferencesKey.syncModeKey), - PreferencesKey.syncAllKey: - _sharedPreferences.getBool(PreferencesKey.syncAllKey), + _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), + PreferencesKey.lookupsOpenAlias: _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), + PreferencesKey.lookupsENS: _sharedPreferences.getBool(PreferencesKey.lookupsENS), + PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey), + PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey), PreferencesKey.autoGenerateSubaddressStatusKey: _sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey), }; From 062315f01b292b96edddffa30b5fa3b0e28cd128 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 15 Nov 2023 11:31:25 -0600 Subject: [PATCH 03/17] Secure storage overwrite fix (#1161) * secure storage overwrite fix * add comment * bump encrypt package, use more explicit iv source --------- Co-authored-by: fossephate --- lib/core/auth_service.dart | 10 +++++----- lib/entities/encrypt.dart | 8 ++++---- pubspec_base.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 854640015..321b5b94a 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -38,6 +38,9 @@ class AuthService with Store { Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: password); + // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless + // we delete what's there first: + await secureStorage.delete(key: key); await secureStorage.write(key: key, value: encodedPassword); } @@ -104,9 +107,8 @@ class AuthService with Store { } return; } -} + } - Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (!isAuthenticatedSuccessfully) { @@ -140,8 +142,6 @@ class AuthService with Store { } } } - - }); - + }); } } diff --git a/lib/entities/encrypt.dart b/lib/entities/encrypt.dart index 3e644a2b7..891f7a92d 100644 --- a/lib/entities/encrypt.dart +++ b/lib/entities/encrypt.dart @@ -2,18 +2,18 @@ import 'package:encrypt/encrypt.dart'; // import 'package:password/password.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; -String encrypt({required String source, required String key, int keyLength = 16}) { +String encrypt({required String source, required String key}) { final _key = Key.fromUtf8(key); - final iv = IV.fromLength(keyLength); + final iv = IV.allZerosOfLength(16); final encrypter = Encrypter(AES(_key)); final encrypted = encrypter.encrypt(source, iv: iv); return encrypted.base64; } -String decrypt({required String source, required String key, int keyLength = 16}) { +String decrypt({required String source, required String key}) { final _key = Key.fromUtf8(key); - final iv = IV.fromLength(keyLength); + final iv = IV.allZerosOfLength(16); final encrypter = Encrypter(AES(_key)); final decrypted = encrypter.decrypt64(source, iv: iv); diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 82cb697f5..573f8c671 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -49,7 +49,7 @@ dependencies: lottie: ^1.3.0 animate_do: ^2.1.0 cupertino_icons: ^1.0.5 - encrypt: 5.0.1 + encrypt: 5.0.2 crypto: ^3.0.2 # password: ^1.0.0 basic_utils: ^5.6.1 From 4cffc8d4c503ab1bbb6d92f8162222bd5f2ef27d Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 15 Nov 2023 21:04:30 +0200 Subject: [PATCH 04/17] Update wallet_restore_page.dart (#1178) --- .../screens/restore/wallet_restore_page.dart | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 4fa9e340d..d77c8aa2a 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -196,23 +196,35 @@ class WalletRestorePage extends BasePage { ), Padding( padding: EdgeInsets.only(top: 20, bottom: 24, left: 24, right: 24), - child: Observer( - builder: (context) { - return LoadingPrimaryButton( - onPressed: () async { - await _confirmForm(context); + child: Column( + children: [ + Observer( + builder: (context) { + return LoadingPrimaryButton( + onPressed: () async { + await _confirmForm(context); + }, + text: S.of(context).restore_recover, + color: Theme.of(context) + .extension()! + .createNewWalletButtonBackgroundColor, + textColor: Theme.of(context) + .extension()! + .restoreWalletButtonTextColor, + isLoading: walletRestoreViewModel.state is IsExecutingState, + isDisabled: !walletRestoreViewModel.isButtonEnabled, + ); }, - text: S.of(context).restore_recover, - color: Theme.of(context) - .extension()! - .createNewWalletButtonBackgroundColor, - textColor: Theme.of(context) - .extension()! - .restoreWalletButtonTextColor, - isLoading: walletRestoreViewModel.state is IsExecutingState, - isDisabled: !walletRestoreViewModel.isButtonEnabled, - ); - }, + ), + const SizedBox(height: 25), + GestureDetector( + onTap: () { + Navigator.of(context) + .pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type); + }, + child: Text(S.of(context).advanced_privacy_settings), + ), + ], ), ) ], From 8084f490b593b4dd74956ab00cf516213a69762b Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 16 Nov 2023 00:12:23 +0100 Subject: [PATCH 05/17] Cw 467 mark change outputs in unspent outputs list (#1137) * CW-490 Use native Coin Freeze * CW-467 Code cleanup * CW-467 Fix native Code * CW-467 Extend Unspend * CW-467 Add isChange * CW-467 Minor Fixes * CW-467 Add isChange to Electrum Unspents * CW-467 Localize Change Tag * CW-467 Fix frozen balance showing on other monero wallets * CW-467 Fix frozen balance showing on other monero wallets --- cw_bitcoin/lib/electrum_wallet.dart | 124 +++++++++--------- cw_core/lib/unspent_coins_info.dart | 10 +- cw_core/lib/unspent_transaction_output.dart | 2 + cw_monero/ios/Classes/monero_api.cpp | 15 +++ cw_monero/lib/api/coins_info.dart | 12 ++ cw_monero/lib/api/signatures.dart | 7 + cw_monero/lib/api/transaction_history.dart | 22 +++- cw_monero/lib/api/types.dart | 7 + cw_monero/lib/monero_unspent.dart | 36 ++--- cw_monero/lib/monero_wallet.dart | 31 +++-- lib/monero/cw_monero.dart | 5 +- .../unspent_coins_list_page.dart | 81 +++--------- .../widgets/unspent_coins_list_item.dart | 46 +++++-- .../dashboard/balance_view_model.dart | 18 +-- .../unspent_coins/unspent_coins_item.dart | 4 + .../unspent_coins_list_view_model.dart | 59 +++------ res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 42 files changed, 296 insertions(+), 261 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 804b53379..05486aa20 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -2,41 +2,41 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:mobx/mobx.dart'; -import 'package:rxdart/subjects.dart'; -import 'package:flutter/foundation.dart'; + import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum_transaction_info.dart'; -import 'package:cw_core/pathForWallet.dart'; +import 'package:collection/collection.dart'; import 'package:cw_bitcoin/address_to_output_script.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; -import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; +import 'package:cw_bitcoin/electrum.dart'; +import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_transaction_history.dart'; +import 'package:cw_bitcoin/electrum_transaction_info.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_bitcoin/electrum.dart'; -import 'package:hex/hex.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:collection/collection.dart'; -import 'package:bip32/bip32.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:hex/hex.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:rxdart/subjects.dart'; part 'electrum_wallet.g.dart'; @@ -47,18 +47,18 @@ abstract class ElectrumWalletBase with Store { ElectrumWalletBase( {required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required this.networkType, - required this.mnemonic, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumClient? electrumClient, - ElectrumBalance? initialBalance, - CryptoCurrency? currency}) + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required this.networkType, + required this.mnemonic, + required Uint8List seedBytes, + List? initialAddresses, + ElectrumClient? electrumClient, + ElectrumBalance? initialBalance, + CryptoCurrency? currency}) : hd = currency == CryptoCurrency.bch - ? bitcoinCashHDWallet(seedBytes) - : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), + ? bitcoinCashHDWallet(seedBytes) + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], @@ -67,9 +67,9 @@ abstract class ElectrumWalletBase _scripthashesUpdateSubject = {}, balance = ObservableMap.of(currency != null ? { - currency: - initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) - } + currency: + initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) + } : {}), this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { @@ -79,8 +79,7 @@ abstract class ElectrumWalletBase } static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => - bitcoin.HDWallet.fromSeed(seedBytes) - .derivePath("m/44'/145'/0'/0"); + bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0"); static int estimatedTransactionSize(int inputsCount, int outputsCounts) => inputsCount * 146 + outputsCounts * 33 + 8; @@ -294,10 +293,12 @@ abstract class ElectrumWalletBase if (input.isP2wpkh) { final p2wpkh = bitcoin .P2WPKH( - data: generatePaymentData( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index), - network: networkType) + data: generatePaymentData( + hd: input.bitcoinAddressRecord.isHidden + ? walletAddresses.sideHd + : walletAddresses.mainHd, + index: input.bitcoinAddressRecord.index), + network: networkType) .data; txb.addInput(input.hash, input.vout, null, p2wpkh.output); @@ -347,12 +348,12 @@ abstract class ElectrumWalletBase } String toJSON() => json.encode({ - 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() - }); + 'mnemonic': mnemonic, + 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), + 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'balance': balance[currency]?.toJSON() + }); int feeRate(TransactionPriority priority) { try { @@ -367,7 +368,7 @@ abstract class ElectrumWalletBase } int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => @@ -467,18 +468,20 @@ abstract class ElectrumWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { - final unspent = await Future.wait(walletAddresses - .addresses.map((address) => electrumClient + final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) - .then((unspent) => unspent - .map((unspent) { - try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch(_) { - return null; - } - }).whereNotNull()))); + .then((unspent) => unspent.map((unspent) { + try { + return BitcoinUnspent.fromJSON(address, unspent); + } catch (_) { + return null; + } + }).whereNotNull()))); unspentCoins = unspent.expand((e) => e).toList(); + unspentCoins.forEach((coin) async { + final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); + coin.isChange = tx!.direction == TransactionDirection.outgoing; + }); if (unspentCoinsInfo.isEmpty) { unspentCoins.forEach((coin) => _addCoinInfo(coin)); @@ -515,6 +518,7 @@ abstract class ElectrumWalletBase address: coin.bitcoinAddressRecord.address, value: coin.value, vout: coin.vout, + isChange: coin.isChange, ); await unspentCoinsInfo.add(newInfo); @@ -524,7 +528,7 @@ abstract class ElectrumWalletBase try { final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { @@ -657,7 +661,7 @@ abstract class ElectrumWalletBase final addresses = walletAddresses.addresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { - final addressRecord = addresses[i] ; + final addressRecord = addresses[i]; final sh = scriptHash(addressRecord.address, networkType: networkType); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 68bbcbfd2..25abd3e48 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -14,7 +14,9 @@ class UnspentCoinsInfo extends HiveObject { required this.address, required this.vout, required this.value, - this.keyImage = null + this.keyImage = null, + this.isChange = false, + this.accountIndex = 0 }); static const typeId = UNSPENT_COINS_INFO_TYPE_ID; @@ -47,6 +49,12 @@ class UnspentCoinsInfo extends HiveObject { @HiveField(8, defaultValue: null) String? keyImage; + + @HiveField(9, defaultValue: false) + bool isChange; + + @HiveField(10, defaultValue: 0) + int accountIndex; String get note => noteRaw ?? ''; diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index 6827f4c01..b52daf43c 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -2,6 +2,7 @@ class Unspent { Unspent(this.address, this.hash, this.value, this.vout, this.keyImage) : isSending = true, isFrozen = false, + isChange = false, note = ''; final String address; @@ -10,6 +11,7 @@ class Unspent { final int vout; final String? keyImage; + bool isChange; bool isSending; bool isFrozen; String note; diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index e04282fe8..a0712255a 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -841,6 +841,12 @@ extern "C" return m_transaction_history->count(); } + TransactionInfoRow* get_transaction(char * txId) + { + Monero::TransactionInfo *row = m_transaction_history->transaction(std::string(txId)); + return new TransactionInfoRow(row); + } + int LedgerExchange( unsigned char *command, unsigned int cmd_len, @@ -970,6 +976,15 @@ extern "C" return result; } + void freeze_coin(int index) + { + m_coins->setFrozen(index); + } + + void thaw_coin(int index) + { + m_coins->thaw(index); + } #ifdef __cplusplus } diff --git a/cw_monero/lib/api/coins_info.dart b/cw_monero/lib/api/coins_info.dart index 9a5303f9d..d7350a6e2 100644 --- a/cw_monero/lib/api/coins_info.dart +++ b/cw_monero/lib/api/coins_info.dart @@ -16,8 +16,20 @@ final coinNative = moneroApi .lookup>('coin') .asFunction(); +final freezeCoinNative = moneroApi + .lookup>('freeze_coin') + .asFunction(); + +final thawCoinNative = moneroApi + .lookup>('thaw_coin') + .asFunction(); + void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex); int countOfCoins() => coinsCountNative(); CoinsInfoRow getCoin(int index) => coinNative(index).ref; + +void freezeCoin(int index) => freezeCoinNative(index); + +void thawCoin(int index) => thawCoinNative(index); diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index e208414c8..9be828df0 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -81,6 +82,8 @@ typedef account_set_label = Void Function(Int32 accountIndex, Pointer labe typedef transactions_refresh = Void Function(); +typedef get_transaction = Pointer Function(Pointer txId); + typedef get_tx_key = Pointer? Function(Pointer txId); typedef transactions_count = Int64 Function(); @@ -139,3 +142,7 @@ typedef coins_count = Int64 Function(); // typedef coins_from_txid = Pointer Function(Pointer txid); typedef coin = Pointer Function(Int32 index); + +typedef freeze_coin = Void Function(Int32 index); + +typedef thaw_coin = Void Function(Int32 index); diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index 1964c4067..73c8de801 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -1,15 +1,16 @@ import 'dart:ffi'; + import 'package:cw_monero/api/convert_utf8_to_string.dart'; +import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart'; +import 'package:cw_monero/api/monero_api.dart'; import 'package:cw_monero/api/monero_output.dart'; +import 'package:cw_monero/api/signatures.dart'; +import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.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'; -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/structs/transaction_info_row.dart'; -import 'package:cw_monero/api/structs/pending_transaction.dart'; -import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart'; final transactionsRefreshNative = moneroApi .lookup>('transactions_refresh') @@ -38,6 +39,10 @@ final transactionCommitNative = moneroApi final getTxKeyNative = moneroApi.lookup>('get_tx_key').asFunction(); +final getTransactionNative = moneroApi + .lookup>('get_transaction') + .asFunction(); + String getTxKey(String txId) { final txIdPointer = txId.toNativeUtf8(); final keyPointer = getTxKeyNative(txIdPointer); @@ -65,6 +70,11 @@ List getAllTransactions() { .toList(); } +TransactionInfoRow getTransaction(String txId) { + final txIdPointer = txId.toNativeUtf8(); + return getTransactionNative(txIdPointer).ref; +} + PendingTransactionDescription createTransactionSync( {required String address, required String paymentId, diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 2c92f2d80..4c0c980dc 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -81,6 +82,8 @@ typedef AccountSetLabel = void Function(int accountIndex, Pointer label); typedef TransactionsRefresh = void Function(); +typedef GetTransaction = Pointer Function(Pointer txId); + typedef GetTxKey = Pointer? Function(Pointer txId); typedef TransactionsCount = int Function(); @@ -139,3 +142,7 @@ typedef RefreshCoins = void Function(int); typedef CoinsCount = int Function(); typedef GetCoin = Pointer Function(int); + +typedef FreezeCoin = void Function(int); + +typedef ThawCoin = void Function(int); diff --git a/cw_monero/lib/monero_unspent.dart b/cw_monero/lib/monero_unspent.dart index c2ff9f9db..65b5c595d 100644 --- a/cw_monero/lib/monero_unspent.dart +++ b/cw_monero/lib/monero_unspent.dart @@ -1,28 +1,20 @@ +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_monero/api/structs/coins_info_row.dart'; -class MoneroUnspent { - MoneroUnspent(this.address, this.hash, this.keyImage, this.value, this.isFrozen, this.isUnlocked) - : isSending = true, - note = ''; +class MoneroUnspent extends Unspent { + MoneroUnspent( + String address, String hash, String keyImage, int value, bool isFrozen, this.isUnlocked) + : super(address, hash, value, 0, keyImage) { + this.isFrozen = isFrozen; + } - MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) - : address = coinsInfoRow.getAddress(), - hash = coinsInfoRow.getHash(), - keyImage = coinsInfoRow.getKeyImage(), - value = coinsInfoRow.amount, - isFrozen = coinsInfoRow.frozen == 1, - isUnlocked = coinsInfoRow.unlocked == 1, - isSending = true, - note = ''; - - final String address; - final String hash; - final String keyImage; - final int value; + factory MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) => MoneroUnspent( + coinsInfoRow.getAddress(), + coinsInfoRow.getHash(), + coinsInfoRow.getKeyImage(), + coinsInfoRow.amount, + coinsInfoRow.frozen == 1, + coinsInfoRow.unlocked == 1); final bool isUnlocked; - - bool isFrozen; - bool isSending; - String note; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 83219af5b..d7e66ecec 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; + import 'package:cw_core/account.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/monero_amount_format.dart'; @@ -22,14 +23,14 @@ import 'package:cw_monero/api/transaction_history.dart' as transaction_history; import 'package:cw_monero/api/wallet.dart' as monero_wallet; import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart'; import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart'; -import 'package:cw_monero/pending_monero_transaction.dart'; import 'package:cw_monero/monero_transaction_creation_credentials.dart'; import 'package:cw_monero/monero_transaction_history.dart'; import 'package:cw_monero/monero_transaction_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:cw_monero/monero_wallet_addresses.dart'; -import 'package:mobx/mobx.dart'; +import 'package:cw_monero/pending_monero_transaction.dart'; import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; part 'monero_wallet.g.dart'; @@ -204,7 +205,7 @@ abstract class MoneroWalletBase for (final utx in unspentCoins) { if (utx.isSending) { allInputsAmount += utx.value; - inputs.add(utx.keyImage); + inputs.add(utx.keyImage!); } } final spendAllCoins = inputs.length == unspentCoins.length; @@ -395,7 +396,9 @@ abstract class MoneroWalletBase for (var i = 0; i < coinCount; i++) { final coin = getCoin(i); if (coin.spent == 0) { - unspentCoins.add(MoneroUnspent.fromCoinsInfoRow(coin)); + final unspent = MoneroUnspent.fromCoinsInfoRow(coin); + unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1; + unspentCoins.add(unspent); } } @@ -406,8 +409,10 @@ abstract class MoneroWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { - final coinInfoList = unspentCoinsInfo.values - .where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash)); + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && + element.accountIndex == walletAddresses.account!.id && + element.keyImage!.contains(coin.keyImage!)); if (coinInfoList.isNotEmpty) { final coinInfo = coinInfoList.first; @@ -435,7 +440,9 @@ abstract class MoneroWalletBase address: coin.address, value: coin.value, vout: 0, - keyImage: coin.keyImage); + keyImage: coin.keyImage, + isChange: coin.isChange, + accountIndex: walletAddresses.account!.id); await unspentCoinsInfo.add(newInfo); } @@ -443,12 +450,13 @@ abstract class MoneroWalletBase Future _refreshUnspentCoinsInfo() async { try { final List keys = []; - final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash)); + final existUnspentCoins = + unspentCoins.where((coin) => element.keyImage!.contains(coin.keyImage!)); if (existUnspentCoins.isEmpty) { keys.add(element.key); @@ -566,7 +574,8 @@ abstract class MoneroWalletBase int _getFrozenBalance() { var frozenBalance = 0; - for (var coin in unspentCoinsInfo.values) { + for (var coin in unspentCoinsInfo.values.where((element) => + element.walletId == id && element.accountIndex == walletAddresses.account!.id)) { if (coin.isFrozen) frozenBalance += coin.value; } diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 1de7b8452..9ae248ca0 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -321,10 +321,7 @@ class CWMonero extends Monero { @override List getUnspents(Object wallet) { final moneroWallet = wallet as MoneroWallet; - return moneroWallet.unspentCoins - .map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash, - moneroUnspent.value, 0, moneroUnspent.keyImage)) - .toList(); + return moneroWallet.unspentCoins; } @override diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index 1a173f62a..36cbda641 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -1,15 +1,13 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListPage extends BasePage { UnspentCoinsListPage({required this.unspentCoinsListViewModel}); @@ -17,31 +15,10 @@ class UnspentCoinsListPage extends BasePage { @override String get title => S.current.unspent_coins_title; - //@override - //Widget trailing(BuildContext context) { - // final questionImage = Image.asset('assets/images/question_mark.png', - // color: Theme.of(context).extension()!.titleColor); - - // return SizedBox( - // height: 20.0, - // width: 20.0, - // child: ButtonTheme( - // minWidth: double.minPositive, - // child: FlatButton( - // highlightColor: Colors.transparent, - // splashColor: Colors.transparent, - // padding: EdgeInsets.all(0), - // onPressed: () => showUnspentCoinsAlert(context), - // child: questionImage), - // ), - // ); - //} - final UnspentCoinsListViewModel unspentCoinsListViewModel; @override - Widget body(BuildContext context) => - UnspentCoinsListForm(unspentCoinsListViewModel); + Widget body(BuildContext context) => UnspentCoinsListForm(unspentCoinsListViewModel); } class UnspentCoinsListForm extends StatefulWidget { @@ -50,8 +27,7 @@ class UnspentCoinsListForm extends StatefulWidget { final UnspentCoinsListViewModel unspentCoinsListViewModel; @override - UnspentCoinsListFormState createState() => - UnspentCoinsListFormState(unspentCoinsListViewModel); + UnspentCoinsListFormState createState() => UnspentCoinsListFormState(unspentCoinsListViewModel); } class UnspentCoinsListFormState extends State { @@ -59,16 +35,6 @@ class UnspentCoinsListFormState extends State { final UnspentCoinsListViewModel unspentCoinsListViewModel; - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback(afterLayout); - } - - void afterLayout(dynamic _) { - //showUnspentCoinsAlert(context); - } - @override Widget build(BuildContext context) { return Container( @@ -76,8 +42,7 @@ class UnspentCoinsListFormState extends State { child: Observer( builder: (_) => ListView.separated( itemCount: unspentCoinsListViewModel.items.length, - separatorBuilder: (_, __) => - SizedBox(height: 15), + separatorBuilder: (_, __) => SizedBox(height: 15), itemBuilder: (_, int index) { return Observer(builder: (_) { final item = unspentCoinsListViewModel.items[index]; @@ -86,38 +51,22 @@ class UnspentCoinsListFormState extends State { : item.address; return GestureDetector( - onTap: () => - Navigator.of(context) - .pushNamed(Routes.unspentCoinsDetails, - arguments: [item, unspentCoinsListViewModel]), + onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails, + arguments: [item, unspentCoinsListViewModel]), child: UnspentCoinsListItem( note: item.note, amount: item.amount, address: address, isSending: item.isSending, isFrozen: item.isFrozen, + isChange: item.isChange, onCheckBoxTap: item.isFrozen - ? null - : () async { - item.isSending = !item.isSending; - await unspentCoinsListViewModel - .saveUnspentCoinInfo(item);})); + ? null + : () async { + item.isSending = !item.isSending; + await unspentCoinsListViewModel.saveUnspentCoinInfo(item); + })); }); - } - ) - ) - ); + }))); } } - -void showUnspentCoinsAlert(BuildContext context) { - showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: '', - alertContent: 'Information about unspent coins', - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); -} \ No newline at end of file diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index 93cf27af1..d629e9454 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -1,8 +1,8 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListItem extends StatelessWidget { UnspentCoinsListItem({ @@ -11,6 +11,7 @@ class UnspentCoinsListItem extends StatelessWidget { required this.address, required this.isSending, required this.isFrozen, + required this.isChange, this.onCheckBoxTap, }); @@ -19,6 +20,7 @@ class UnspentCoinsListItem extends StatelessWidget { final String address; final bool isSending; final bool isFrozen; + final bool isChange; final Function()? onCheckBoxTap; @override @@ -27,9 +29,8 @@ class UnspentCoinsListItem extends StatelessWidget { final selectedItemColor = Theme.of(context).primaryColor; final itemColor = isSending ? selectedItemColor : unselectedItemColor; - final amountColor = isSending - ? Colors.white - : Theme.of(context).extension()!.buttonTextColor; + final amountColor = + isSending ? Colors.white : Theme.of(context).extension()!.buttonTextColor; final addressColor = isSending ? Colors.white.withOpacity(0.5) : Theme.of(context).extension()!.buttonSecondaryTextColor; @@ -47,7 +48,8 @@ class UnspentCoinsListItem extends StatelessWidget { child: StandardCheckbox( iconColor: amountColor, borderColor: addressColor, - value: isSending, onChanged: (value) => onCheckBoxTap?.call())), + value: isSending, + onChanged: (value) => onCheckBoxTap?.call())), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -57,9 +59,7 @@ class UnspentCoinsListItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ if (note.isNotEmpty) AutoSizeText( note, @@ -69,8 +69,8 @@ class UnspentCoinsListItem extends StatelessWidget { ), AutoSizeText( amount, - style: - TextStyle(color: amountColor, fontSize: 15, fontWeight: FontWeight.w600), + style: TextStyle( + color: amountColor, fontSize: 15, fontWeight: FontWeight.w600), maxLines: 1, ) ]), @@ -84,23 +84,41 @@ class UnspentCoinsListItem extends StatelessWidget { alignment: Alignment.center, child: Text( S.of(context).frozen, - style: - TextStyle(color: amountColor, fontSize: 7, fontWeight: FontWeight.w600), - )) + style: TextStyle( + color: amountColor, fontSize: 7, fontWeight: FontWeight.w600), + )), ], ), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AutoSizeText( - '${address.substring(0, 5)}...${address.substring(address.length-5)}', // ToDo: Maybe use address label + '${address.substring(0, 5)}...${address.substring(address.length - 5)}', // ToDo: Maybe use address label style: TextStyle( color: addressColor, fontSize: 12, ), maxLines: 1, ), + if (isChange) + Container( + height: 17, + padding: EdgeInsets.only(left: 6, right: 6), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.5)), + color: Colors.white), + alignment: Alignment.center, + child: Text( + S.of(context).unspent_change, + style: TextStyle( + color: itemColor, + fontSize: 7, + fontWeight: FontWeight.w600, + ), + ), + ), ], ), ), diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 06d05b3a3..f32b43cd6 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -175,10 +175,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: getFormattedFrozenBalance(walletBalance)) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(walletBalance)) + + ' ${fiatCurrency.toString()}'; } @computed @@ -201,10 +199,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: walletBalance.formattedAvailableBalance) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAvailableBalance) + + ' ${fiatCurrency.toString()}'; } @computed @@ -216,10 +212,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: walletBalance.formattedAdditionalBalance) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAdditionalBalance) + + ' ${fiatCurrency.toString()}'; } @computed diff --git a/lib/view_model/unspent_coins/unspent_coins_item.dart b/lib/view_model/unspent_coins/unspent_coins_item.dart index 9d1f6c71c..bb5c4dd7b 100644 --- a/lib/view_model/unspent_coins/unspent_coins_item.dart +++ b/lib/view_model/unspent_coins/unspent_coins_item.dart @@ -12,6 +12,7 @@ abstract class UnspentCoinsItemBase with Store { required this.isFrozen, required this.note, required this.isSending, + required this.isChange, required this.amountRaw, required this.vout, required this.keyImage @@ -35,6 +36,9 @@ abstract class UnspentCoinsItemBase with Store { @observable bool isSending; + @observable + bool isChange; + @observable int amountRaw; diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 709c50562..1815b1689 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -1,10 +1,8 @@ -import 'package:collection/collection.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; @@ -26,66 +24,49 @@ abstract class UnspentCoinsListViewModelBase with Store { @computed ObservableList get items => ObservableList.of(_getUnspents().map((elem) { - final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}'; - final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); return UnspentCoinsItem( address: elem.address, - amount: amount, + amount: '${formatAmountToString(elem.value)} ${wallet.currency.title}', hash: elem.hash, - isFrozen: info?.isFrozen ?? false, - note: info?.note ?? '', - isSending: info?.isSending ?? true, + isFrozen: info.isFrozen, + note: info.note, + isSending: info.isSending, amountRaw: elem.value, vout: elem.vout, - keyImage: elem.keyImage); + keyImage: elem.keyImage, + isChange: elem.isChange, + ); })); Future saveUnspentCoinInfo(UnspentCoinsItem item) async { try { final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage); - if (info == null) { - final newInfo = UnspentCoinsInfo( - walletId: wallet.id, - hash: item.hash, - address: item.address, - value: item.amountRaw, - vout: item.vout, - isFrozen: item.isFrozen, - isSending: item.isSending, - noteRaw: item.note, - keyImage: item.keyImage); - await _unspentCoinsInfo.add(newInfo); - _updateUnspents(); - wallet.updateBalance(); - return; - } info.isFrozen = item.isFrozen; info.isSending = item.isSending; info.note = item.note; await info.save(); - _updateUnspents(); - wallet.updateBalance(); + await _updateUnspents(); + await wallet.updateBalance(); } catch (e) { print(e.toString()); } } - UnspentCoinsInfo? getUnspentCoinInfo( - String hash, String address, int value, int vout, String? keyImage) { - return _unspentCoinsInfo.values.firstWhereOrNull((element) => - element.walletId == wallet.id && - element.hash == hash && - element.address == address && - element.value == value && - element.vout == vout && - element.keyImage == keyImage); - } + UnspentCoinsInfo getUnspentCoinInfo( + String hash, String address, int value, int vout, String? keyImage) => + _unspentCoinsInfo.values.firstWhere((element) => + element.walletId == wallet.id && + element.hash == hash && + element.address == address && + element.value == value && + element.vout == vout && + element.keyImage == keyImage); String formatAmountToString(int fullBalance) { if (wallet.type == WalletType.monero) @@ -95,7 +76,7 @@ abstract class UnspentCoinsListViewModelBase with Store { return ''; } - void _updateUnspents() { + Future _updateUnspents() async { if (wallet.type == WalletType.monero) return monero!.updateUnspents(wallet); if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) return bitcoin!.updateUnspents(wallet); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4100bdeb8..54a9a1d75 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -726,5 +726,6 @@ "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", - "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" + "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "unspent_change": "يتغير" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index e12a24119..89be7d8a9 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -722,5 +722,6 @@ "domain_looks_up": "Търсене на домейни", "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", - "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" + "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "unspent_change": "Промяна" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 52087ef60..4b3d2c44e 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -722,5 +722,6 @@ "domain_looks_up": "Vyhledávání domén", "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", - "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" + "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "unspent_change": "Změna" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 733b645c9..8fa81fdb0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Domain-Suchen", "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", - "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" + "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "unspent_change": "Wechselgeld" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4264d6b37..327bfbdc9 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -731,5 +731,6 @@ "domain_looks_up": "Domain lookups", "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", - "switchToETHWallet": "Please switch to an Ethereum wallet and try again" + "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "unspent_change": "Change" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 728d15afb..89143e97c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Búsquedas de dominio", "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", - "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." + "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "unspent_change": "Cambiar" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d4d27ae0b..8e43afee5 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Recherches de domaine", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer" + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", + "unspent_change": "Changement" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 57199fa47..506c68503 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -708,5 +708,6 @@ "domain_looks_up": "Binciken yanki", "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", - "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" + "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "unspent_change": "Canza" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 536731c94..5c77d0f01 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -730,5 +730,6 @@ "domain_looks_up": "डोमेन लुकअप", "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", - "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" + "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "unspent_change": "परिवर्तन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 936e41338..e09df5a99 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -728,5 +728,6 @@ "domain_looks_up": "Pretraga domena", "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", - "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" + "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "unspent_change": "Promijeniti" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 036e3e96d..1f1640744 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -718,5 +718,6 @@ "domain_looks_up": "Pencarian domain", "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", - "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" + "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "unspent_change": "Mengubah" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5138b1a59..0a626932c 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Ricerche di domini", "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", - "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" + "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "unspent_change": "Modifica" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index cc6dad9a8..40ab152a9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -730,5 +730,6 @@ "domain_looks_up": "ドメイン検索", "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", - "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" + "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "unspent_change": "変化" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 9ce833b08..ea95072cf 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -728,5 +728,6 @@ "domain_looks_up": "도메인 조회", "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", - "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." + "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "unspent_change": "변화" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c92871c5f..f2a4a8fac 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -728,5 +728,6 @@ "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", - "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" + "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "unspent_change": "ပေြာင်းလဲခြင်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c93861b2b..a582a9439 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Domein opzoeken", "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", - "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" + "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "unspent_change": "Wijziging" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 5d32aaa74..85b8668b9 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Wyszukiwanie domen", "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", - "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" + "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "unspent_change": "Zmiana" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index aa1f7459f..3c7253197 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -729,5 +729,6 @@ "domain_looks_up": "Pesquisas de domínio", "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", - "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" + "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "unspent_change": "Mudar" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 31fc00bca..a833e2c4c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Поиск доменов", "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", - "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." + "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "unspent_change": "Изменять" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b9757a08d..f20d7e3ae 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -728,5 +728,6 @@ "domain_looks_up": "การค้นหาโดเมน", "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", - "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" + "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "unspent_change": "เปลี่ยน" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6157d9eb3..e323a3523 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -725,5 +725,6 @@ "domain_looks_up": "Mga paghahanap ng domain", "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", - "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" + "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "unspent_change": "Baguhin" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index ddc669221..b13b85bb4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -728,5 +728,6 @@ "domain_looks_up": "Etki alanı aramaları", "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", - "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" + "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "unspent_change": "Değiştirmek" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 9fb39b6cf..6ee8a491e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Пошук доменів", "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", - "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" + "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "unspent_change": "Зміна" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e3f934891..2f44cb510 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -722,5 +722,6 @@ "domain_looks_up": "ڈومین تلاش کرنا", "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", - "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" + "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "unspent_change": "تبدیل کریں" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index aafb70803..09f9d1b87 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -724,5 +724,6 @@ "domain_looks_up": "Awọn wiwa agbegbe", "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", - "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" + "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "unspent_change": "Yipada" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 336083a72..1eec3f477 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -729,5 +729,6 @@ "domain_looks_up": "域名查找", "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", - "switchToETHWallet": "请切换到以太坊钱包并重试" + "switchToETHWallet": "请切换到以太坊钱包并重试", + "unspent_change": "改变" } From 28ad0dbd692880bdb4e24bdd5c93e72d947d3a2a Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Wed, 15 Nov 2023 23:18:50 +0000 Subject: [PATCH 06/17] Minor fixes to FR localization (#1164) Co-authored-by: Omar Hatem --- res/values/strings_fr.arb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 8e43afee5..f83493f7a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -727,9 +727,9 @@ "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", - "domain_looks_up": "Recherches de domaine", + "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", - "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement" } From bb5336ff604e9983f5ddcf546abf206431adb37c Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 01:22:10 +0200 Subject: [PATCH 07/17] CW-516-Improve-balance-layout-in-home-screen (#1171) * unavailable balance * localization * unavailable balance description * add unavailable balance popup --- cw_core/lib/balance.dart | 2 +- cw_core/lib/monero_balance.dart | 14 +-- .../dashboard/widgets/balance_page.dart | 102 +++++++++++------- .../dashboard/balance_view_model.dart | 2 +- res/values/strings_ar.arb | 5 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 30 files changed, 124 insertions(+), 76 deletions(-) diff --git a/cw_core/lib/balance.dart b/cw_core/lib/balance.dart index 6145411c4..431aff515 100644 --- a/cw_core/lib/balance.dart +++ b/cw_core/lib/balance.dart @@ -9,5 +9,5 @@ abstract class Balance { String get formattedAdditionalBalance; - String get formattedFrozenBalance => ''; + String get formattedUnAvailableBalance => ''; } diff --git a/cw_core/lib/monero_balance.dart b/cw_core/lib/monero_balance.dart index bf30110a3..98a7f134a 100644 --- a/cw_core/lib/monero_balance.dart +++ b/cw_core/lib/monero_balance.dart @@ -4,17 +4,18 @@ import 'package:cw_core/monero_amount_format.dart'; class MoneroBalance extends Balance { MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0}) : formattedFullBalance = moneroAmountToString(amount: fullBalance), - formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance), - frozenFormatted = moneroAmountToString(amount: frozenBalance), + formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance - frozenBalance), + formattedLockedBalance = + moneroAmountToString(amount: frozenBalance + fullBalance - unlockedBalance), super(unlockedBalance, fullBalance); MoneroBalance.fromString( {required this.formattedFullBalance, required this.formattedUnlockedBalance, - this.frozenFormatted = '0.0'}) + this.formattedLockedBalance = '0.0'}) : fullBalance = moneroParseAmount(amount: formattedFullBalance), unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance), - frozenBalance = moneroParseAmount(amount: frozenFormatted), + frozenBalance = moneroParseAmount(amount: formattedLockedBalance), super(moneroParseAmount(amount: formattedUnlockedBalance), moneroParseAmount(amount: formattedFullBalance)); @@ -23,10 +24,11 @@ class MoneroBalance extends Balance { final int frozenBalance; final String formattedFullBalance; final String formattedUnlockedBalance; - final String frozenFormatted; + final String formattedLockedBalance; @override - String get formattedFrozenBalance => frozenFormatted == '0.0' ? '' : frozenFormatted; + String get formattedUnAvailableBalance => + formattedLockedBalance == '0.0' ? '' : formattedLockedBalance; @override String get formattedAvailableBalance => formattedUnlockedBalance; diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart index b4c4f71dc..41d4e7bb0 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -165,7 +165,9 @@ class BalancePage extends StatelessWidget { children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance ? () => _showBalanceDescription(context) : null, + onTap: hasAdditionalBalance ? () => + _showBalanceDescription(context, S.current.available_balance_description) + : null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -225,47 +227,65 @@ class BalancePage extends StatelessWidget { ], ), if (frozenBalance.isNotEmpty) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 26), - Text( - S.current.frozen_balance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.labelTextColor, - height: 1, + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: hasAdditionalBalance ? + () => _showBalanceDescription(context, S.current.unavailable_balance_description) + : null, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 26), + Row( + children: [ + Text( + S.current.unavailable_balance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ), + ], ), - ), - SizedBox(height: 8), - AutoSizeText( - frozenBalance, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + SizedBox(height: 8), + AutoSizeText( + frozenBalance, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 4), - Text( - frozenFiatBalance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + SizedBox(height: 4), + Text( + frozenFiatBalance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), ), - ), - ], + ], + ), ), if (hasAdditionalBalance) Column( @@ -316,9 +336,9 @@ class BalancePage extends StatelessWidget { ); } - void _showBalanceDescription(BuildContext context) { + void _showBalanceDescription(BuildContext context, String content) { showPopUp( context: context, - builder: (_) => InformationPage(information: S.current.available_balance_description)); + builder: (_) => InformationPage(information: content)); } } diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index f32b43cd6..9366985b5 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -392,6 +392,6 @@ abstract class BalanceViewModelBase with Store { } } - String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedFrozenBalance; + String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedUnAvailableBalance; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 54a9a1d75..4727a0262 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -591,7 +591,6 @@ "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت", "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", "edit_node": "تحرير العقدة", - "frozen_balance": "الرصيد المجمد", "invoice_details": "تفاصيل الفاتورة", "donation_link_details": "تفاصيل رابط التبرع", "anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه", @@ -727,5 +726,7 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", + "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير" -} +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 89be7d8a9..d52529e38 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -588,7 +588,6 @@ "error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.", "decimal_places_error": "Твърде много знаци след десетичната запетая", "edit_node": "Редактиране на възел", - "frozen_balance": "Замразен баланс", "invoice_details": "IДанни за фактура", "donation_link_details": "Подробности за връзката за дарение", "anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "unavailable_balance": "Неналично салдо", + "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 4b3d2c44e..8b86c517f 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -588,7 +588,6 @@ "error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.", "decimal_places_error": "Příliš mnoho desetinných míst", "edit_node": "Upravit uzel", - "frozen_balance": "Zmrazená bilance", "invoice_details": "detaily faktury", "donation_link_details": "Podrobnosti odkazu na darování", "anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "unavailable_balance": "Nedostupný zůstatek", + "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8fa81fdb0..0928e1462 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", "decimal_places_error": "Zu viele Nachkommastellen", "edit_node": "Knoten bearbeiten", - "frozen_balance": "Gefrorenes Guthaben", "invoice_details": "Rechnungs-Details", "donation_link_details": "Details zum Spendenlink", "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "unavailable_balance": "Nicht verfügbares Guthaben", + "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 327bfbdc9..55b6f8339 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -606,7 +606,6 @@ "onion_link": "Onion link", "decimal_places_error": "Too many decimal places", "edit_node": "Edit Node", - "frozen_balance": "Frozen Balance", "settings": "Settings", "sell_monero_com_alert_content": "Selling Monero is not supported yet", "error_text_input_below_minimum_limit": "Amount is less than the minimum", @@ -732,5 +731,7 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "unavailable_balance": "Unavailable balance", + "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 89143e97c..048bf05ea 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS", "decimal_places_error": "Demasiados lugares decimales", "edit_node": "Editar nodo", - "frozen_balance": "Balance congelado", "invoice_details": "Detalles de la factura", "donation_link_details": "Detalles del enlace de donación", "anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "unavailable_balance": "Saldo no disponible", + "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f83493f7a..d82f8a677 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS", "decimal_places_error": "Trop de décimales", "edit_node": "Modifier le nœud", - "frozen_balance": "Solde gelé", "invoice_details": "Détails de la facture", "donation_link_details": "Détails du lien de don", "anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).", @@ -729,6 +728,8 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "unavailable_balance": "Solde indisponible", + "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement" diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 506c68503..6c0644316 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -602,7 +602,6 @@ "onion_link": "Lambar onion", "decimal_places_error": "Wadannan suna da tsawon harsuna", "edit_node": "Shirya Node", - "frozen_balance": "Falin kuma maɓallin", "settings": "Saiti", "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba", "error_text_input_below_minimum_limit": "Kudin ba a kamai", @@ -709,5 +708,7 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "unavailable_balance": "Ma'aunin da ba ya samuwa", + "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5c77d0f01..ae0b1a94d 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं", "decimal_places_error": "बहुत अधिक दशमलव स्थान", "edit_node": "नोड संपादित करें", - "frozen_balance": "जमे हुए संतुलन", "invoice_details": "चालान विवरण", "donation_link_details": "दान लिंक विवरण", "anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "unavailable_balance": "अनुपलब्ध शेष", + "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e09df5a99..d9dcba723 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI", "decimal_places_error": "Previše decimalnih mjesta", "edit_node": "Uredi čvor", - "frozen_balance": "Zamrznuti saldo", "invoice_details": "Podaci o fakturi", "donation_link_details": "Detalji veza za donacije", "anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "unavailable_balance": "Nedostupno stanje", + "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 1f1640744..e6498d169 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -584,7 +584,6 @@ "contact_list_wallets": "Dompet Saya", "decimal_places_error": "Terlalu banyak tempat desimal", "edit_node": "Sunting Node", - "frozen_balance": "Saldo Beku", "invoice_details": "Detail faktur", "donation_link_details": "Detail tautan donasi", "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", @@ -719,5 +718,7 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "unavailable_balance": "Saldo tidak tersedia", + "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0a626932c..b78644766 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI", "decimal_places_error": "Troppe cifre decimali", "edit_node": "Modifica nodo", - "frozen_balance": "Equilibrio congelato", "invoice_details": "Dettagli della fattura", "donation_link_details": "Dettagli del collegamento alla donazione", "anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "unavailable_balance": "Saldo non disponibile", + "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 40ab152a9..1c7ad6497 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります", "decimal_places_error": "小数点以下の桁数が多すぎる", "edit_node": "ノードを編集", - "frozen_balance": "冷凍残高", "invoice_details": "請求の詳細", "donation_link_details": "寄付リンクの詳細", "anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "unavailable_balance": "利用できない残高", + "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index ea95072cf..cbf1744e1 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.", "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", "edit_node": "노드 편집", - "frozen_balance": "얼어붙은 균형", "invoice_details": "인보이스 세부정보", "donation_link_details": "기부 링크 세부정보", "anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "unavailable_balance": "사용할 수 없는 잔액", + "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index f2a4a8fac..bb2f8a86d 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်", "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", "edit_node": "Node ကို တည်းဖြတ်ပါ။", - "frozen_balance": "ေးခဲမှူ", "invoice_details": "ပြေစာအသေးစိတ်", "donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်", "anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", + "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a582a9439..e833dde50 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN", "decimal_places_error": "Te veel decimalen", "edit_node": "Knooppunt bewerken", - "frozen_balance": "Bevroren saldo", "invoice_details": "Factuurgegevens", "donation_link_details": "Details van de donatielink", "anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "unavailable_balance": "Onbeschikbaar saldo", + "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 85b8668b9..8429cec8a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", "decimal_places_error": "Za dużo miejsc dziesiętnych", "edit_node": "Edytuj węzeł", - "frozen_balance": "Zamrożona równowaga", "invoice_details": "Dane do faktury", "donation_link_details": "Szczegóły linku darowizny", "anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "unavailable_balance": "Niedostępne saldo", + "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 3c7253197..9bb27a582 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -594,7 +594,6 @@ "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", "decimal_places_error": "Muitas casas decimais", "edit_node": "Editar nó", - "frozen_balance": "Saldo Congelado", "invoice_details": "Detalhes da fatura", "donation_link_details": "Detalhes do link de doação", "anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.", @@ -730,5 +729,7 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "unavailable_balance": "Saldo indisponível", + "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a833e2c4c..d0f64c8b2 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ", "decimal_places_error": "Слишком много десятичных знаков", "edit_node": "Редактировать узел", - "frozen_balance": "Замороженный баланс", "invoice_details": "Детали счета", "donation_link_details": "Информация о ссылке для пожертвований", "anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "unavailable_balance": "Недоступный баланс", + "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f20d7e3ae..3159bd649 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย", "decimal_places_error": "ทศนิยมมากเกินไป", "edit_node": "แก้ไขโหนด", - "frozen_balance": "ยอดคงเหลือแช่แข็ง", "invoice_details": "รายละเอียดใบแจ้งหนี้", "donation_link_details": "รายละเอียดลิงค์บริจาค", "anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", + "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e323a3523..b38dc35ad 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -606,7 +606,6 @@ "onion_link": "Link ng Onion", "decimal_places_error": "Masyadong maraming mga lugar na desimal", "edit_node": "I -edit ang node", - "frozen_balance": "Frozen na balanse", "settings": "Mga setting", "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", @@ -726,5 +725,7 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "unavailable_balance": "Hindi available na balanse", + "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b13b85bb4..77d29f8d2 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR", "decimal_places_error": "Çok fazla ondalık basamak", "edit_node": "Düğümü Düzenle", - "frozen_balance": "Dondurulmuş Bakiye", "invoice_details": "fatura detayları", "donation_link_details": "Bağış bağlantısı ayrıntıları", "anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "unavailable_balance": "Kullanılamayan bakiye", + "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 6ee8a491e..aa9e29687 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ", "decimal_places_error": "Забагато знаків після коми", "edit_node": "Редагувати вузол", - "frozen_balance": "Заморожений баланс", "invoice_details": "Реквізити рахунку-фактури", "donation_link_details": "Деталі посилання для пожертв", "anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "unavailable_balance": "Недоступний баланс", + "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 2f44cb510..e8cf03835 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -588,7 +588,6 @@ "error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔", "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", "edit_node": "نوڈ میں ترمیم کریں۔", - "frozen_balance": "منجمد بیلنس", "invoice_details": "رسید کی تفصیلات", "donation_link_details": "عطیہ کے لنک کی تفصیلات", "anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", + "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 09f9d1b87..7784e785a 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -599,7 +599,6 @@ "onion_link": "Kọja ilọ alubosa", "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", "edit_node": "Tun awọn ọwọnrin ṣiṣe", - "frozen_balance": "Aferugbo Iye", "settings": "Awọn aseṣe", "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu", "error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ", @@ -725,5 +724,7 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "unavailable_balance": "Iwontunwonsi ti ko si", + "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 1eec3f477..454c79194 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -594,7 +594,6 @@ "sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金", "decimal_places_error": "小数位太多", "edit_node": "编辑节点", - "frozen_balance": "冻结余额", "invoice_details": "发票明细", "donation_link_details": "捐赠链接详情", "anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。", @@ -730,5 +729,7 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "unavailable_balance": "不可用余额", + "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变" } From 36361ef329fb7ae988d3e4e48b4109b7b98cc836 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 01:23:34 +0200 Subject: [PATCH 08/17] CW-526-Add-Trocador-providers-option-in-privacy-settings (#1177) * Trocador settings page UI * add trocador providers states * add settings icon * minor fix * Revert "minor fix" This reverts commit e59d9dfdaf9bd1c13a17ae5012db80a8f973a4d4. * fixes * PR fixes * remove trocador menu icon --- lib/di.dart | 6 +++ .../provider/trocador_exchange_provider.dart | 43 +++++++++++++++++-- lib/router.dart | 5 +++ lib/routes.dart | 1 + lib/src/screens/settings/privacy_page.dart | 4 ++ .../settings/trocador_providers_page.dart | 37 ++++++++++++++++ lib/store/settings_store.dart | 19 ++++++++ .../exchange/exchange_view_model.dart | 3 +- .../trocador_providers_view_model.dart | 21 +++++++++ 9 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 lib/src/screens/settings/trocador_providers_page.dart create mode 100644 lib/view_model/settings/trocador_providers_view_model.dart diff --git a/lib/di.dart b/lib/di.dart index 10662d816..8cc393510 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -45,6 +45,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -92,6 +93,7 @@ import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; @@ -699,6 +701,8 @@ Future setup({ return PrivacySettingsViewModel(getIt.get(), getIt.get().wallet!); }); + getIt.registerFactory(() => TrocadorProvidersViewModel(getIt.get())); + getIt.registerFactory(() { return OtherSettingsViewModel(getIt.get(), getIt.get().wallet!); }); @@ -752,6 +756,8 @@ Future setup({ getIt.registerFactory(() => PrivacyPage(getIt.get())); + getIt.registerFactory(() => TrocadorProvidersPage(getIt.get())); + getIt.registerFactory(() => DomainLookupsPage(getIt.get())); getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index 3d08bbd37..52e38ecc8 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -12,11 +12,27 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:http/http.dart'; class TrocadorExchangeProvider extends ExchangeProvider { - TrocadorExchangeProvider({this.useTorOnly = false}) - : _lastUsedRateId = '', + TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}}) + : _lastUsedRateId = '', _provider = [], super(pairList: supportedPairs(_notSupported)); bool useTorOnly; + final Map providerStates; + + static const List availableProviders = [ + 'Swapter', + 'StealthEx', + 'Simpleswap', + 'Swapuz' + 'ChangeNow', + 'Changehero', + 'FixedFloat', + 'LetsExchange', + 'Exolix', + 'Godex', + 'Exch', + 'CoinCraddle' + ]; static const List _notSupported = [ CryptoCurrency.stx, @@ -33,6 +49,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { static const coinPath = 'api/coin'; String _lastUsedRateId; + List _provider; @override String get title => 'Trocador'; @@ -105,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'payment': isFixedRateMode ? 'True' : 'False', 'min_kycrating': 'C', 'markup': markup, - 'best_only': 'True', }; final uri = await _getUri(newRatePath, params); @@ -115,6 +131,9 @@ class TrocadorExchangeProvider extends ExchangeProvider { final toAmount = double.parse(responseJSON['amount_to'].toString()); final rateId = responseJSON['trade_id'] as String? ?? ''; + var quotes = responseJSON['quotes']['quotes'] as List; + _provider = quotes.map((quote) => quote['provider']).toList(); + if (rateId.isNotEmpty) _lastUsedRateId = rateId; return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount); @@ -126,6 +145,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { @override Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + final params = { 'api_key': apiKey, 'ticker_from': _normalizeCurrency(request.fromCurrency), @@ -135,7 +155,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'payment': isFixedRateMode ? 'True' : 'False', 'min_kycrating': 'C', 'markup': markup, - 'best_only': 'True', if (!isFixedRateMode) 'amount_from': request.fromAmount, if (isFixedRateMode) 'amount_to': request.toAmount, 'address': request.toAddress, @@ -153,6 +172,22 @@ class TrocadorExchangeProvider extends ExchangeProvider { params['id'] = _lastUsedRateId; } + + String firstAvailableProvider = ''; + + for (var provider in _provider) { + if (providerStates.containsKey(provider) && providerStates[provider] == true) { + firstAvailableProvider = provider as String; + break; + } + } + + if (firstAvailableProvider.isEmpty) { + throw Exception('No available provider is enabled'); + } + + params['provider'] = firstAvailableProvider; + final uri = await _getUri(createTradePath, params); final response = await get(uri); diff --git a/lib/router.dart b/lib/router.dart index 1211bbcb6..dc2d8f8ab 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -42,6 +42,7 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -323,6 +324,10 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.trocadorProvidersPage: + return CupertinoPageRoute( + fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.domainLookupsPage: return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 0b4e8817d..8b521247a 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -81,6 +81,7 @@ class Routes { static const connectionSync = '/connection_sync_page'; static const securityBackupPage = '/security_and_backup_page'; static const privacyPage = '/privacy_page'; + static const trocadorProvidersPage = '/trocador_providers_page'; static const domainLookupsPage = '/domain_lookups_page'; static const displaySettingsPage = '/display_settings_page'; static const otherSettingsPage = '/other_settings_page'; diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 8e71b6020..7a8671224 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -90,6 +90,10 @@ class PrivacyPage extends BasePage { title: S.current.domain_looks_up, handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), ), + SettingsCellWithArrow( + title: 'Trocador providers', + handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), + ), ], ); }), diff --git a/lib/src/screens/settings/trocador_providers_page.dart b/lib/src/screens/settings/trocador_providers_page.dart new file mode 100644 index 000000000..b972c22d5 --- /dev/null +++ b/lib/src/screens/settings/trocador_providers_page.dart @@ -0,0 +1,37 @@ +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class TrocadorProvidersPage extends BasePage { + TrocadorProvidersPage(this.trocadorProvidersViewModel); + + @override + String get title => 'Trocador Providers'; + + final TrocadorProvidersViewModel trocadorProvidersViewModel; + + @override + Widget body(BuildContext context) { + final availableProviders = TrocadorExchangeProvider.availableProviders; + final providerStates = trocadorProvidersViewModel.providerStates; + return Container( + padding: EdgeInsets.only(top: 10), + child: ListView.builder( + itemCount: availableProviders.length, + itemBuilder: (_, index) { + String provider = availableProviders[index]; + return Observer( + builder: (_) => SettingsSwitcherCell( + title: provider, + value: providerStates[provider] ?? false, + onValueChange: (BuildContext _, bool value) { + trocadorProvidersViewModel.toggleProviderState(provider); + })); + }, + ), + ); + } +} diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index cb9df3d1d..3c9ba36d5 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; @@ -161,6 +162,8 @@ abstract class SettingsStoreBase with Store { priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority; } + initializeTrocadorProviderStates(); + reaction( (_) => fiatCurrency, (FiatCurrency fiatCurrency) => sharedPreferences.setString( @@ -515,6 +518,9 @@ abstract class SettingsStoreBase with Store { @observable ObservableMap priority; + @observable + ObservableMap trocadorProviderStates = ObservableMap(); + @observable SortBalanceBy sortBalanceBy; @@ -1059,6 +1065,19 @@ abstract class SettingsStoreBase with Store { powNodes[walletType] = node; } + void initializeTrocadorProviderStates() { + for (var provider in TrocadorExchangeProvider.availableProviders) { + final savedState = _sharedPreferences.getBool(provider) ?? true; + trocadorProviderStates[provider] = savedState; + } + } + + void saveTrocadorProviderState(String providerName, bool state) { + _sharedPreferences.setBool(providerName, state); + trocadorProviderStates[providerName] = state; + } + + static Future _getDeviceName() async { String? deviceName = ''; final deviceInfoPlugin = DeviceInfoPlugin(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 1a6b118f8..80c331ab2 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -146,7 +146,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with ChangeNowExchangeProvider(settingsStore: _settingsStore), SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), - TrocadorExchangeProvider(useTorOnly: _useTorOnly), + TrocadorExchangeProvider(useTorOnly: _useTorOnly, + providerStates: _settingsStore.trocadorProviderStates), if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(), ]; diff --git a/lib/view_model/settings/trocador_providers_view_model.dart b/lib/view_model/settings/trocador_providers_view_model.dart new file mode 100644 index 000000000..19204d1f9 --- /dev/null +++ b/lib/view_model/settings/trocador_providers_view_model.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'trocador_providers_view_model.g.dart'; + +class TrocadorProvidersViewModel = TrocadorProvidersViewModelBase with _$TrocadorProvidersViewModel; + +abstract class TrocadorProvidersViewModelBase with Store { + TrocadorProvidersViewModelBase(this._settingsStore); + + final SettingsStore _settingsStore; + + @computed + Map get providerStates => _settingsStore.trocadorProviderStates; + + @action + void toggleProviderState(String providerName) { + final currentState = providerStates[providerName] ?? false; + _settingsStore.saveTrocadorProviderState(providerName, !currentState); + } +} \ No newline at end of file From 8237b89d56a7c3a8f035abb4976589e6c5deb470 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 15:45:42 +0200 Subject: [PATCH 09/17] CW-520-Enable-user-to-choose-12-or-24-seed-words-for-BCH-and-ETH (#1181) * seed phrase option UI * bch seed length option * eth seed lengh option * update preseed info * update localization files --- .../lib/src/bitcoin_cash_wallet_service.dart | 7 ++++- cw_core/lib/wallet_credentials.dart | 2 ++ cw_ethereum/lib/ethereum_wallet_service.dart | 9 ++++++- lib/core/wallet_creation_service.dart | 6 +++++ lib/di.dart | 13 ++++++---- lib/entities/preferences_key.dart | 1 + lib/entities/seed_phrase_length.dart | 26 +++++++++++++++++++ lib/router.dart | 5 +++- .../advanced_privacy_settings_page.dart | 13 ++++++++++ lib/src/screens/seed/pre_seed_page.dart | 15 +++++++---- lib/store/settings_store.dart | 16 ++++++++++++ .../advanced_privacy_settings_view_model.dart | 10 +++++++ res/values/strings_ar.arb | 3 ++- res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 38 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 lib/entities/seed_phrase_length.dart diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index fa572b38b..8cc469a3a 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -32,8 +32,13 @@ class BitcoinCashWalletService extends WalletService create( credentials) async { + final strength = (credentials.seedPhraseLength == 12) + ? 128 + : (credentials.seedPhraseLength == 24) + ? 256 + : 128; final wallet = await BitcoinCashWalletBase.create( - mnemonic: await Mnemonic.generate(), + mnemonic: await Mnemonic.generate(strength: strength), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); diff --git a/cw_core/lib/wallet_credentials.dart b/cw_core/lib/wallet_credentials.dart index 0cdf892bd..4d5f331c9 100644 --- a/cw_core/lib/wallet_credentials.dart +++ b/cw_core/lib/wallet_credentials.dart @@ -4,6 +4,7 @@ abstract class WalletCredentials { WalletCredentials({ required this.name, this.height, + this.seedPhraseLength, this.walletInfo, this.password, this.derivationType, @@ -12,6 +13,7 @@ abstract class WalletCredentials { final String name; final int? height; + int? seedPhraseLength; String? password; DerivationType? derivationType; String? derivationPath; diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 16dbc0b04..8810d6014 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -20,7 +20,14 @@ class EthereumWalletService extends WalletService create(EthereumNewWalletCredentials credentials) async { - final mnemonic = bip39.generateMnemonic(); + + final strength = (credentials.seedPhraseLength == 12) + ? 128 + : (credentials.seedPhraseLength == 24) + ? 256 + : 128; + + final mnemonic = bip39.generateMnemonic(strength: strength); final wallet = EthereumWallet( walletInfo: credentials.walletInfo!, mnemonic: mnemonic, diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index dda591115..8548f079f 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:flutter/foundation.dart'; @@ -18,6 +19,7 @@ class WalletCreationService { required this.secureStorage, required this.keyService, required this.sharedPreferences, + required this.settingsStore, required this.walletInfoSource}) : type = initialType { changeWalletType(type: type); @@ -26,6 +28,7 @@ class WalletCreationService { WalletType type; final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; + final SettingsStore settingsStore; final KeyService keyService; final Box walletInfoSource; WalletService? _service; @@ -56,6 +59,9 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; + if (type == WalletType.bitcoinCash || type == WalletType.ethereum) { + credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; + } await keyService.saveWalletPassword(password: password, walletName: credentials.name); final wallet = await _service!.create(credentials); diff --git a/lib/di.dart b/lib/di.dart index 8cc393510..a59483a4f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -333,6 +333,7 @@ Future setup({ keyService: getIt.get(), secureStorage: getIt.get(), sharedPreferences: getIt.get(), + settingsStore: getIt.get(), walletInfoSource: _walletInfoSource)); getIt.registerFactory(() => WalletLoadingService( @@ -340,9 +341,10 @@ Future setup({ getIt.get(), (WalletType type) => getIt.get(param1: type))); - getIt.registerFactoryParam((type, _) => WalletNewVM( - getIt.get(), getIt.get(param1: type), _walletInfoSource, - type: type)); + getIt.registerFactoryParam((type, _) => + WalletNewVM(getIt.get(), + getIt.get(param1: type), _walletInfoSource, + type: type)); getIt.registerFactoryParam((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get(), @@ -894,8 +896,9 @@ Future setup({ getIt.registerFactoryParam( (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); - getIt.registerFactoryParam( - (WalletType type, _) => PreSeedPage(type)); + getIt.registerFactoryParam( + (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) + => PreSeedPage(type, advancedPrivacySettingsViewModel)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 5ecd1bcc7..b8730d802 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -87,4 +87,5 @@ class PreferencesKey { 'should_require_totp_2fa_for_all_security_and_backup_settings'; static const selectedCake2FAPreset = 'selected_cake_2fa_preset'; static const totpSecretKey = 'totp_secret_key'; + static const currentSeedPhraseLength = 'current_seed_phrase_length'; } diff --git a/lib/entities/seed_phrase_length.dart b/lib/entities/seed_phrase_length.dart new file mode 100644 index 000000000..65e9fac40 --- /dev/null +++ b/lib/entities/seed_phrase_length.dart @@ -0,0 +1,26 @@ +import 'package:cake_wallet/generated/i18n.dart'; + +enum SeedPhraseLength { + twelveWords(12), + twentyFourWords(24); + + const SeedPhraseLength(this.value); + final int value; + + static SeedPhraseLength deserialize({required int raw}) => + SeedPhraseLength.values.firstWhere((e) => e.value == raw); + + @override + String toString() { + String label = ''; + switch (this) { + case SeedPhraseLength.twelveWords: + label = '12 Words'; + break; + case SeedPhraseLength.twentyFourWords: + label = '24 Words'; + break; + } + return label; + } +} \ No newline at end of file diff --git a/lib/router.dart b/lib/router.dart index dc2d8f8ab..8174e0be8 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -418,7 +418,10 @@ Route createRoute(RouteSettings settings) { case Routes.preSeed: return MaterialPageRoute( - builder: (_) => getIt.get(param1: settings.arguments as WalletType)); + builder: (_) => getIt.get( + param1: settings.arguments as WalletType, + param2: getIt.get( + param1: settings.arguments as WalletType))); case Routes.backup: return CupertinoPageRoute( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 386f3012b..66a28042d 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.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/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; @@ -94,6 +96,17 @@ class _AdvancedPrivacySettingsBodyState extends State( + title: S.current.seed_phrase_length, + items: SeedPhraseLength.values, + selectedItem: widget.privacySettingsViewModel.seedPhraseLength, + onItemSelected: (SeedPhraseLength length) { + widget.privacySettingsViewModel.setSeedPhraseLength(length); + }, + ); + }), ], ), bottomSectionPadding: EdgeInsets.all(24), diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index bb6902a7e..947099983 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; @@ -9,15 +10,19 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; class PreSeedPage extends BasePage { - PreSeedPage(this.type) + PreSeedPage(this.type, this.advancedPrivacySettingsViewModel) : imageLight = Image.asset('assets/images/pre_seed_light.png'), imageDark = Image.asset('assets/images/pre_seed_dark.png'), - wordsCount = _wordsCount(type); + seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value { + wordsCount = _wordsCount(type, seedPhraseLength); + } final Image imageDark; final Image imageLight; final WalletType type; - final int wordsCount; + final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; + final int seedPhraseLength; + late final int wordsCount; @override Widget? leading(BuildContext context) => null; @@ -68,13 +73,13 @@ class PreSeedPage extends BasePage { )); } - static int _wordsCount(WalletType type) { + static int _wordsCount(WalletType type, int seedPhraseLength) { switch (type) { case WalletType.monero: return 25; case WalletType.ethereum: case WalletType.bitcoinCash: - return 12; + return seedPhraseLength; default: return 24; } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 3c9ba36d5..61e9ba029 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; @@ -71,6 +72,7 @@ abstract class SettingsStoreBase with Store { required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, required this.pinTimeOutDuration, + required this.seedPhraseLength, required Cake2FAPresetsOptions initialCake2FAPresetOptions, required bool initialShouldRequireTOTP2FAForAccessingWallet, required bool initialShouldRequireTOTP2FAForSendsToContact, @@ -329,6 +331,11 @@ abstract class SettingsStoreBase with Store { (String languageCode) => sharedPreferences.setString(PreferencesKey.currentLanguageCode, languageCode)); + reaction( + (_) => seedPhraseLength, + (SeedPhraseLength seedPhraseWordCount) => + sharedPreferences.setInt(PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value)); + reaction( (_) => pinTimeOutDuration, (PinCodeRequiredDuration pinCodeInterval) => @@ -418,6 +425,7 @@ abstract class SettingsStoreBase with Store { static const defaultActionsMode = 11; static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes; static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized; + static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords; @observable FiatCurrency fiatCurrency; @@ -509,6 +517,9 @@ abstract class SettingsStoreBase with Store { @observable PinCodeRequiredDuration pinTimeOutDuration; + @observable + SeedPhraseLength seedPhraseLength; + @computed ThemeData get theme => currentTheme.themeData; @@ -699,9 +710,13 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); final timeOutDuration = sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration); + final seedPhraseCount = sharedPreferences.getInt(PreferencesKey.currentSeedPhraseLength); final pinCodeTimeOutDuration = timeOutDuration != null ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) : defaultPinCodeTimeOutDuration; + final seedPhraseWordCount = seedPhraseCount != null + ? SeedPhraseLength.deserialize(raw: seedPhraseCount) + : defaultSeedPhraseLength; final sortBalanceBy = SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = @@ -816,6 +831,7 @@ abstract class SettingsStoreBase with Store { actionlistDisplayMode: actionListDisplayMode, initialPinLength: pinLength, pinTimeOutDuration: pinCodeTimeOutDuration, + seedPhraseLength: seedPhraseWordCount, initialLanguageCode: savedLanguageCode, sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 380937212..b67a4378a 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -25,9 +26,15 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; + bool get hasSeedPhraseLengthOption => + type == WalletType.bitcoinCash || type == WalletType.ethereum; + @computed bool get addCustomNode => _addCustomNode; + @computed + SeedPhraseLength get seedPhraseLength => _settingsStore.seedPhraseLength; + @action void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode; @@ -36,4 +43,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @action void toggleAddCustomNode() => _addCustomNode = !_addCustomNode; + + @action + void setSeedPhraseLength(SeedPhraseLength length) => _settingsStore.seedPhraseLength = length; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4727a0262..21ebc7def 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -726,7 +726,8 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير" -} \ No newline at end of file +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d52529e38..b091e072f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "seed_phrase_length": "Дължина на началната фраза", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна" diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8b86c517f..2c73fdc3e 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "seed_phrase_length": "Délka fráze semene", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna" diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 0928e1462..567f9d9c0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "seed_phrase_length": "Länge der Seed-Phrase", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld" diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 55b6f8339..1d50540a7 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -731,6 +731,7 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "seed_phrase_length": "Seed phrase length", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change" diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 048bf05ea..d021902d3 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "seed_phrase_length": "Longitud de la frase inicial", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar" diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d82f8a677..9e6a6c07e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -728,6 +728,7 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 6c0644316..b865c4790 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -708,6 +708,7 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "seed_phrase_length": "Tsawon jimlar iri", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza" diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index ae0b1a94d..5f53141e5 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "seed_phrase_length": "बीज वाक्यांश की लंबाई", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन" diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index d9dcba723..58bd0f497 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "seed_phrase_length": "Duljina početne fraze", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti" diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index e6498d169..c03523f5d 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -718,6 +718,7 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "seed_phrase_length": "Panjang frase benih", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah" diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index b78644766..1c9387180 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "seed_phrase_length": "Lunghezza della frase seed", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica" diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 1c7ad6497..42aeb34f8 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "seed_phrase_length": "シードフレーズの長さ", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化" diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index cbf1744e1..8e09c7034 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "seed_phrase_length": "시드 문구 길이", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화" diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index bb2f8a86d..71255d98e 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း" diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index e833dde50..4de0fac30 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "seed_phrase_length": "Lengte van de zaadzin", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging" diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 8429cec8a..160bf2f88 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "seed_phrase_length": "Długość frazy początkowej", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana" diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 9bb27a582..ab221dd49 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -729,6 +729,7 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "seed_phrase_length": "Comprimento da frase-semente", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar" diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index d0f64c8b2..4474c26e3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "seed_phrase_length": "Длина исходной фразы", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять" diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 3159bd649..90f71cf75 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "seed_phrase_length": "ความยาววลีของเมล็ด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน" diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index b38dc35ad..ffd89c30e 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -725,6 +725,7 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "seed_phrase_length": "Haba ng parirala ng binhi", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin" diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 77d29f8d2..0e2690ad6 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "seed_phrase_length": "Çekirdek cümle uzunluğu", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek" diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index aa9e29687..044bde32a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "seed_phrase_length": "Довжина початкової фрази", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна" diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e8cf03835..a8b3813a3 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں" diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 7784e785a..6b46201b8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -724,6 +724,7 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "seed_phrase_length": "Gigun gbolohun irugbin", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada" diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 454c79194..c54ba2696 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -729,6 +729,7 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "seed_phrase_length": "种子短语长度", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变" From f4e71c72ef9c509dffa95bb46cb3ba3d5f0aa52e Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 17 Nov 2023 13:35:46 -0500 Subject: [PATCH 10/17] Nano rep fixes (#1145) * add preference keys for default nano/banano rep * updates to change rep page, add success message * forgot to save this file * nano_client cleanup * first pass * refactor to use sharedprefs in nano_client * review fixes --- cw_nano/lib/nano_client.dart | 204 +++++++++--------- cw_nano/lib/nano_wallet.dart | 2 +- cw_nano/pubspec.lock | 63 +++++- cw_nano/pubspec.yaml | 1 + lib/core/backup_service.dart | 15 +- lib/di.dart | 11 +- lib/entities/preferences_key.dart | 2 + lib/nano/cw_nano.dart | 5 +- lib/reactions/on_current_wallet_change.dart | 1 + .../screens/nano/nano_change_rep_page.dart | 52 ++++- lib/store/settings_store.dart | 80 ++++--- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 5 +- res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 37 files changed, 321 insertions(+), 149 deletions(-) diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 2866c4653..f1d08204a 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -8,18 +8,28 @@ import 'package:cw_nano/nano_util.dart'; import 'package:http/http.dart' as http; import 'package:nanodart/nanodart.dart'; import 'package:cw_core/node.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class NanoClient { - static const String DEFAULT_REPRESENTATIVE = - "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579"; - static const Map CAKE_HEADERS = { "Content-Type": "application/json", "nano-app": "cake-wallet" }; + NanoClient() { + SharedPreferences.getInstance().then((value) => prefs = value); + } + + late SharedPreferences prefs; Node? _node; Node? _powNode; + static const String _defaultDefaultRepresentative = + "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579"; + + String getRepFromPrefs() { + // from preferences_key.dart "defaultNanoRep" key: + return prefs.getString("default_nano_representative") ?? _defaultDefaultRepresentative; + } bool connect(Node node) { try { @@ -84,44 +94,45 @@ class NanoClient { required String repAddress, required String ourAddress, }) async { + AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress); + + if (accountInfo == null) { + throw Exception( + "error while getting account info, you can't change the rep of an unopened account"); + } + + // construct the change block: + Map changeBlock = { + "type": "state", + "account": ourAddress, + "previous": accountInfo.frontier, + "representative": repAddress, + "balance": accountInfo.balance, + "link": "0000000000000000000000000000000000000000000000000000000000000000", + "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", + }; + + // sign the change block: + final String hash = NanoBlocks.computeStateHash( + NanoAccountType.NANO, + changeBlock["account"]!, + changeBlock["previous"]!, + changeBlock["representative"]!, + BigInt.parse(changeBlock["balance"]!), + changeBlock["link"]!, + ); + final String signature = NanoSignatures.signBlock(hash, privateKey); + + // get PoW for the send block: + final String work = await requestWork(accountInfo.frontier); + + changeBlock["signature"] = signature; + changeBlock["work"] = work; + try { - AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress); - - if (accountInfo == null) { - throw Exception("error while getting account info"); - } - - // construct the change block: - Map changeBlock = { - "type": "state", - "account": ourAddress, - "previous": accountInfo.frontier, - "representative": repAddress, - "balance": accountInfo.balance, - "link": "0000000000000000000000000000000000000000000000000000000000000000", - "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", - }; - - // sign the change block: - final String hash = NanoBlocks.computeStateHash( - NanoAccountType.NANO, - changeBlock["account"]!, - changeBlock["previous"]!, - changeBlock["representative"]!, - BigInt.parse(changeBlock["balance"]!), - changeBlock["link"]!, - ); - final String signature = NanoSignatures.signBlock(hash, privateKey); - - // get PoW for the send block: - final String work = await requestWork(accountInfo.frontier); - - changeBlock["signature"] = signature; - changeBlock["work"] = work; - return await processBlock(changeBlock, "change"); } catch (e) { - throw Exception("error while changing representative"); + throw Exception("error while changing representative: $e"); } } @@ -191,68 +202,63 @@ class NanoClient { BigInt? balanceAfterTx, String? previousHash, }) async { - try { - // our address: - final String publicAddress = NanoUtil.privateKeyToAddress(privateKey); + // our address: + final String publicAddress = NanoUtil.privateKeyToAddress(privateKey); - // first get the current account balance: - if (balanceAfterTx == null) { - final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance; - final BigInt txAmount = BigInt.parse(amountRaw); - balanceAfterTx = currentBalance - txAmount; - } - - // get the account info (we need the frontier and representative): - AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress); - if (infoResponse == null) { - throw Exception( - "error while getting account info! (we probably don't have an open account yet)"); - } - - String frontier = infoResponse.frontier; - // override if provided: - if (previousHash != null) { - frontier = previousHash; - } - final String representative = infoResponse.representative; - // link = destination address: - final String link = NanoAccounts.extractPublicKey(destinationAddress); - final String linkAsAccount = destinationAddress; - - // construct the send block: - Map sendBlock = { - "type": "state", - "account": publicAddress, - "previous": frontier, - "representative": representative, - "balance": balanceAfterTx.toString(), - "link": link, - }; - - // sign the send block: - final String hash = NanoBlocks.computeStateHash( - NanoAccountType.NANO, - sendBlock["account"]!, - sendBlock["previous"]!, - sendBlock["representative"]!, - BigInt.parse(sendBlock["balance"]!), - sendBlock["link"]!, - ); - final String signature = NanoSignatures.signBlock(hash, privateKey); - - // get PoW for the send block: - final String work = await requestWork(frontier); - - sendBlock["link_as_account"] = linkAsAccount; - sendBlock["signature"] = signature; - sendBlock["work"] = work; - - // ready to post send block: - return sendBlock; - } catch (e) { - print(e); - rethrow; + // first get the current account balance: + if (balanceAfterTx == null) { + final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance; + final BigInt txAmount = BigInt.parse(amountRaw); + balanceAfterTx = currentBalance - txAmount; } + + // get the account info (we need the frontier and representative): + AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress); + if (infoResponse == null) { + throw Exception( + "error while getting account info! (we probably don't have an open account yet)"); + } + + String frontier = infoResponse.frontier; + // override if provided: + if (previousHash != null) { + frontier = previousHash; + } + final String representative = infoResponse.representative; + // link = destination address: + final String link = NanoAccounts.extractPublicKey(destinationAddress); + final String linkAsAccount = destinationAddress; + + // construct the send block: + Map sendBlock = { + "type": "state", + "account": publicAddress, + "previous": frontier, + "representative": representative, + "balance": balanceAfterTx.toString(), + "link": link, + }; + + // sign the send block: + final String hash = NanoBlocks.computeStateHash( + NanoAccountType.NANO, + sendBlock["account"]!, + sendBlock["previous"]!, + sendBlock["representative"]!, + BigInt.parse(sendBlock["balance"]!), + sendBlock["link"]!, + ); + final String signature = NanoSignatures.signBlock(hash, privateKey); + + // get PoW for the send block: + final String work = await requestWork(frontier); + + sendBlock["link_as_account"] = linkAsAccount; + sendBlock["signature"] = signature; + sendBlock["work"] = work; + + // ready to post send block: + return sendBlock; } Future receiveBlock({ @@ -274,7 +280,7 @@ class NanoClient { // account is not open yet, we need to create an open block: openBlock = true; // we don't have a representative set yet: - representative = DEFAULT_REPRESENTATIVE; + representative = await getRepFromPrefs(); // we don't have a frontier yet: frontier = "0000000000000000000000000000000000000000000000000000000000000000"; } else { diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index bf7cc6bca..44d564fc6 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -382,7 +382,7 @@ abstract class NanoWalletBase _representativeAddress = accountInfo.representative; } catch (e) { // account not found: - _representativeAddress = NanoClient.DEFAULT_REPRESENTATIVE; + _representativeAddress = await _client.getRepFromPrefs(); throw Exception("Failed to get representative address $e"); } } diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index ea932baee..d28558422 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -290,6 +290,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -594,6 +599,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" shelf: dependency: transitive description: @@ -753,4 +814,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.3.0" + flutter: ">=3.7.0" diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index 054dd5df4..f06177d3c 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -21,6 +21,7 @@ dependencies: ed25519_hd_key: ^2.2.0 hex: ^0.2.0 http: ^1.1.0 + shared_preferences: ^2.0.15 cw_core: path: ../cw_core diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 85fd8f588..2913505c0 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -247,6 +247,8 @@ class BackupService { final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?; final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?; final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; + final defaultNanoRep = data[PreferencesKey.defaultNanoRep] as String?; + final defaultBananoRep = data[PreferencesKey.defaultBananoRep] as String?; final lookupsTwitter = data[PreferencesKey.lookupsTwitter] as bool?; final lookupsMastodon = data[PreferencesKey.lookupsMastodon] as bool?; final lookupsYatService = data[PreferencesKey.lookupsYatService] as bool?; @@ -322,11 +324,10 @@ class BackupService { if (currentTheme != null && DeviceInfo.instance.isMobile) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme); - // enforce dark theme on desktop platforms until the design is ready: + // enforce dark theme on desktop platforms until the design is ready: } else if (DeviceInfo.instance.isDesktop) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw); } - if (exchangeStatus != null) await _sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus); @@ -389,6 +390,13 @@ class BackupService { if (useEtherscan != null) await _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan); + if (defaultNanoRep != null) + await _sharedPreferences.setString(PreferencesKey.defaultNanoRep, defaultNanoRep); + + if (defaultBananoRep != null) + await _sharedPreferences.setString(PreferencesKey.defaultBananoRep, defaultBananoRep); + + if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); if (lookupsTwitter != null) await _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, lookupsTwitter); @@ -560,6 +568,9 @@ class BackupService { PreferencesKey.pinNativeTokenAtTop: _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan), + PreferencesKey.defaultNanoRep: _sharedPreferences.getString(PreferencesKey.defaultNanoRep), + PreferencesKey.defaultBananoRep: + _sharedPreferences.getString(PreferencesKey.defaultBananoRep), PreferencesKey.lookupsTwitter: _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), PreferencesKey.lookupsMastodon: _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), PreferencesKey.lookupsYatService: diff --git a/lib/di.dart b/lib/di.dart index a59483a4f..94f5dbb63 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -522,8 +522,7 @@ Future setup({ getIt.registerFactory( () => Modify2FAPage(setup2FAViewModel: getIt.get())); - getIt.registerFactory( - () => DesktopSettingsPage()); + getIt.registerFactory(() => DesktopSettingsPage()); getIt.registerFactoryParam( (pageOption, _) => ReceiveOptionViewModel(getIt.get().wallet!, pageOption)); @@ -766,7 +765,10 @@ Future setup({ getIt.registerFactory(() => OtherSettingsPage(getIt.get())); - getIt.registerFactory(() => NanoChangeRepPage(getIt.get().wallet!)); + getIt.registerFactory(() => NanoChangeRepPage( + settingsStore: getIt.get().settingsStore, + wallet: getIt.get().wallet!, + )); getIt.registerFactoryParam( (WalletType? type, bool? isPow) => NodeCreateOrEditViewModel( @@ -839,7 +841,8 @@ Future setup({ case WalletType.ethereum: return ethereum!.createEthereumWalletService(_walletInfoSource); case WalletType.bitcoinCash: - return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoinCash! + .createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); case WalletType.nano: return nano!.createNanoWalletService(_walletInfoSource); default: diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index b8730d802..85df63b69 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -50,6 +50,8 @@ class PreferencesKey { static const sortBalanceBy = 'sort_balance_by'; static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const useEtherscan = 'use_etherscan'; + static const defaultNanoRep = 'default_nano_representative'; + static const defaultBananoRep = 'default_banano_representative'; static const lookupsTwitter = 'looks_up_twitter'; static const lookupsMastodon = 'looks_up_mastodon'; static const lookupsYatService = 'looks_up_mastodon'; diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 778b2584a..0c072c95c 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -166,7 +166,10 @@ class CWNano extends Nano { @override Future changeRep(Object wallet, String address) async { - return (wallet as NanoWallet).changeRep(address); + if ((wallet as NanoWallet).transactionHistory.transactions.isEmpty) { + throw Exception("Can't change representative without an existing transaction history"); + } + return wallet.changeRep(address); } @override diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index cf1cf7b81..5f956dc1a 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart index bf541c39a..a625f7e29 100644 --- a/lib/src/screens/nano/nano_change_rep_page.dart +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -1,8 +1,11 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; @@ -14,21 +17,28 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class NanoChangeRepPage extends BasePage { - NanoChangeRepPage(WalletBase wallet) + NanoChangeRepPage({required SettingsStore settingsStore, required WalletBase wallet}) : _wallet = wallet, - _addressController = TextEditingController() { + _settingsStore = settingsStore, + _addressController = TextEditingController(), + _formKey = GlobalKey() { _addressController.text = nano!.getRepresentative(wallet); } final TextEditingController _addressController; final WalletBase _wallet; + final SettingsStore _settingsStore; + + final GlobalKey _formKey; @override String get title => S.current.change_rep; @override Widget body(BuildContext context) { - return Container( + return Form( + key: _formKey, + child: Container( padding: EdgeInsets.only(left: 24, right: 24), child: ScrollableWithBottomSection( contentPadding: EdgeInsets.only(bottom: 24.0), @@ -38,9 +48,17 @@ class NanoChangeRepPage extends BasePage { Row( children: [ Expanded( - child: BaseTextFormField( + child: AddressTextField( controller: _addressController, - hintText: S.of(context).node_address, + onURIScanned: (uri) { + final paymentRequest = PaymentRequest.fromUri(uri); + _addressController.text = paymentRequest.address; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + ], + buttonColor: Theme.of(context).extension()!.actionButtonColor, validator: AddressValidator(type: CryptoCurrency.nano), ), ) @@ -59,6 +77,11 @@ class NanoChangeRepPage extends BasePage { padding: EdgeInsets.only(right: 8.0), child: LoadingPrimaryButton( onPressed: () async { + if (_formKey.currentState != null && + !_formKey.currentState!.validate()) { + return; + } + final confirmed = await showPopUp( context: context, builder: (BuildContext context) { @@ -74,8 +97,19 @@ class NanoChangeRepPage extends BasePage { if (confirmed) { try { + _settingsStore.defaultNanoRep = _addressController.text; + await nano!.changeRep(_wallet, _addressController.text); - Navigator.of(context).pop(); + + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).successful, + alertContent: S.of(context).change_rep_successful, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.pop(context)); + }); } catch (e) { await showPopUp( context: context, @@ -97,6 +131,8 @@ class NanoChangeRepPage extends BasePage { )), ], )), - )); + ), + ), + ); } } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 61e9ba029..1522ea354 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -86,6 +86,8 @@ abstract class SettingsStoreBase with Store { required this.sortBalanceBy, required this.pinNativeTokenAtTop, required this.useEtherscan, + required this.defaultNanoRep, + required this.defaultBananoRep, required this.lookupsTwitter, required this.lookupsMastodon, required this.lookupsYatService, @@ -378,6 +380,13 @@ abstract class SettingsStoreBase with Store { (bool useEtherscan) => _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan)); + reaction((_) => defaultNanoRep, + (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep)); + + reaction( + (_) => defaultBananoRep, + (String bananoRep) => + _sharedPreferences.setString(PreferencesKey.defaultBananoRep, bananoRep)); reaction( (_) => lookupsTwitter, (bool looksUpTwitter) => @@ -541,6 +550,12 @@ abstract class SettingsStoreBase with Store { @observable bool useEtherscan; + @observable + String defaultNanoRep; + + @observable + String defaultBananoRep; + @observable bool lookupsTwitter; @@ -618,8 +633,8 @@ abstract class SettingsStoreBase with Store { TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority( raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!); TransactionPriority? bitcoinTransactionPriority = - bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); + bitcoin?.deserializeBitcoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); TransactionPriority? havenTransactionPriority; TransactionPriority? litecoinTransactionPriority; @@ -658,8 +673,8 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; - final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt( - PreferencesKey.defaultBuyProvider) ?? 0]; + final defaultBuyProvider = + BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); @@ -678,7 +693,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; final shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? @@ -689,7 +704,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false; final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? ''; @@ -718,10 +733,12 @@ abstract class SettingsStoreBase with Store { ? SeedPhraseLength.deserialize(raw: seedPhraseCount) : defaultSeedPhraseLength; final sortBalanceBy = - SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; + SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; + final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; @@ -738,11 +755,11 @@ abstract class SettingsStoreBase with Store { await LanguageService.localeDetection(); final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); final bitcoinCashElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -759,7 +776,7 @@ abstract class SettingsStoreBase with Store { final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); final autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -799,10 +816,10 @@ abstract class SettingsStoreBase with Store { powNodes[WalletType.nano] = nanoPowNode; } - final savedSyncMode = SyncMode.all.firstWhere((element) { - return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); - }); - final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; + final savedSyncMode = SyncMode.all.firstWhere((element) { + return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); + }); + final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; return SettingsStore( sharedPreferences: sharedPreferences, @@ -836,6 +853,8 @@ abstract class SettingsStoreBase with Store { sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, useEtherscan: useEtherscan, + defaultNanoRep: defaultNanoRep, + defaultBananoRep: defaultBananoRep, lookupsTwitter: lookupsTwitter, lookupsMastodon: lookupsMastodon, lookupsYatService: lookupsYatService, @@ -874,35 +893,35 @@ abstract class SettingsStoreBase with Store { raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); priority[WalletType.monero] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.monero]!; priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.bitcoin]!; if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { priority[WalletType.haven] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? priority[WalletType.haven]!; } if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) { priority[WalletType.litecoin] = bitcoin?.deserializeLitecoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? priority[WalletType.litecoin]!; } if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) { priority[WalletType.ethereum] = ethereum?.deserializeEthereumTransactionPriority( - sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? priority[WalletType.ethereum]!; } if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority( - sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? priority[WalletType.bitcoinCash]!; } final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -921,7 +940,7 @@ abstract class SettingsStoreBase with Store { disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; defaultBuyProvider = - BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; + BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; @@ -938,7 +957,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? @@ -949,7 +968,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? @@ -982,6 +1001,8 @@ abstract class SettingsStoreBase with Store { .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; + defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; @@ -991,11 +1012,11 @@ abstract class SettingsStoreBase with Store { final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); final bitcoinCashElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -1057,7 +1078,8 @@ abstract class SettingsStoreBase with Store { await _sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int); break; case WalletType.bitcoinCash: - await _sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); + await _sharedPreferences.setInt( + PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); break; case WalletType.nano: await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 21ebc7def..a5298c343 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -720,6 +720,7 @@ "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", "seed_key": "مفتاح البذور", "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", + "change_rep_successful": "تم تغيير ممثل بنجاح", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b091e072f..3b085cd59 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "Въведете URI на WalletConnect", "seed_key": "Ключ за семена", "enter_seed_phrase": "Въведете вашата фраза за семена", + "change_rep_successful": "Успешно промени представител", "add_contact": "Добави контакт", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", "domain_looks_up": "Търсене на домейни", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 2c73fdc3e..f6d024957 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", "seed_key": "Klíč semen", "enter_seed_phrase": "Zadejte svou frázi semen", + "change_rep_successful": "Úspěšně změnil zástupce", "add_contact": "Přidat kontakt", "exchange_provider_unsupported": "${providerName} již není podporováno!", "domain_looks_up": "Vyhledávání domén", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 567f9d9c0..6519f0ef6 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -722,8 +722,9 @@ "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Seed-Schlüssel", - "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", + "seed_key": "Samenschlüssel", + "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", + "change_rep_successful": "Erfolgreich veränderte Vertreter", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", "domain_looks_up": "Domain-Suchen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 1d50540a7..2c1d00eb6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -725,6 +725,7 @@ "enterWalletConnectURI": "Enter WalletConnect URI", "seed_key": "Seed key", "enter_seed_phrase": "Enter your seed phrase", + "change_rep_successful": "Successfully changed representative", "add_contact": "Add contact", "exchange_provider_unsupported": "${providerName} is no longer supported!", "domain_looks_up": "Domain lookups", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index d021902d3..3629a6d37 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Ingrese el URI de WalletConnect", "seed_key": "Llave de semilla", "enter_seed_phrase": "Ingrese su frase de semillas", + "change_rep_successful": "Representante cambiado con éxito", "add_contact": "Agregar contacto", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", "domain_looks_up": "Búsquedas de dominio", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9e6a6c07e..cae478d7d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -722,8 +722,9 @@ "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé secrète (seed key)", - "enter_seed_phrase": "Entrez votre phrase secrète (seed)", + "seed_key": "Clé de graines", + "enter_seed_phrase": "Entrez votre phrase de semence", + "change_rep_successful": "Représentant changé avec succès", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index b865c4790..84c3b4b74 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -702,6 +702,7 @@ "enterWalletConnectURI": "Shigar da WalletConnect URI", "seed_key": "Maɓallin iri", "enter_seed_phrase": "Shigar da Sert Sentarku", + "change_rep_successful": "An samu nasarar canzawa wakilin", "add_contact": "Ƙara lamba", "exchange_provider_unsupported": "${providerName}", "domain_looks_up": "Binciken yanki", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5f53141e5..af3b888cb 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", "seed_key": "बीज कुंजी", "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", + "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि", "add_contact": "संपर्क जोड़ें", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", "domain_looks_up": "डोमेन लुकअप", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 58bd0f497..3c56b8552 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "Unesite WalletConnect URI", "seed_key": "Sjemenski ključ", "enter_seed_phrase": "Unesite svoju sjemensku frazu", + "change_rep_successful": "Uspješno promijenjena reprezentativna", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} više nije podržan!", "domain_looks_up": "Pretraga domena", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c03523f5d..b3d22780a 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -712,6 +712,7 @@ "enterWalletConnectURI": "Masukkan URI WalletConnect", "seed_key": "Kunci benih", "enter_seed_phrase": "Masukkan frasa benih Anda", + "change_rep_successful": "Berhasil mengubah perwakilan", "add_contact": "Tambah kontak", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", "domain_looks_up": "Pencarian domain", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 1c9387180..8fc157f27 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", "seed_key": "Chiave di semi", "enter_seed_phrase": "Inserisci la tua frase di semi", + "change_rep_successful": "Rappresentante modificato con successo", "add_contact": "Aggiungi contatto", "exchange_provider_unsupported": "${providerName} non è più supportato!", "domain_looks_up": "Ricerche di domini", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 42aeb34f8..06d8efd37 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "WalletConnect URI を入力してください", "seed_key": "シードキー", "enter_seed_phrase": "シードフレーズを入力してください", + "change_rep_successful": "代表者の変更に成功しました", "add_contact": "連絡先を追加", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", "domain_looks_up": "ドメイン検索", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 8e09c7034..6830b1183 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", "seed_key": "시드 키", "enter_seed_phrase": "시드 문구를 입력하십시오", + "change_rep_successful": "대리인이 성공적으로 변경되었습니다", "add_contact": "주소록에 추가", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", "domain_looks_up": "도메인 조회", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 71255d98e..ff8f6683b 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", "seed_key": "မျိုးစေ့သော့", "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", + "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 4de0fac30..753e28cd5 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Voer WalletConnect-URI in", "seed_key": "Zaadsleutel", "enter_seed_phrase": "Voer uw zaadzin in", + "change_rep_successful": "Met succes veranderde vertegenwoordiger", "add_contact": "Contactpersoon toevoegen", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", "domain_looks_up": "Domein opzoeken", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 160bf2f88..1900ca590 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", "seed_key": "Klucz nasion", "enter_seed_phrase": "Wprowadź swoją frazę nasienną", + "change_rep_successful": "Pomyślnie zmienił przedstawiciela", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", "domain_looks_up": "Wyszukiwanie domen", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ab221dd49..86c7a6b0d 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -723,6 +723,7 @@ "enterWalletConnectURI": "Insira o URI do WalletConnect", "seed_key": "Chave de semente", "enter_seed_phrase": "Digite sua frase de semente", + "change_rep_successful": "Mudou com sucesso o representante", "add_contact": "Adicionar contato", "exchange_provider_unsupported": "${providerName} não é mais suportado!", "domain_looks_up": "Pesquisas de domínio", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 4474c26e3..a37b0908b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Введите URI WalletConnect", "seed_key": "Ключ семян", "enter_seed_phrase": "Введите свою семенную фразу", + "change_rep_successful": "Успешно изменил представитель", "add_contact": "Добавить контакт", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", "domain_looks_up": "Поиск доменов", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 90f71cf75..fa36c04bb 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", "seed_key": "คีย์เมล็ดพันธุ์", "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", + "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ", "add_contact": "เพิ่มผู้ติดต่อ", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", "domain_looks_up": "การค้นหาโดเมน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index ffd89c30e..b8bf168ce 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -719,6 +719,7 @@ "enterWalletConnectURI": "Ilagay ang WalletConnect URI", "seed_key": "Seed Key", "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", + "change_rep_successful": "Matagumpay na nagbago ng kinatawan", "add_contact": "Magdagdag ng contact", "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", "domain_looks_up": "Mga paghahanap ng domain", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 0e2690ad6..f7962b526 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI'sini girin", "seed_key": "Tohum", "enter_seed_phrase": "Tohum ifadenizi girin", + "change_rep_successful": "Temsilciyi başarıyla değiştirdi", "add_contact": "Kişi ekle", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", "domain_looks_up": "Etki alanı aramaları", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 044bde32a..0e4cc3ecb 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Введіть URI WalletConnect", "seed_key": "Насіннєвий ключ", "enter_seed_phrase": "Введіть свою насіннєву фразу", + "change_rep_successful": "Успішно змінив представник", "add_contact": "Додати контакт", "exchange_provider_unsupported": "${providerName} більше не підтримується!", "domain_looks_up": "Пошук доменів", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a8b3813a3..cd05010d7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", "seed_key": "بیج کی کلید", "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", + "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", "domain_looks_up": "ڈومین تلاش کرنا", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 6b46201b8..fc632f8a8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -718,6 +718,7 @@ "enterWalletConnectURI": "Tẹ WalletConnect URI sii", "seed_key": "Bọtini Ose", "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", + "change_rep_successful": "Ni ifijišẹ yipada aṣoju", "add_contact": "Fi olubasọrọ kun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", "domain_looks_up": "Awọn wiwa agbegbe", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c54ba2696..e57df96d9 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -723,6 +723,7 @@ "enterWalletConnectURI": "输入 WalletConnect URI", "seed_key": "种子钥匙", "enter_seed_phrase": "输入您的种子短语", + "change_rep_successful": "成功改变了代表", "add_contact": "增加联系人", "exchange_provider_unsupported": "${providerName}不再支持!", "domain_looks_up": "域名查找", From 539eb9b3eb27306c5b3b578f17408ecf0dd4e242 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Fri, 17 Nov 2023 19:37:32 +0100 Subject: [PATCH 11/17] Cw 523 robinhood enhancements (#1176) * CW-523 Add BCH support to Robinhood * CW-523 Only show popup on Robinhood error * CW-523 Add BitcoinCash to Robinhood Provider --- .../lib/src/bitcoin_cash_address_utils.dart | 1 + .../lib/src/bitcoin_cash_wallet.dart | 14 +++++++++++++ lib/buy/robinhood/robinhood_buy_provider.dart | 20 +++++++++++-------- lib/entities/main_actions.dart | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart index ca47ea9f6..5832835eb 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart @@ -2,4 +2,5 @@ import 'package:bitbox/bitbox.dart' as bitbox; class AddressUtils { static String getCashAddrFormat(String address) => bitbox.Address.toCashAddress(address); + static String toLegacyAddress(String address) => bitbox.Address.toLegacyAddress(address); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index b4924e2db..5f2a33ab6 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -294,4 +296,16 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { return 0; } + + @override + String signMessage(String message, {String? address = null}) { + final index = address != null + ? walletAddresses.addresses + .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) + .index + : null; + return index == null + ? base64Encode(hd.sign(message)) + : base64Encode(hd.derive(index).sign(message)); + } } diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index e7a9e0579..ade0bf99f 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; @@ -12,8 +11,7 @@ import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class RobinhoodBuyProvider { - RobinhoodBuyProvider({required WalletBase wallet}) - : this._wallet = wallet; + RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet; final WalletBase _wallet; @@ -21,10 +19,15 @@ class RobinhoodBuyProvider { static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; String get _applicationId => secrets.robinhoodApplicationId; + String get _apiSecret => secrets.robinhoodCIdApiSecret; - bool get isAvailable => - [WalletType.bitcoin, WalletType.litecoin, WalletType.ethereum].contains(_wallet.type); + bool get isAvailable => [ + WalletType.bitcoin, + WalletType.bitcoinCash, + WalletType.litecoin, + WalletType.ethereum + ].contains(_wallet.type); String getSignature(String message) { switch (_wallet.type) { @@ -32,6 +35,7 @@ class RobinhoodBuyProvider { return _wallet.signMessage(message); case WalletType.litecoin: case WalletType.bitcoin: + case WalletType.bitcoinCash: return _wallet.signMessage(message, address: _wallet.walletAddresses.address); default: throw Exception("WalletType is not available for Robinhood ${_wallet.type}"); @@ -55,7 +59,8 @@ class RobinhoodBuyProvider { if (response.statusCode == 200) { return (jsonDecode(response.body) as Map)['connectId'] as String; } else { - throw Exception('Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); + throw Exception( + 'Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); } } @@ -76,8 +81,7 @@ class RobinhoodBuyProvider { try { final uri = await requestUrl(); await launchUrl(uri, mode: LaunchMode.externalApplication); - } catch (e, s) { - ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s)); + } catch (_) { await showPopUp( context: context, builder: (BuildContext context) { diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 5f270deaf..46865cbcc 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -52,7 +52,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: - // case WalletType.bitcoinCash: // TODO: add sign message function to BCH first + case WalletType.bitcoinCash: switch (defaultBuyProvider) { case BuyProviderType.AskEachTime: Navigator.pushNamed(context, Routes.buy); From e0925092641449c151f8213ca808d617f8eef29c Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 18 Nov 2023 00:15:15 +0200 Subject: [PATCH 12/17] Generic fixes (#1173) * - Catch get balance network issues - Disable remove button when adding node * Update packages and android gradle version minor enhancements * Backup issue fix * update workflow java version * Remove useless permission check for saving file * minor enhancements * only delete secure storage key before overriding it on MacOS * Minor UI changes * Remove debug prints [skip ci] * Revert FR localization changes --- .github/workflows/cache_dependencies.yml | 2 +- .github/workflows/pr_test_build.yml | 2 +- android/app/build.gradle | 1 - android/app/src/main/AndroidManifestBase.xml | 1 + android/build.gradle | 4 +- cw_ethereum/lib/ethereum_client.dart | 9 +- cw_haven/android/build.gradle | 4 +- cw_monero/android/build.gradle | 4 +- cw_shared_external/android/build.gradle | 4 +- lib/core/auth_service.dart | 6 +- lib/core/backup_service.dart | 2 +- lib/ionia/ionia_service.dart | 5 +- .../on_wallet_sync_status_change.dart | 6 +- lib/src/screens/backup/backup_page.dart | 10 +- lib/src/screens/buy/buy_options_page.dart | 20 +-- .../monero_account_list_page.dart | 4 +- .../monero_accounts/widgets/account_tile.dart | 3 +- .../nodes/node_create_or_edit_page.dart | 36 +++--- .../restore/restore_from_backup_page.dart | 114 +++++++++++++----- .../screens/restore/restore_options_page.dart | 9 +- lib/src/widgets/base_alert_dialog.dart | 3 +- lib/src/widgets/option_tile.dart | 2 +- lib/utils/permission_handler.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 10 +- pubspec_base.yaml | 15 ++- res/values/strings_fr.arb | 4 +- 26 files changed, 168 insertions(+), 116 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 5373bbc87..bf0d0f7bc 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: '8.x' + java-version: '11.x' - name: Flutter action uses: subosito/flutter-action@v1 diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 5434429b2..3c6b132bd 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: "8.x" + java-version: "11.x" - name: Flutter action uses: subosito/flutter-action@v1 diff --git a/android/app/build.gradle b/android/app/build.gradle index 946c53697..e6b9eb2f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -75,7 +75,6 @@ android { shrinkResources false minifyEnabled false - useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 77a555db8..910149f60 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -3,6 +3,7 @@ + diff --git a/android/build.gradle b/android/build.gradle index bd4ebd770..8286d9cb9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.6.21' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' + classpath 'com.android.tools.build:gradle:7.3.0' classpath 'com.google.gms:google-services:4.3.8' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 42221c4f5..f0c7381e8 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -38,8 +38,13 @@ class EthereumClient { // }); } - Future getBalance(EthereumAddress address) async => - await _client!.getBalance(address); + Future getBalance(EthereumAddress address) async { + try { + return await _client!.getBalance(address); + } catch (_) { + return EtherAmount.zero(); + } + } Future getGasUnitPrice() async { try { diff --git a/cw_haven/android/build.gradle b/cw_haven/android/build.gradle index 91da1b857..fb941f657 100644 --- a/cw_haven/android/build.gradle +++ b/cw_haven/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.cw_haven' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/cw_monero/android/build.gradle b/cw_monero/android/build.gradle index 1d7ae93d8..fc4835e81 100644 --- a/cw_monero/android/build.gradle +++ b/cw_monero/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.monero' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/cw_shared_external/android/build.gradle b/cw_shared_external/android/build.gradle index d6cdaf658..8db51f0e6 100644 --- a/cw_shared_external/android/build.gradle +++ b/cw_shared_external/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.cw_shared_external' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 321b5b94a..c072bf65e 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -40,7 +42,9 @@ class AuthService with Store { final encodedPassword = encodedPinCode(pin: password); // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless // we delete what's there first: - await secureStorage.delete(key: key); + if (Platform.isMacOS) { + await secureStorage.delete(key: key); + } await secureStorage.write(key: key, value: encodedPassword); } diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2913505c0..b13a01889 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -295,7 +295,7 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - if (Platform.isMacOS || Platform.isLinux) { + if (DeviceInfo.instance.isDesktop) { await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false); } else if (allowBiometricalAuthentication != null) { await _sharedPreferences.setBool( diff --git a/lib/ionia/ionia_service.dart b/lib/ionia/ionia_service.dart index 51e23ad28..0396ed7c1 100644 --- a/lib/ionia/ionia_service.dart +++ b/lib/ionia/ionia_service.dart @@ -6,7 +6,6 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; -import 'package:platform_device_id/platform_device_id.dart'; class IoniaService { IoniaService(this.secureStorage, this.ioniaApi); @@ -112,9 +111,9 @@ class IoniaService { required String currency}) async { final username = (await secureStorage.read(key: ioniaUsernameStorageKey))!; final password = (await secureStorage.read(key: ioniaPasswordStorageKey))!; - final deviceId = await PlatformDeviceId.getDeviceId; + final deviceId = ''; return ioniaApi.purchaseGiftCard( - requestedUUID: deviceId!, + requestedUUID: deviceId, merchId: merchId, amount: amount, currency: currency, diff --git a/lib/reactions/on_wallet_sync_status_change.dart b/lib/reactions/on_wallet_sync_status_change.dart index 767bfd7e8..9a13db597 100644 --- a/lib/reactions/on_wallet_sync_status_change.dart +++ b/lib/reactions/on_wallet_sync_status_change.dart @@ -7,7 +7,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/sync_status.dart'; -import 'package:wakelock/wakelock.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; ReactionDisposer? _onWalletSyncStatusChangeReaction; @@ -27,10 +27,10 @@ void startWalletSyncStatusChangeReaction( } } if (status is SyncingSyncStatus) { - await Wakelock.enable(); + await WakelockPlus.enable(); } if (status is SyncedSyncStatus || status is FailedSyncStatus) { - await Wakelock.disable(); + await WakelockPlus.disable(); } } catch(e) { print(e.toString()); diff --git a/lib/src/screens/backup/backup_page.dart b/lib/src/screens/backup/backup_page.dart index 5995e71c4..d17702724 100644 --- a/lib/src/screens/backup/backup_page.dart +++ b/lib/src/screens/backup/backup_page.dart @@ -17,7 +17,6 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:permission_handler/permission_handler.dart'; class BackupPage extends BasePage { BackupPage(this.backupViewModelBase); @@ -129,15 +128,8 @@ class BackupPage extends BasePage { alertTitle: S.of(context).export_backup, alertContent: S.of(context).select_destination, rightButtonText: S.of(context).save_to_downloads, - leftButtonText:S.of(context).share, + leftButtonText: S.of(context).share, actionRightButton: () async { - final permission = await Permission.storage.request(); - - if (permission.isDenied) { - Navigator.of(dialogContext).pop(); - return; - } - await backupViewModelBase.saveToDownload(backup.name, backup.content); Navigator.of(dialogContext).pop(); }, diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 45edfc921..930878544 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -34,16 +34,6 @@ class BuyOptionsPage extends BasePage { constraints: BoxConstraints(maxWidth: 330), child: Column( children: [ - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconRobinhood, - title: "Robinhood Connect", - description: S.of(context).robinhood_option_description, - onPressed: () async => - await getIt.get().launchProvider(context), - ), - ), Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( @@ -54,6 +44,16 @@ class BuyOptionsPage extends BasePage { await getIt.get().launchProvider(context), ), ), + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconRobinhood, + title: "Robinhood Connect", + description: S.of(context).robinhood_option_description, + onPressed: () async => + await getIt.get().launchProvider(context), + ), + ), Spacer(), Padding( padding: EdgeInsets.fromLTRB(24, 24, 24, 32), diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index 6b3d3e08b..38055854b 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -15,7 +15,7 @@ class MoneroAccountListPage extends StatelessWidget { @override Widget build(BuildContext context) { - double itemHeight = 80; + double itemHeight = 65; double buttonHeight = 62; return Observer(builder: (_) { @@ -31,7 +31,7 @@ class MoneroAccountListPage extends StatelessWidget { child: ListView.separated( padding: EdgeInsets.zero, controller: controller, - separatorBuilder: (context, index) => const VerticalSectionDivider(), + separatorBuilder: (context, index) => const HorizontalSectionDivider(), itemCount: accounts.length, itemBuilder: (context, index) { final account = accounts[index]; diff --git a/lib/src/screens/monero_accounts/widgets/account_tile.dart b/lib/src/screens/monero_accounts/widgets/account_tile.dart index 3e428f355..97d328214 100644 --- a/lib/src/screens/monero_accounts/widgets/account_tile.dart +++ b/lib/src/screens/monero_accounts/widgets/account_tile.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; -import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -33,7 +32,7 @@ class AccountTile extends StatelessWidget { final Widget cell = GestureDetector( onTap: onTap, child: Container( - height: 77, + height: 60, width: double.infinity, padding: EdgeInsets.only(left: 24, right: 24), color: color, diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index ff9d59719..50c1c3be5 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -78,7 +78,7 @@ class NodeCreateOrEditPage extends BasePage { 'assets/images/qr_code_icon.png', ), ); - + final NodeCreateOrEditViewModel nodeCreateOrEditViewModel; final Node? editingNode; final bool? isSelected; @@ -133,27 +133,20 @@ class NodeCreateOrEditPage extends BasePage { mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible( - child: Container( - padding: EdgeInsets.only(right: 8.0), - child: LoadingPrimaryButton( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( onPressed: () async { final confirmed = await showPopUp( context: context, builder: (BuildContext context) { return AlertWithTwoActions( - alertTitle: - S.of(context).remove_node, - alertContent: S - .of(context) - .remove_node_message, - rightButtonText: - S.of(context).remove, - leftButtonText: - S.of(context).cancel, - actionRightButton: () => - Navigator.pop(context, true), - actionLeftButton: () => - Navigator.pop(context, false)); + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).remove, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); }) ?? false; @@ -163,11 +156,14 @@ class NodeCreateOrEditPage extends BasePage { } }, text: S.of(context).delete, - isDisabled: !nodeCreateOrEditViewModel.isReady || + isDisabled: editingNode == null || + !nodeCreateOrEditViewModel.isReady || (isSelected ?? false), color: Palette.red, - textColor: Colors.white), - )), + textColor: Colors.white, + ), + ), + ), Flexible( child: Container( padding: EdgeInsets.only(left: 8.0), diff --git a/lib/src/screens/restore/restore_from_backup_page.dart b/lib/src/screens/restore/restore_from_backup_page.dart index c3440fb06..f7fddac3f 100644 --- a/lib/src/screens/restore/restore_from_backup_page.dart +++ b/lib/src/screens/restore/restore_from_backup_page.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/view_model/restore_from_backup_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -31,10 +30,11 @@ class RestoreFromBackupPage extends BasePage { context: context, builder: (BuildContext context) { return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: state.error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); + alertTitle: S.of(context).error, + alertContent: state.error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); }); }); } @@ -44,42 +44,97 @@ class RestoreFromBackupPage extends BasePage { child: ConstrainedBox( constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Padding( - padding: EdgeInsets.only(bottom: 24, left: 24, right: 24), - child: Column(children: [ + padding: EdgeInsets.only(bottom: 24, left: 24, right: 24), + child: Column( + children: [ Expanded( child: Container( child: Center( - child: TextFormField( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( obscureText: true, enableSuggestions: false, autocorrect: false, - decoration: InputDecoration( - hintText: S.of(context).enter_backup_password), + decoration: + InputDecoration(hintText: S.of(context).enter_backup_password), keyboardType: TextInputType.visiblePassword, controller: textEditingController, - style: TextStyle(fontSize: 26, color: Colors.black))), + style: TextStyle(fontSize: 26, color: Colors.black), + ), + Observer( + builder: (_) { + if (restoreFromBackupViewModel.filePath.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 100), + Row( + children: [ + Text( + "File Name: ", + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: titleColor(context), + ), + ), + Expanded( + child: Text( + restoreFromBackupViewModel.filePath.split("/").last, + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: titleColor(context), + ), + ), + ), + ], + ), + ], + ); + } + + return const SizedBox(); + }, + ), + ], + ), + ), ), ), Container( - child: Row(children: [ - Expanded( - child: PrimaryButton( + child: Row( + children: [ + Expanded( + child: PrimaryButton( onPressed: () => presentFilePicker(), text: S.of(context).select_backup_file, color: Colors.grey, - textColor: Colors.white)), - SizedBox(width: 20), - Expanded(child: Observer(builder: (_) { - return LoadingPrimaryButton( - isLoading: - restoreFromBackupViewModel.state is IsExecutingState, - onPressed: () => onImportHandler(context), - text: S.of(context).import, - color: Theme.of(context).primaryColor, - textColor: Colors.white); - })) - ])), - ])), + textColor: Colors.white, + ), + ), + SizedBox(width: 20), + Expanded( + child: Observer( + builder: (_) { + return LoadingPrimaryButton( + isLoading: restoreFromBackupViewModel.state is IsExecutingState, + onPressed: () => onImportHandler(context), + text: S.of(context).import, + color: Theme.of(context).primaryColor, + textColor: Colors.white); + }, + ), + ), + ], + ), + ), + ], + ), + ), ), ); } @@ -87,7 +142,7 @@ class RestoreFromBackupPage extends BasePage { Future presentFilePicker() async { final result = await FilePicker.platform.pickFiles(); - if (result?.files?.isEmpty ?? true) { + if (result?.files.isEmpty ?? true) { return; } @@ -95,8 +150,7 @@ class RestoreFromBackupPage extends BasePage { } Future onImportHandler(BuildContext context) async { - if (textEditingController.text.isEmpty || - (restoreFromBackupViewModel.filePath.isEmpty ?? true)) { + if (textEditingController.text.isEmpty || (restoreFromBackupViewModel.filePath.isEmpty)) { await showPopUp( context: context, builder: (_) { diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index e54c0da29..91ee9bd0b 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -21,7 +21,6 @@ class RestoreOptionsPage extends BasePage { @override String get title => S.current.restore_restore_wallet; - final bool isNewInstall; final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png'); final imageBackup = Image.asset('assets/images/backup.png'); @@ -38,8 +37,7 @@ class RestoreOptionsPage extends BasePage { child: Column( children: [ OptionTile( - onPressed: () => Navigator.pushNamed( - context, Routes.restoreWalletFromSeedKeys, + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys, arguments: isNewInstall), image: imageSeedKeys, title: S.of(context).restore_title_from_seed_keys, @@ -58,7 +56,7 @@ class RestoreOptionsPage extends BasePage { child: OptionTile( onPressed: () async { bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; bool isPinSet = false; if (isNewInstall) { @@ -73,7 +71,8 @@ class RestoreOptionsPage extends BasePage { final restoreWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context); - final restoreFromQRViewModel = getIt.get(param1: restoreWallet.type); + final restoreFromQRViewModel = + getIt.get(param1: restoreWallet.type); await restoreFromQRViewModel.create(restoreWallet: restoreWallet); if (restoreFromQRViewModel.state is FailureState) { diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 757ee1862..02a1f6ad0 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/themes/extensions/alert_theme.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/palette.dart'; class BaseAlertDialog extends StatelessWidget { String get titleText => ''; @@ -49,7 +48,7 @@ class BaseAlertDialog extends StatelessWidget { Widget actionButtons(BuildContext context) { return Container( - height: 52, + height: 60, child: Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/src/widgets/option_tile.dart b/lib/src/widgets/option_tile.dart index 6a2825003..8b46641fb 100644 --- a/lib/src/widgets/option_tile.dart +++ b/lib/src/widgets/option_tile.dart @@ -52,7 +52,7 @@ class OptionTile extends StatelessWidget { child: Text( description, style: TextStyle( - fontSize: 16, + fontSize: 14, fontWeight: FontWeight.normal, color: Theme.of(context).extension()!.descriptionColor, ), diff --git a/lib/utils/permission_handler.dart b/lib/utils/permission_handler.dart index 6b76f767a..6a6126df2 100644 --- a/lib/utils/permission_handler.dart +++ b/lib/utils/permission_handler.dart @@ -17,7 +17,9 @@ class PermissionHandler { var status = await permission.status; if (status.isDenied) { - status = await permission.request(); + try { + status = await permission.request(); + } catch (_) {} } if (status.isPermanentlyDenied || status.isDenied) { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index c55241797..68d03b5f8 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -12,13 +12,12 @@ import devicelocale import flutter_secure_storage_macos import in_app_review import package_info +import package_info_plus import path_provider_foundation -import platform_device_id -import platform_device_id_macos import share_plus_macos import shared_preferences_foundation import url_launcher_macos -import wakelock_macos +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) @@ -28,11 +27,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) - WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 573f8c671..f43d65400 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -60,16 +60,21 @@ dependencies: another_flushbar: ^1.12.29 archive: ^3.3.0 cryptography: ^2.0.5 - file_picker: ^5.2.5 + file_picker: + git: + url: https://github.com/cake-tech/flutter_file_picker.git + ref: master unorm_dart: ^0.2.0 # check unorm_dart for usage and for replace permission_handler: ^10.0.0 - device_display_brightness: ^0.0.6 + device_display_brightness: + git: + url: https://github.com/cake-tech/device_display_brightness.git + ref: master workmanager: ^0.5.1 - platform_device_id: ^1.0.1 - wakelock: ^0.6.2 + wakelock_plus: ^1.1.3 flutter_mailer: ^2.0.2 - device_info_plus: 8.1.0 + device_info_plus: ^9.1.0 base32: 2.1.3 in_app_review: ^2.0.6 cake_backup: diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index cae478d7d..9f8a269d4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -722,8 +722,8 @@ "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé de graines", - "enter_seed_phrase": "Entrez votre phrase de semence", + "seed_key": "Clé secrète (seed key)", + "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "change_rep_successful": "Représentant changé avec succès", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", From 2c63867378af265be2f15675756ffedffbfef5f9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 18 Nov 2023 03:15:43 +0200 Subject: [PATCH 13/17] Update app version and release notes --- assets/text/Monerocom_Release_Notes.txt | 6 +- assets/text/Release_Notes.txt | 7 +- .../.plugin_symlinks/path_provider_linux | 2 +- ios/Podfile.lock | 32 ++-- lib/src/screens/settings/privacy_page.dart | 138 +++++++++--------- macos/Podfile.lock | 28 ++-- scripts/android/app_env.sh | 8 +- scripts/ios/app_env.sh | 8 +- scripts/macos/app_env.sh | 4 +- 9 files changed, 113 insertions(+), 120 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 9c09278a5..0f3f1f275 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,6 @@ -UI enhancements +Coin control fixes and enhancements +Accessibility enhancements Privacy settings enhancements -Tablet/iPad fixes +UI enhancements +Backup flow fixes Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 8b8ab36a1..0f3f1f275 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1,6 @@ -WalletConnect enhancements -UI enhancements +Coin control fixes and enhancements +Accessibility enhancements Privacy settings enhancements -Tablet/iPad fixes +UI enhancements +Backup flow fixes Bug fixes \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 0ed52b295..17553f81e 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file +/Users/omarhatem/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 970ee3f80..1db5b98f7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -63,8 +63,6 @@ PODS: - Flutter - device_display_brightness (0.0.1): - Flutter - - device_info (0.0.1): - - Flutter - device_info_plus (0.0.1): - Flutter - devicelocale (0.0.1): @@ -126,13 +124,13 @@ PODS: - OrderedSet (5.0.0) - package_info (0.0.1): - Flutter + - package_info_plus (0.4.5): + - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - permission_handler_apple (9.1.1): - Flutter - - platform_device_id (0.0.1): - - Flutter - ReachabilitySwift (5.0.0) - SDWebImage (5.16.0): - SDWebImage/Core (= 5.16.0) @@ -154,7 +152,7 @@ PODS: - CryptoSwift - url_launcher_ios (0.0.1): - Flutter - - wakelock (0.0.1): + - wakelock_plus (0.0.1): - Flutter - workmanager (0.0.1): - Flutter @@ -167,7 +165,6 @@ DEPENDENCIES: - cw_monero (from `.symlinks/plugins/cw_monero/ios`) - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - - device_info (from `.symlinks/plugins/device_info/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) @@ -179,16 +176,16 @@ DEPENDENCIES: - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - platform_device_id (from `.symlinks/plugins/platform_device_id/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - wakelock (from `.symlinks/plugins/wakelock/ios`) + - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) - workmanager (from `.symlinks/plugins/workmanager/ios`) SPEC REPOS: @@ -219,8 +216,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/cw_shared_external/ios" device_display_brightness: :path: ".symlinks/plugins/device_display_brightness/ios" - device_info: - :path: ".symlinks/plugins/device_info/ios" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" devicelocale: @@ -243,12 +238,12 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/local_auth_ios/ios" package_info: :path: ".symlinks/plugins/package_info/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" - platform_device_id: - :path: ".symlinks/plugins/platform_device_id/ios" sensitive_clipboard: :path: ".symlinks/plugins/sensitive_clipboard/ios" share_plus: @@ -259,8 +254,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" - wakelock: - :path: ".symlinks/plugins/wakelock/ios" + wakelock_plus: + :path: ".symlinks/plugins/wakelock_plus/ios" workmanager: :path: ".symlinks/plugins/workmanager/ios" @@ -273,12 +268,11 @@ SPEC CHECKSUMS: cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 - device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 - device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed + device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 devicelocale: b22617f40038496deffba44747101255cee005b0 DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 - file_picker: ce3938a0df3cc1ef404671531facef740d03f920 + file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 @@ -289,9 +283,9 @@ SPEC CHECKSUMS: MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 + package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 @@ -303,7 +297,7 @@ SPEC CHECKSUMS: uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 - wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f + wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100 diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 7a8671224..b1927648a 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -22,81 +22,83 @@ class PrivacyPage extends BasePage { @override Widget body(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Observer(builder: (_) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SettingsChoicesCell( - ChoicesListItem( - title: S.current.fiat_api, - items: FiatApiMode.all, - selectedItem: _privacySettingsViewModel.fiatApiMode, - onItemSelected: (FiatApiMode fiatApiMode) => - _privacySettingsViewModel.setFiatMode(fiatApiMode), + return SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10), + child: Observer(builder: (_) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsChoicesCell( + ChoicesListItem( + title: S.current.fiat_api, + items: FiatApiMode.all, + selectedItem: _privacySettingsViewModel.fiatApiMode, + onItemSelected: (FiatApiMode fiatApiMode) => + _privacySettingsViewModel.setFiatMode(fiatApiMode), + ), ), - ), - SettingsChoicesCell( - ChoicesListItem( - title: S.current.exchange, - items: ExchangeApiMode.all, - selectedItem: _privacySettingsViewModel.exchangeStatus, - onItemSelected: (ExchangeApiMode mode) => - _privacySettingsViewModel.setExchangeApiMode(mode), + SettingsChoicesCell( + ChoicesListItem( + title: S.current.exchange, + items: ExchangeApiMode.all, + selectedItem: _privacySettingsViewModel.exchangeStatus, + onItemSelected: (ExchangeApiMode mode) => + _privacySettingsViewModel.setExchangeApiMode(mode), + ), ), - ), - SettingsSwitcherCell( - title: S.current.settings_save_recipient_address, - value: _privacySettingsViewModel.shouldSaveRecipientAddress, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setShouldSaveRecipientAddress(value); - }), - if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) SettingsSwitcherCell( - title: S.current.auto_generate_subaddresses, - value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setAutoGenerateSubaddresses(value); - }, - ), - if (DeviceInfo.instance.isMobile) - SettingsSwitcherCell( - title: S.current.prevent_screenshots, - value: _privacySettingsViewModel.isAppSecure, + title: S.current.settings_save_recipient_address, + value: _privacySettingsViewModel.shouldSaveRecipientAddress, onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setIsAppSecure(value); + _privacySettingsViewModel.setShouldSaveRecipientAddress(value); }), - SettingsSwitcherCell( - title: S.current.disable_buy, - value: _privacySettingsViewModel.disableBuy, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setDisableBuy(value); - }), - SettingsSwitcherCell( - title: S.current.disable_sell, - value: _privacySettingsViewModel.disableSell, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setDisableSell(value); - }), - if (_privacySettingsViewModel.canUseEtherscan) - SettingsSwitcherCell( - title: S.current.etherscan_history, - value: _privacySettingsViewModel.useEtherscan, + if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) + SettingsSwitcherCell( + title: S.current.auto_generate_subaddresses, + value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setUseEtherscan(value); + _privacySettingsViewModel.setAutoGenerateSubaddresses(value); + }, + ), + if (DeviceInfo.instance.isMobile) + SettingsSwitcherCell( + title: S.current.prevent_screenshots, + value: _privacySettingsViewModel.isAppSecure, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setIsAppSecure(value); + }), + SettingsSwitcherCell( + title: S.current.disable_buy, + value: _privacySettingsViewModel.disableBuy, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setDisableBuy(value); }), - SettingsCellWithArrow( - title: S.current.domain_looks_up, - handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), - ), - SettingsCellWithArrow( - title: 'Trocador providers', - handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), - ), - ], - ); - }), + SettingsSwitcherCell( + title: S.current.disable_sell, + value: _privacySettingsViewModel.disableSell, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setDisableSell(value); + }), + if (_privacySettingsViewModel.canUseEtherscan) + SettingsSwitcherCell( + title: S.current.etherscan_history, + value: _privacySettingsViewModel.useEtherscan, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setUseEtherscan(value); + }), + SettingsCellWithArrow( + title: S.current.domain_looks_up, + handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), + ), + SettingsCellWithArrow( + title: 'Trocador providers', + handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), + ), + ], + ); + }), + ), ); } } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 664a5231b..329732075 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -30,13 +30,11 @@ PODS: - FlutterMacOS - package_info (0.0.1): - FlutterMacOS + - package_info_plus (0.0.1): + - FlutterMacOS - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - platform_device_id (0.0.1): - - FlutterMacOS - - platform_device_id_macos (0.0.1): - - FlutterMacOS - ReachabilitySwift (5.0.0) - share_plus_macos (0.0.1): - FlutterMacOS @@ -45,7 +43,7 @@ PODS: - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - - wakelock_macos (0.0.1): + - wakelock_plus (0.0.1): - FlutterMacOS DEPENDENCIES: @@ -57,13 +55,12 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - - platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`) - - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) + - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) SPEC REPOS: trunk: @@ -86,20 +83,18 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos package_info: :path: Flutter/ephemeral/.symlinks/plugins/package_info/macos + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin - platform_device_id: - :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos - platform_device_id_macos: - :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos share_plus_macos: :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos - wakelock_macos: - :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos + wakelock_plus: + :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 @@ -110,14 +105,13 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763 - platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 - wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 + wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ba7575d3a..9d69d46ee 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.3" -MONERO_COM_BUILD_NUMBER=64 +MONERO_COM_VERSION="1.7.5" +MONERO_COM_BUILD_NUMBER=65 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.3" -CAKEWALLET_BUILD_NUMBER=178 +CAKEWALLET_VERSION="4.10.5" +CAKEWALLET_BUILD_NUMBER=179 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 328b3825b..23406e049 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.4" -MONERO_COM_BUILD_NUMBER=63 +MONERO_COM_VERSION="1.7.5" +MONERO_COM_BUILD_NUMBER=64 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.4" -CAKEWALLET_BUILD_NUMBER=196 +CAKEWALLET_VERSION="4.10.5" +CAKEWALLET_BUILD_NUMBER=198 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 57434db8e..8f8d549ea 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.3" -CAKEWALLET_BUILD_NUMBER=40 +CAKEWALLET_VERSION="1.3.5" +CAKEWALLET_BUILD_NUMBER=41 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From af7c512d1d9143780a7e212f511b1a2dfc8561e6 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 18 Nov 2023 04:07:48 +0200 Subject: [PATCH 14/17] Update Linux version Fix conflicts with main --- cw_bitcoin/lib/electrum_wallet.dart | 1 - linux/flutter/generated_plugin_registrant.cc | 8 ++++---- linux/flutter/generated_plugins.cmake | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 +++- scripts/linux/app_env.sh | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 7929e80c1..1719e9acd 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -19,7 +19,6 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 77cfc4257..54b70c724 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,7 +8,7 @@ #include #include -#include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -18,9 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) devicelocale_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DevicelocalePlugin"); devicelocale_plugin_register_with_registrar(devicelocale_registrar); - g_autoptr(FlPluginRegistrar) platform_device_id_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "PlatformDeviceIdLinuxPlugin"); - platform_device_id_linux_plugin_register_with_registrar(platform_device_id_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index e432c44eb..c7dfb4d7a 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,7 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST cw_monero devicelocale - platform_device_id_linux + flutter_secure_storage_linux url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index f8f725b27..1d6aff06d 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import connectivity_plus_macos import cw_monero import device_info_plus import devicelocale +import flutter_secure_storage_macos import in_app_review import package_info_plus import path_provider_foundation @@ -22,8 +23,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) - FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh index d1a4fe720..79d83d2dc 100755 --- a/scripts/linux/app_env.sh +++ b/scripts/linux/app_env.sh @@ -14,8 +14,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.1.4" -CAKEWALLET_BUILD_NUMBER=7 +CAKEWALLET_VERSION="1.1.5" +CAKEWALLET_BUILD_NUMBER=8 if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then echo "Wrong app type." From ab83f5b67fe085c993abb7738e7d692364ebb5e7 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 18 Nov 2023 15:43:15 +0200 Subject: [PATCH 15/17] Cw 519 tor connection (#1158) * initial draft for tor feature * Configure nodes to use Tor proxy if enabled * Add socks proxy upon connecting to tor fix disconnect button * Try tor with github actions * accept defaults for rust installation * Merge main Change Tor tile name --- .github/workflows/pr_test_build.yml | 2 + cw_bitcoin/pubspec.lock | 43 ++- .../.plugin_symlinks/path_provider_linux | 2 +- .../linux/flutter/generated_plugins.cmake | 1 + cw_core/lib/node.dart | 23 +- cw_core/pubspec.lock | 43 ++- cw_core/pubspec.yaml | 5 + cw_haven/pubspec.lock | 43 ++- cw_monero/example/pubspec.lock | 43 ++- cw_monero/pubspec.lock | 43 ++- cw_nano/pubspec.lock | 41 ++- ios/Podfile.lock | 6 + lib/di.dart | 2 + lib/router.dart | 4 + lib/routes.dart | 1 + .../settings/connection_sync_page.dart | 7 +- lib/src/screens/settings/tor_page.dart | 267 ++++++++++++++++++ pubspec_base.yaml | 7 +- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 44 files changed, 548 insertions(+), 113 deletions(-) create mode 100644 lib/src/screens/settings/tor_page.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 3c6b132bd..d74b85ce4 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -38,6 +38,8 @@ jobs: sudo mkdir -p /opt/android sudo chown $USER /opt/android cd /opt/android + -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + cargo install cargo-ndk git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF cd cake_wallet/scripts/android/ ./install_ndk.sh diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index eb75227b6..43391881f 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -481,50 +481,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.1" platform: dependency: transitive description: @@ -610,6 +610,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -690,6 +698,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -756,4 +773,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 0ed52b295..17553f81e 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file +/Users/omarhatem/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake index 2e1de87a7..3d57782b2 100644 --- a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake +++ b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 5f0951447..3f6056ae1 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -6,6 +6,7 @@ import 'package:hive/hive.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; +import 'package:tor/tor.dart'; part 'node.g.dart'; @@ -129,9 +130,7 @@ class Node extends HiveObject with Keyable { try { switch (type) { case WalletType.monero: - return useSocksProxy - ? requestNodeWithProxy(socksProxyAddress ?? '') - : requestMoneroNode(); + return requestMoneroNode(); case WalletType.bitcoin: return requestElectrumServer(); case WalletType.litecoin: @@ -154,6 +153,9 @@ class Node extends HiveObject with Keyable { } Future requestMoneroNode() async { + if (uri.toString().contains(".onion") || useSocksProxy) { + return await requestNodeWithProxy(); + } final path = '/json_rpc'; final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); final realm = 'monero-rpc'; @@ -205,11 +207,20 @@ class Node extends HiveObject with Keyable { } } - Future requestNodeWithProxy(String proxy) async { - if (proxy.isEmpty || !proxy.contains(':')) { + Future requestNodeWithProxy() async { + if ((socksProxyAddress == null || + socksProxyAddress!.isEmpty || + !socksProxyAddress!.contains(':')) && + !Tor.instance.enabled) { return false; } - final proxyAddress = proxy.split(':')[0]; + + String? proxy = socksProxyAddress; + + if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) { + proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + } + final proxyAddress = proxy!.split(':')[0]; final proxyPort = int.parse(proxy.split(':')[1]); try { final socket = await Socket.connect(proxyAddress, proxyPort, timeout: Duration(seconds: 5)); diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index e399526fd..058f33ba4 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -407,50 +407,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.1" platform: dependency: transitive description: @@ -528,6 +528,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: "direct main" + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -608,6 +616,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -666,4 +683,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 9dcb7eaba..3763a7318 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -19,6 +19,11 @@ dependencies: flutter_mobx: ^2.0.6+1 intl: ^0.18.0 encrypt: ^5.0.1 + socks5_proxy: ^1.0.4 + tor: + git: + url: https://github.com/cake-tech/tor.git + ref: main dev_dependencies: flutter_test: diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index a63aa3237..525e8e5fa 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -414,50 +414,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -535,6 +535,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -615,6 +623,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -673,4 +690,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 1aae6b0c9..661341e96 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -237,50 +237,50 @@ packages: dependency: transitive description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -318,6 +318,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_span: dependency: transitive description: @@ -366,6 +374,15 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -400,4 +417,4 @@ packages: version: "0.2.0+3" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 37e08e7ca..dc0f9aeed 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -414,50 +414,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -535,6 +535,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -615,6 +623,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -673,4 +690,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index d28558422..4a5496fa6 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -491,50 +491,50 @@ packages: dependency: transitive description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" pinenacl: dependency: transitive description: @@ -676,6 +676,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -756,6 +764,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 970ee3f80..cc60cad08 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -147,6 +147,8 @@ PODS: - SwiftProtobuf (1.22.0) - SwiftyGif (5.4.4) - Toast (4.0.0) + - tor (0.0.1): + - Flutter - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -185,6 +187,7 @@ DEPENDENCIES: - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - tor (from `.symlinks/plugins/tor/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -255,6 +258,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + tor: + :path: ".symlinks/plugins/tor/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -300,6 +305,7 @@ SPEC CHECKSUMS: SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 diff --git a/lib/di.dart b/lib/di.dart index 94f5dbb63..d6a43030a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -46,6 +46,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page. import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; +import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -1175,6 +1176,7 @@ Future setup({ getIt.registerFactory( () => WalletConnectConnectionsView(web3walletService: getIt.get())); + getIt.registerFactory(() => TorPage(getIt.get())); _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index 8174e0be8..75f491dfc 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -43,6 +43,7 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; +import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -615,6 +616,9 @@ Route createRoute(RouteSettings settings) { web3walletService: getIt.get(), launchUri: settings.arguments as Uri?, )); + case Routes.torPage: + return MaterialPageRoute(builder: (_) => getIt.get()); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index 8b521247a..4c1a917ab 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -101,4 +101,5 @@ class Routes { static const manageNodes = '/manage_nodes'; static const managePowNodes = '/manage_pow_nodes'; static const walletConnectConnectionsListing = '/wallet-connect-connections-listing'; + static const torPage = '/tor_page'; } diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index e4763653b..7d1289e78 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -3,7 +3,6 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro 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/screens/settings/widgets/wallet_connect_button.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; @@ -90,7 +89,11 @@ class ConnectionSyncPage extends BasePage { onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), - ] + ], + SettingsCellWithArrow( + title: S.current.tor_connection, + handler: (context) => Navigator.of(context).pushNamed(Routes.torPage), + ), ], ), ); diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart new file mode 100644 index 000000000..d1d5c7e83 --- /dev/null +++ b/lib/src/screens/settings/tor_page.dart @@ -0,0 +1,267 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:flutter/material.dart'; +import 'package:tor/tor.dart'; + +class TorPage extends BasePage { + final AppStore appStore; + + TorPage(this.appStore); + + @override + Widget body(BuildContext context) { + return TorPageBody(appStore); + } +} + +class TorPageBody extends StatefulWidget { + final AppStore appStore; + + const TorPageBody(this.appStore, {Key? key}) : super(key: key); + + @override + State createState() => _TorPageBodyState(); +} + +class _TorPageBodyState extends State { + bool torEnabled = false; + bool connecting = false; + + // Set the default text for the host input field. + final hostController = TextEditingController(text: 'https://icanhazip.com/'); + + // https://check.torproject.org is another good option. + + Future startTor() async { + setState(() { + connecting = true; // Update flag + }); + + await Tor.init(); + + // Start the proxy + await Tor.instance.start(); + + // Toggle started flag. + setState(() { + torEnabled = Tor.instance.enabled; // Update flag + connecting = false; + }); + + final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type); + if (node.socksProxyAddress?.isEmpty ?? true) { + node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + } + widget.appStore.wallet!.connectToNode(node: node); + + print('Done awaiting; tor should be running'); + } + + Future endTor() async { + // Start the proxy + Tor.instance.disable(); + + // Toggle started flag. + setState(() { + torEnabled = Tor.instance.enabled; // Update flag + }); + + print('Done awaiting; tor should be stopped'); + } + + @override + void initState() { + super.initState(); + + torEnabled = Tor.instance.enabled; + } + + @override + void dispose() { + // Clean up the controller when the widget is disposed. + hostController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(10), + child: connecting + ? ConnectingScreen() + : torEnabled + ? DisconnectScreen(disconnect: endTor) + : ConnectScreen(connect: startTor), + ), + ); + } +} + +class ConnectScreen extends StatelessWidget { + final Function() connect; + + const ConnectScreen({super.key, required this.connect}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + child: Icon( + Icons.lock, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connect to Tor', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + Text( + 'Your connection to the Tor network ensures privacy and security.', + style: TextStyle( + fontSize: 16, + color: Colors.grey, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 30), + ElevatedButton( + onPressed: connect, + style: ElevatedButton.styleFrom( + primary: Colors.blue, + padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + ), + child: Text( + 'Connect', + style: TextStyle( + fontSize: 18, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } +} + +class DisconnectScreen extends StatelessWidget { + final Function() disconnect; + + const DisconnectScreen({super.key, required this.disconnect}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.green, + ), + child: Icon( + Icons.check, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connected to Tor', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + Text( + 'You are currently connected to the Tor network.', + style: TextStyle( + fontSize: 16, + color: Colors.grey, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 30), + ElevatedButton( + onPressed: disconnect, + style: ElevatedButton.styleFrom( + primary: Colors.red, + padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + ), + child: Text( + 'Disconnect', + style: TextStyle( + fontSize: 18, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } +} + +class ConnectingScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.yellow, + ), + child: Icon( + Icons.hourglass_bottom, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connecting...', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + ], + ), + ); + } +} diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f43d65400..c6101d28c 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -83,7 +83,7 @@ dependencies: ref: main version: 1.0.0 flutter_plugin_android_lifecycle: 2.0.9 - path_provider_android: 2.0.24 + path_provider_android: ^2.2.1 shared_preferences_android: 2.0.17 url_launcher_android: 6.0.24 sensitive_clipboard: ^1.0.0 @@ -98,6 +98,11 @@ dependencies: url: https://github.com/cake-tech/bitcoin_flutter.git ref: cake-update-v3 fluttertoast: 8.1.4 + tor: + git: + url: https://github.com/cake-tech/tor.git + ref: main + socks5_proxy: ^1.0.4 dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a5298c343..84a0a72f5 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -730,5 +730,6 @@ "seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", - "unspent_change": "يتغير" + "unspent_change": "يتغير", + "tor_connection": " ﺭﻮﺗ ﻝﺎﺼﺗﺍ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 3b085cd59..b1851156c 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -726,5 +726,6 @@ "seed_phrase_length": "Дължина на началната фраза", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", - "unspent_change": "Промяна" + "unspent_change": "Промяна", + "tor_connection": "Tor връзка" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index f6d024957..2e59f5fc5 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -726,5 +726,6 @@ "seed_phrase_length": "Délka fráze semene", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", - "unspent_change": "Změna" + "unspent_change": "Změna", + "tor_connection": "Připojení Tor" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 6519f0ef6..7868553be 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Länge der Seed-Phrase", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", - "unspent_change": "Wechselgeld" + "unspent_change": "Wechselgeld", + "tor_connection": "Tor-Verbindung" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 2c1d00eb6..c3cd256d9 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -735,5 +735,6 @@ "seed_phrase_length": "Seed phrase length", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", - "unspent_change": "Change" + "unspent_change": "Change", + "tor_connection": "Tor connection" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3629a6d37..4e624a9b4 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Longitud de la frase inicial", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", - "unspent_change": "Cambiar" + "unspent_change": "Cambiar", + "tor_connection": "conexión tor" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9f8a269d4..d4d414029 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -734,5 +734,6 @@ "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", - "unspent_change": "Changement" + "unspent_change": "Changement", + "tor_connection": "Connexion Tor" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 84c3b4b74..0e2589b6a 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -712,5 +712,6 @@ "seed_phrase_length": "Tsawon jimlar iri", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", - "unspent_change": "Canza" + "unspent_change": "Canza", + "tor_connection": "Tor haɗin gwiwa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index af3b888cb..19467af09 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "बीज वाक्यांश की लंबाई", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", - "unspent_change": "परिवर्तन" + "unspent_change": "परिवर्तन", + "tor_connection": "टोर कनेक्शन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3c56b8552..30eea10dc 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "Duljina početne fraze", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", - "unspent_change": "Promijeniti" + "unspent_change": "Promijeniti", + "tor_connection": "Tor veza" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b3d22780a..c10feffbc 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -722,5 +722,6 @@ "seed_phrase_length": "Panjang frase benih", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", - "unspent_change": "Mengubah" + "unspent_change": "Mengubah", + "tor_connection": "koneksi Tor" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8fc157f27..a13930666 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Lunghezza della frase seed", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", - "unspent_change": "Modifica" + "unspent_change": "Modifica", + "tor_connection": "Connessione Tor" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 06d8efd37..3e61dbd9d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "シードフレーズの長さ", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", - "unspent_change": "変化" + "unspent_change": "変化", + "tor_connection": "Tor接続" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6830b1183..de09c65d1 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "시드 문구 길이", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", - "unspent_change": "변화" + "unspent_change": "변화", + "tor_connection": "토르 연결" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index ff8f6683b..1853c0eff 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", - "unspent_change": "ပေြာင်းလဲခြင်း" + "unspent_change": "ပေြာင်းလဲခြင်း", + "tor_connection": "Tor ချိတ်ဆက်မှု" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 753e28cd5..a497c20ab 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Lengte van de zaadzin", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", - "unspent_change": "Wijziging" + "unspent_change": "Wijziging", + "tor_connection": "Tor-verbinding" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 1900ca590..dc69468bd 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Długość frazy początkowej", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", - "unspent_change": "Zmiana" + "unspent_change": "Zmiana", + "tor_connection": "Połączenie Torem" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 86c7a6b0d..c6d22ae23 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -733,5 +733,6 @@ "seed_phrase_length": "Comprimento da frase-semente", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", - "unspent_change": "Mudar" + "unspent_change": "Mudar", + "tor_connection": "Conexão Tor" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a37b0908b..50bef718d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Длина исходной фразы", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", - "unspent_change": "Изменять" + "unspent_change": "Изменять", + "tor_connection": "Тор соединение" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index fa36c04bb..95a1cd406 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "ความยาววลีของเมล็ด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", - "unspent_change": "เปลี่ยน" + "unspent_change": "เปลี่ยน", + "tor_connection": "การเชื่อมต่อทอร์" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index b8bf168ce..960432a1b 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -729,5 +729,6 @@ "seed_phrase_length": "Haba ng parirala ng binhi", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", - "unspent_change": "Baguhin" + "unspent_change": "Baguhin", + "tor_connection": "Koneksyon ng Tor" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f7962b526..1b7982504 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "Çekirdek cümle uzunluğu", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", - "unspent_change": "Değiştirmek" + "unspent_change": "Değiştirmek", + "tor_connection": "Tor bağlantısı" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 0e4cc3ecb..849542e6f 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Довжина початкової фрази", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", - "unspent_change": "Зміна" + "unspent_change": "Зміна", + "tor_connection": "Підключення Tor" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index cd05010d7..0b7e4c0a7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -726,5 +726,6 @@ "seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", - "unspent_change": "تبدیل کریں" + "unspent_change": "تبدیل کریں", + "tor_connection": " ﻦﺸﮑﻨﮐ ﺭﻮﭨ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index fc632f8a8..57962b38e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -728,5 +728,6 @@ "seed_phrase_length": "Gigun gbolohun irugbin", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", - "unspent_change": "Yipada" + "unspent_change": "Yipada", + "tor_connection": "Tor asopọ" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e57df96d9..0862f20e2 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -733,5 +733,6 @@ "seed_phrase_length": "种子短语长度", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", - "unspent_change": "改变" + "unspent_change": "改变", + "tor_connection": "Tor连接" } From c92e89b38e10719be865c8e6bbbd5edaf466dcc9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 18 Nov 2023 15:52:06 +0200 Subject: [PATCH 16/17] Add Tor to this release --- assets/text/Monerocom_Release_Notes.txt | 1 + assets/text/Release_Notes.txt | 1 + scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- scripts/macos/app_env.sh | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 0f3f1f275..caac086d1 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,5 @@ Coin control fixes and enhancements +In-app Tor connection Accessibility enhancements Privacy settings enhancements UI enhancements diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 0f3f1f275..caac086d1 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,4 +1,5 @@ Coin control fixes and enhancements +In-app Tor connection Accessibility enhancements Privacy settings enhancements UI enhancements diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 9d69d46ee..a373003a1 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -16,14 +16,14 @@ APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.7.5" -MONERO_COM_BUILD_NUMBER=65 +MONERO_COM_BUILD_NUMBER=66 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.10.5" -CAKEWALLET_BUILD_NUMBER=179 +CAKEWALLET_BUILD_NUMBER=180 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 23406e049..810b2b78c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -14,12 +14,12 @@ APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.7.5" -MONERO_COM_BUILD_NUMBER=64 +MONERO_COM_BUILD_NUMBER=65 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.10.5" -CAKEWALLET_BUILD_NUMBER=198 +CAKEWALLET_BUILD_NUMBER=199 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 8f8d549ea..665da3425 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,7 +16,7 @@ fi CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.3.5" -CAKEWALLET_BUILD_NUMBER=41 +CAKEWALLET_BUILD_NUMBER=42 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 5eab78343489f86ccec149742418b7cd74f5b7bb Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 18 Nov 2023 17:12:45 +0200 Subject: [PATCH 17/17] Add Tor to this release --- scripts/linux/app_env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh index 79d83d2dc..937ae010f 100755 --- a/scripts/linux/app_env.sh +++ b/scripts/linux/app_env.sh @@ -15,7 +15,7 @@ fi CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.1.5" -CAKEWALLET_BUILD_NUMBER=8 +CAKEWALLET_BUILD_NUMBER=9 if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then echo "Wrong app type."