From d4b317b3a0ee77245666651aad4638f9d2c3700c Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 8 Apr 2024 10:42:27 -0700 Subject: [PATCH 1/9] minor fix (#1371) --- lib/buy/moonpay/moonpay_provider.dart | 72 +++++++++++++-------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 52a4f6187..fea8fdabd 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -155,7 +155,7 @@ class MoonPayProvider extends BuyProvider { 'baseCurrencyAmount': amount ?? '0', 'currencyCode': currencyCode, 'walletAddress': walletAddress, - 'lockAmount': 'true', + 'lockAmount': 'false', 'showAllCurrencies': 'false', 'showWalletAddressForm': 'false', 'enabledPaymentMethods': @@ -256,44 +256,44 @@ class MoonPayProvider extends BuyProvider { @override Future launchProvider(BuildContext context, bool? isBuyAction) async { - // try { - late final Uri uri; - if (isBuyAction ?? true) { - uri = await requestBuyMoonPayUrl( - currency: wallet.currency, - walletAddress: wallet.walletAddresses.address, - settingsStore: _settingsStore, - ); - } else { - uri = await requestSellMoonPayUrl( - currency: wallet.currency, - refundWalletAddress: wallet.walletAddresses.address, - settingsStore: _settingsStore, - ); - } - - if (await canLaunchUrl(uri)) { - if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + try { + late final Uri uri; + if (isBuyAction ?? true) { + uri = await requestBuyMoonPayUrl( + currency: wallet.currency, + walletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); } else { - await launchUrl(uri, mode: LaunchMode.externalApplication); + uri = await requestSellMoonPayUrl( + currency: wallet.currency, + refundWalletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); } - } else { - throw Exception('Could not launch URL'); + + if (await canLaunchUrl(uri)) { + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + } else { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } else { + throw Exception('Could not launch URL'); + } + } catch (e) { + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: 'MoonPay', + alertContent: 'The MoonPay service is currently unavailable: $e', + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); } - // } catch (e) { - // await showDialog( - // context: context, - // builder: (BuildContext context) { - // return AlertWithOneAction( - // alertTitle: 'MoonPay', - // alertContent: 'The MoonPay service is currently unavailable: $e', - // buttonText: S.of(context).ok, - // buttonAction: () => Navigator.of(context).pop(), - // ); - // }, - // ); - // } } String _normalizeCurrency(CryptoCurrency currency) { From 2877cc160c707e0826aa6ae75a7eab36fffa8648 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:53:14 +0100 Subject: [PATCH 2/9] CW-608-Fetch-And-Save-Icons-Of-ERC20-And-SPL-Tokens-When-Adding-Them (#1365) * feat: Fetch and save icons of SPL tokens when adding them * feat: Implement fetch and save icons for ERC20 tokens when adding them * fix: Add moralisApiKey to evm secrets * Add check to ensure decimals cannot be zero * - Fallback to adding erc20 token from web3dart - Wrap fetching spl token icon in a try/catch block --------- Co-authored-by: OmarHatem --- .github/workflows/pr_test_build.yml | 1 + cw_evm/lib/evm_chain_client.dart | 51 ++++++++++++++++--- cw_evm/lib/evm_chain_wallet.dart | 19 ++++--- cw_solana/lib/solana_client.dart | 17 +++++++ cw_solana/lib/solana_wallet.dart | 6 +++ cw_solana/lib/spl_token.dart | 3 +- lib/ethereum/cw_ethereum.dart | 2 +- lib/polygon/cw_polygon.dart | 2 +- lib/solana/cw_solana.dart | 1 + .../screens/dashboard/edit_token_page.dart | 10 ++++ .../screens/dashboard/home_settings_page.dart | 38 +++++++------- .../screens/dashboard/pages/balance_page.dart | 42 +++++++-------- lib/src/widgets/cake_image_widget.dart | 2 +- .../dashboard/home_settings_view_model.dart | 2 + res/values/strings_ar.arb | 1 + 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 | 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 +- tool/utils/secret_key.dart | 1 + 41 files changed, 182 insertions(+), 69 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index ddc8869f0..db9870412 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -140,6 +140,7 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart + echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index cf73b13db..eebbe4f4f 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'package:cw_core/node.dart'; @@ -9,6 +10,7 @@ import 'package:cw_evm/evm_erc20_balance.dart'; import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/.secrets.g.dart' as secrets; import 'package:flutter/services.dart'; import 'package:http/http.dart'; @@ -211,26 +213,61 @@ abstract class EVMChainClient { return EVMChainERC20Balance(balance, exponent: exponent); } - Future getErc20Token(String contractAddress) async { + Future getErc20Token(String contractAddress, String chainName) async { try { - final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); - final name = await erc20.name(); - final symbol = await erc20.symbol(); - final decimal = await erc20.decimals(); + final uri = Uri.https( + 'deep-index.moralis.io', + '/api/v2.2/erc20/metadata', + { + "chain": chainName, + "addresses": contractAddress, + }, + ); + + final response = await httpClient.get( + uri, + headers: { + "Accept": "application/json", + "X-API-Key": secrets.moralisApiKey, + }, + ); + + final decodedResponse = jsonDecode(response.body)[0] as Map; + + final name = decodedResponse['name'] ?? ''; + final symbol = decodedResponse['symbol'] ?? ''; + final decimal = decodedResponse['decimals'] ?? '0'; + final iconPath = decodedResponse['logo'] ?? ''; return Erc20Token( name: name, symbol: symbol, contractAddress: contractAddress, - decimal: decimal.toInt(), + decimal: int.tryParse(decimal) ?? 0, + iconPath: iconPath, ); } catch (e) { + try { + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final name = await erc20.name(); + final symbol = await erc20.symbol(); + final decimal = await erc20.decimals(); + + return Erc20Token( + name: name, + symbol: symbol, + contractAddress: contractAddress, + decimal: decimal.toInt(), + ); + } catch (_) {} + return null; } } Uint8List hexToBytes(String hexString) { - return Uint8List.fromList(hex.HEX.decode(hexString.startsWith('0x') ? hexString.substring(2) : hexString)); + return Uint8List.fromList( + hex.HEX.decode(hexString.startsWith('0x') ? hexString.substring(2) : hexString)); } void stop() { diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index c90a3e809..4193e590a 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -439,11 +439,16 @@ abstract class EVMChainWalletBase Future addErc20Token(Erc20Token token) async { String? iconPath; - try { - iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - } catch (_) {} + + if (token.iconPath == null || token.iconPath!.isEmpty) { + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + } else { + iconPath = token.iconPath; + } final newToken = createNewErc20TokenObject(token, iconPath); @@ -466,8 +471,8 @@ abstract class EVMChainWalletBase _updateBalance(); } - Future getErc20Token(String contractAddress) async => - await _client.getErc20Token(contractAddress); + Future getErc20Token(String contractAddress, String chainName) async => + await _client.getErc20Token(contractAddress, chainName); void _onNewTransaction() { _updateBalance(); diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index 781fff5f7..6ed8cab29 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -533,4 +533,21 @@ class SolanaWalletClient { throw Exception(e); } } + + Future getIconImageFromTokenUri(String uri) async { + try { + final response = await httpClient.get(Uri.parse(uri)); + + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && response.statusCode < 300) { + return jsonResponse['image']; + } else { + return null; + } + } catch (e) { + print('Error occurred while fetching token image: \n${e.toString()}'); + return null; + } + } } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index f69a597ae..ad58c4293 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -464,11 +464,17 @@ abstract class SolanaWalletBase return null; } + String? iconPath; + try { + iconPath = await _client.getIconImageFromTokenUri(token.uri); + } catch (_) {} + return SPLToken.fromMetadata( name: token.name, mint: token.mint, symbol: token.symbol, mintAddress: mintAddress, + iconPath: iconPath, ); } catch (e) { return null; diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart index 0413990b1..0b3b8b372 100644 --- a/cw_solana/lib/spl_token.dart +++ b/cw_solana/lib/spl_token.dart @@ -55,6 +55,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { required String mint, required String symbol, required String mintAddress, + String? iconPath }) { return SPLToken( name: name, @@ -62,7 +63,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { mintAddress: mintAddress, decimal: 0, mint: mint, - iconPath: '', + iconPath: iconPath, ); } diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 52839d68a..13fe3aafd 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -131,7 +131,7 @@ class CWEthereum extends Ethereum { @override Future getErc20Token(WalletBase wallet, String contractAddress) async { final ethereumWallet = wallet as EthereumWallet; - return await ethereumWallet.getErc20Token(contractAddress); + return await ethereumWallet.getErc20Token(contractAddress, 'eth'); } @override diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 0ee7457eb..9f0f9a1bf 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -129,7 +129,7 @@ class CWPolygon extends Polygon { @override Future getErc20Token(WalletBase wallet, String contractAddress) async { final polygonWallet = wallet as PolygonWallet; - return await polygonWallet.getErc20Token(contractAddress); + return await polygonWallet.getErc20Token(contractAddress, 'polygon'); } @override diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index d6df78318..6f4b17309 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -86,6 +86,7 @@ class CWSolana extends Solana { decimal: token.decimals, mint: token.name.toUpperCase(), enabled: token.enabled, + iconPath: token.iconPath, ); await (wallet as SolanaWallet).addSPLToken(splToken); diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 1a1db8658..59f7de9e5 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -59,6 +59,7 @@ class _EditTokenPageBodyState extends State { final TextEditingController _tokenNameController = TextEditingController(); final TextEditingController _tokenSymbolController = TextEditingController(); final TextEditingController _tokenDecimalController = TextEditingController(); + final TextEditingController _tokenIconPathController = TextEditingController(); final FocusNode _contractAddressFocusNode = FocusNode(); final FocusNode _tokenNameFocusNode = FocusNode(); @@ -83,6 +84,7 @@ class _EditTokenPageBodyState extends State { _tokenNameController.text = widget.token!.name; _tokenSymbolController.text = widget.token!.title; _tokenDecimalController.text = widget.token!.decimals.toString(); + _tokenIconPathController.text = widget.token?.iconPath ?? ''; } if (widget.initialContractAddress != null) { @@ -200,6 +202,7 @@ class _EditTokenPageBodyState extends State { name: _tokenNameController.text, title: _tokenSymbolController.text.toUpperCase(), decimals: int.parse(_tokenDecimalController.text), + iconPath: _tokenIconPathController.text, ), contractAddress: _contractAddressController.text, ); @@ -228,6 +231,8 @@ class _EditTokenPageBodyState extends State { if (token != null) { if (_tokenNameController.text.isEmpty) _tokenNameController.text = token.name; if (_tokenSymbolController.text.isEmpty) _tokenSymbolController.text = token.title; + if (_tokenIconPathController.text.isEmpty) + _tokenIconPathController.text = token.iconPath ?? ''; if (_tokenDecimalController.text.isEmpty) _tokenDecimalController.text = token.decimals.toString(); } @@ -305,10 +310,15 @@ class _EditTokenPageBodyState extends State { if (text?.isEmpty ?? true) { return S.of(context).field_required; } + if (int.tryParse(text!) == null) { return S.of(context).invalid_input; } + if (int.tryParse(text) == 0) { + return S.current.decimals_cannot_be_zero; + } + return null; }, ), diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index e841423c1..aa6bb12c0 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -129,25 +129,29 @@ class HomeSettingsPage extends BasePage { 'token': token, }); }, - leading: CakeImageWidget( - imageUrl: token.iconPath, - height: 40, - width: 40, - displayOnError: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - token.title.substring(0, min(token.title.length, 2)), - style: TextStyle(fontSize: 11), - ), - ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade400, + leading: Container( + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(shape: BoxShape.circle), + child: CakeImageWidget( + imageUrl: token.iconPath, + height: 40, + width: 40, + displayOnError: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + token.title.substring(0, min(token.title.length, 2)), + style: TextStyle(fontSize: 11), ), + ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), ), - ), + ), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(30), diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index bb3ec70dc..0b7596469 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -323,7 +323,7 @@ class BalanceRowWidget extends StatelessWidget { style: TextStyle( fontSize: 16, fontFamily: 'Lato', - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w500, color: Theme.of(context).extension()!.textColor, height: 1)), ], @@ -334,24 +334,28 @@ class BalanceRowWidget extends StatelessWidget { child: Center( child: Column( children: [ - CakeImageWidget( - imageUrl: currency.iconPath, - height: 40, - width: 40, - displayOnError: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - currency.title.substring(0, min(currency.title.length, 2)), - style: TextStyle(fontSize: 11), - ), - ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade400, + Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: CakeImageWidget( + imageUrl: currency.iconPath, + height: 40, + width: 40, + displayOnError: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + currency.title.substring(0, min(currency.title.length, 2)), + style: TextStyle(fontSize: 11), ), ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), + ), ), const SizedBox(height: 10), Text( @@ -410,9 +414,7 @@ class BalanceRowWidget extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .balanceAmountColor, + color: Theme.of(context).extension()!.balanceAmountColor, height: 1, ), maxLines: 1, diff --git a/lib/src/widgets/cake_image_widget.dart b/lib/src/widgets/cake_image_widget.dart index 14c62ad34..ad02c48dd 100644 --- a/lib/src/widgets/cake_image_widget.dart +++ b/lib/src/widgets/cake_image_widget.dart @@ -18,7 +18,7 @@ class CakeImageWidget extends StatelessWidget { @override Widget build(BuildContext context) { try { - if (imageUrl == null) return _displayOnError!; + if (imageUrl == null || imageUrl!.isEmpty) return _displayOnError!; if (imageUrl!.contains('assets/images')) { return Image.asset( diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index 4b9811c37..e60a37ccf 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -54,6 +54,7 @@ abstract class HomeSettingsViewModelBase with Store { symbol: token.title, decimal: token.decimals, contractAddress: contractAddress, + iconPath: token.iconPath, ); await ethereum!.addErc20Token(_balanceViewModel.wallet, erc20token); @@ -65,6 +66,7 @@ abstract class HomeSettingsViewModelBase with Store { symbol: token.title, decimal: token.decimals, contractAddress: contractAddress, + iconPath: token.iconPath, ); await polygon!.addErc20Token(_balanceViewModel.wallet, polygonToken); } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 08815bf1d..d0f1a2043 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -175,6 +175,7 @@ "debit_card": "بطاقة ائتمان", "debit_card_terms": "يخضع تخزين واستخدام رقم بطاقة الدفع الخاصة بك (وبيانات الاعتماد المقابلة لرقم بطاقة الدفع الخاصة بك) في هذه المحفظة الرقمية لشروط وأحكام اتفاقية حامل البطاقة المعمول بها مع جهة إصدار بطاقة الدفع ، كما هو معمول به من وقت لآخر.", "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", + "decimals_cannot_be_zero": "الرمز العشري لا يمكن أن يكون الصفر.", "default_buy_provider": "مزود شراء الافتراضي", "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "delete": "حذف", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 49e494394..249952d75 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -175,6 +175,7 @@ "debit_card": "Дебитна карта", "debit_card_terms": "Съхранението и използването на данните от вашата платежна карта в този дигитален портфейл подлежат на условията на съответното съгласие за картодържец от издателя на картата.", "decimal_places_error": "Твърде много знаци след десетичната запетая", + "decimals_cannot_be_zero": "Десетичната точка не може да бъде нула.", "default_buy_provider": "Доставчик по подразбиране купува", "default_sell_provider": "Доставчик за продажба по подразбиране", "delete": "Изтрий", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 348b6fa38..9b3b06ffd 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -175,6 +175,7 @@ "debit_card": "Debetní karta", "debit_card_terms": "Uložení a použití vašeho čísla platební karty (a přihlašovací údaje k vašemu číslu karty) v této digitální peněžence se řídí Obchodními podmínkami smlouvy příslušného držitele karty s vydavatelem karty (v jejich nejaktuálnější verzi).", "decimal_places_error": "Příliš mnoho desetinných míst", + "decimals_cannot_be_zero": "Desetinná desetinná škola nemůže být nulová.", "default_buy_provider": "Výchozí poskytovatel nákupu", "default_sell_provider": "Výchozí poskytovatel prodeje", "delete": "Smazat", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 25ab3a54d..8a914628f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -175,6 +175,7 @@ "debit_card": "Debitkarte", "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Geldbörse unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.", "decimal_places_error": "Zu viele Nachkommastellen", + "decimals_cannot_be_zero": "Token -Dezimalzahl kann nicht Null sein.", "default_buy_provider": "Standard-Kaufanbieter", "default_sell_provider": "Standard-Verkaufsanbieter", "delete": "Löschen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 45e8ef21b..3fe9474c5 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -175,6 +175,7 @@ "debit_card": "Debit Card", "debit_card_terms": "The storage and usage of your payment card number (and credentials corresponding to your payment card number) in this digital wallet are subject to the Terms and Conditions of the applicable cardholder agreement with the payment card issuer, as in effect from time to time.", "decimal_places_error": "Too many decimal places", + "decimals_cannot_be_zero": "Token decimal cannot be zero.", "default_buy_provider": "Default Buy Provider", "default_sell_provider": "Default Sell Provider", "delete": "Delete", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index e04bc4cfe..47b11bc48 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -175,6 +175,7 @@ "debit_card": "Tarjeta de Débito", "debit_card_terms": "El almacenamiento y el uso de su número de tarjeta de pago (y las credenciales correspondientes a su número de tarjeta de pago) en esta billetera digital están sujetos a los Términos y condiciones del acuerdo del titular de la tarjeta aplicable con el emisor de la tarjeta de pago, en vigor desde tiempo al tiempo.", "decimal_places_error": "Demasiados lugares decimales", + "decimals_cannot_be_zero": "Token Decimal no puede ser cero.", "default_buy_provider": "Proveedor de compra predeterminado", "default_sell_provider": "Proveedor de venta predeterminado", "delete": "Borrar", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 069f569ba..edae901a3 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -175,6 +175,7 @@ "debit_card": "Carte de débit", "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille (wallet) numérique peuvent être soumis aux conditions générales de l'accord du titulaire de carte parfois en vigueur avec l'émetteur de la carte de paiement.", "decimal_places_error": "Trop de décimales", + "decimals_cannot_be_zero": "La décimale du jeton ne peut pas être nulle.", "default_buy_provider": "Fournisseur d'achat par défaut", "default_sell_provider": "Fournisseur de vente par défaut", "delete": "Effacer", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7dd1cd52e..c7174d23f 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -175,6 +175,7 @@ "debit_card": "Katin Zare kudi", "debit_card_terms": "Adana da amfani da lambar katin kuɗin ku (da takaddun shaida masu dacewa da lambar katin kuɗin ku) a cikin wannan walat ɗin dijital suna ƙarƙashin Sharuɗɗa da Sharuɗɗa na yarjejeniya mai amfani da katin tare da mai fitar da katin biyan kuɗi, kamar yadda yake aiki daga lokaci zuwa lokaci.", "decimal_places_error": "Wadannan suna da tsawon harsuna", + "decimals_cannot_be_zero": "Alamar alama ba zata iya zama sifili ba.", "default_buy_provider": "Tsohuwar Siyarwa", "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "delete": "Share", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5dbe22f0e..4ee9bd4f8 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -175,6 +175,7 @@ "debit_card": "डेबिट कार्ड", "debit_card_terms": "इस डिजिटल वॉलेट में आपके भुगतान कार्ड नंबर (और आपके भुगतान कार्ड नंबर से संबंधित क्रेडेंशियल) का भंडारण और उपयोग भुगतान कार्ड जारीकर्ता के साथ लागू कार्डधारक समझौते के नियमों और शर्तों के अधीन है, जैसा कि प्रभावी है समय - समय पर।", "decimal_places_error": "बहुत अधिक दशमलव स्थान", + "decimals_cannot_be_zero": "टोकन दशमलव शून्य नहीं हो सकता।", "default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता", "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "delete": "हटाएं", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4aac8216e..a4de56dcf 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -175,6 +175,7 @@ "debit_card": "Debitna kartica", "debit_card_terms": "Pohranjivanje i korištenje broja vaše platne kartice (i vjerodajnica koje odgovaraju broju vaše platne kartice) u ovom digitalnom novčaniku podliježu Uvjetima i odredbama važećeg ugovora vlasnika kartice s izdavateljem platne kartice, koji su na snazi ​​od S vremena na vrijeme.", "decimal_places_error": "Previše decimalnih mjesta", + "decimals_cannot_be_zero": "Token Decimal ne može biti nula.", "default_buy_provider": "Zadani davatelj kupnje", "default_sell_provider": "Zadani dobavljač prodaje", "delete": "Izbriši", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 09d28e453..411daf9e0 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -175,6 +175,7 @@ "debit_card": "Kartu Debit", "debit_card_terms": "Penyimpanan dan penggunaan nomor kartu pembayaran Anda (dan kredensial yang sesuai dengan nomor kartu pembayaran Anda) dalam dompet digital ini tertakluk pada Syarat dan Ketentuan persetujuan pemegang kartu yang berlaku dengan penerbit kartu pembayaran, seperti yang berlaku dari waktu ke waktu.", "decimal_places_error": "Terlalu banyak tempat desimal", + "decimals_cannot_be_zero": "Token desimal tidak bisa nol.", "default_buy_provider": "Penyedia beli default", "default_sell_provider": "Penyedia Penjualan Default", "delete": "Hapus", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index c9ac60bb5..7cf298cae 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -176,6 +176,7 @@ "debit_card": "Carta di debito", "debit_card_terms": "L'archiviazione e l'utilizzo del numero della carta di pagamento (e delle credenziali corrispondenti al numero della carta di pagamento) in questo portafoglio digitale sono soggetti ai Termini e condizioni del contratto applicabile con il titolare della carta con l'emittente della carta di pagamento, come in vigore da tempo al tempo.", "decimal_places_error": "Troppe cifre decimali", + "decimals_cannot_be_zero": "Il decimale token non può essere zero.", "default_buy_provider": "Provider di acquisto predefinito", "default_sell_provider": "Fornitore di vendita predefinito", "delete": "Elimina", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 98d87a90c..42377fa85 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -175,6 +175,7 @@ "debit_card": "デビットカード", "debit_card_terms": "このデジタルウォレットでの支払いカード番号(および支払いカード番号に対応する資格情報)の保存と使用には、支払いカード発行者との該当するカード所有者契約の利用規約が適用されます。時々。", "decimal_places_error": "小数点以下の桁数が多すぎる", + "decimals_cannot_be_zero": "トークン小数はゼロにすることはできません。", "default_buy_provider": "デフォルトの購入プロバイダー", "default_sell_provider": "デフォルトの販売プロバイダー", "delete": "削除する", @@ -809,4 +810,4 @@ "you_will_get": "に変換", "you_will_send": "から変換", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 7cc49e315..c67d531ce 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -175,6 +175,7 @@ "debit_card": "직불 카드", "debit_card_terms": "이 디지털 지갑에 있는 귀하의 지불 카드 번호(및 귀하의 지불 카드 번호에 해당하는 자격 증명)의 저장 및 사용은 부터 발효되는 지불 카드 발행자와의 해당 카드 소지자 계약의 이용 약관을 따릅니다. 수시로.", "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", + "decimals_cannot_be_zero": "토큰 소수점은 0이 될 수 없습니다.", "default_buy_provider": "기본 구매 제공자", "default_sell_provider": "기본 판매 공급자", "delete": "지우다", @@ -810,4 +811,4 @@ "you_will_send": "다음에서 변환", "YY": "YY", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 9c88dc817..e373eefc0 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -175,6 +175,7 @@ "debit_card": "ဒက်ဘစ်ကတ်", "debit_card_terms": "ဤဒစ်ဂျစ်တယ်ပိုက်ဆံအိတ်ရှိ သင့်ငွေပေးချေမှုကတ်နံပါတ် (နှင့် သင့်ငွေပေးချေကတ်နံပါတ်နှင့် သက်ဆိုင်သောအထောက်အထားများ) ၏ သိုလှောင်မှုနှင့် အသုံးပြုမှုသည် အချိန်အခါနှင့်အမျှ သက်ရောက်မှုရှိသကဲ့သို့ ကတ်ကိုင်ဆောင်ထားသူ၏ သဘောတူညီချက်၏ စည်းကမ်းသတ်မှတ်ချက်များနှင့် ကိုက်ညီပါသည်။", "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", + "decimals_cannot_be_zero": "တိုကင်ဒ decimal မသုညမဖြစ်နိုင်ပါ။", "default_buy_provider": "Default Provider ကိုဝယ်ပါ", "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "delete": "ဖျက်ပါ။", @@ -808,4 +809,4 @@ "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 74b111dcb..1fc85a28b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -175,6 +175,7 @@ "debit_card": "Debetkaart", "debit_card_terms": "De opslag en het gebruik van uw betaalkaartnummer (en inloggegevens die overeenkomen met uw betaalkaartnummer) in deze digitale portemonnee zijn onderworpen aan de Algemene voorwaarden van de toepasselijke kaarthouderovereenkomst met de uitgever van de betaalkaart, zoals van kracht vanaf tijd tot tijd.", "decimal_places_error": "Te veel decimalen", + "decimals_cannot_be_zero": "Token decimaal kan niet nul zijn.", "default_buy_provider": "Standaard Koopprovider", "default_sell_provider": "Standaard verkoopaanbieder", "delete": "Delete", @@ -809,4 +810,4 @@ "you_will_get": "Converteren naar", "you_will_send": "Converteren van", "yy": "JJ" -} +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 2ac1b9fb5..f279dbaa7 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -175,6 +175,7 @@ "debit_card": "Karta debetowa", "debit_card_terms": "Przechowywanie i używanie numeru karty płatniczej (oraz danych uwierzytelniających odpowiadających numerowi karty płatniczej) w tym portfelu cyfrowym podlega Warunkom odpowiedniej umowy posiadacza karty z wydawcą karty płatniczej, zgodnie z obowiązującym od od czasu do czasu.", "decimal_places_error": "Za dużo miejsc dziesiętnych", + "decimals_cannot_be_zero": "Token dziesiętny nie może być zerowy.", "default_buy_provider": "Domyślny dostawca zakupu", "default_sell_provider": "Domyślny dostawca sprzedaży", "delete": "Skasuj", @@ -808,4 +809,4 @@ "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", "yy": "RR" -} +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index bf0b0082d..ba3acae88 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -175,6 +175,7 @@ "debit_card": "Cartão de débito", "debit_card_terms": "O armazenamento e uso do número do cartão de pagamento (e credenciais correspondentes ao número do cartão de pagamento) nesta carteira digital estão sujeitos aos Termos e Condições do contrato do titular do cartão aplicável com o emissor do cartão de pagamento, em vigor a partir de tempo ao tempo.", "decimal_places_error": "Muitas casas decimais", + "decimals_cannot_be_zero": "Decimal de token não pode ser zero.", "default_buy_provider": "Provedor de compra padrão", "default_sell_provider": "Provedor de venda padrão", "delete": "Excluir", @@ -811,4 +812,4 @@ "you_will_get": "Converter para", "you_will_send": "Converter de", "yy": "aa" -} +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 999728faf..b24f940dd 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -175,6 +175,7 @@ "debit_card": "Дебетовая карта", "debit_card_terms": "Хранение и использование номера вашей платежной карты (и учетных данных, соответствующих номеру вашей платежной карты) в этом цифровом кошельке регулируются положениями и условиями применимого соглашения держателя карты с эмитентом платежной карты, действующим с время от времени.", "decimal_places_error": "Слишком много десятичных знаков", + "decimals_cannot_be_zero": "Десятичный токен не может быть нулевым.", "default_buy_provider": "По умолчанию поставщик покупки", "default_sell_provider": "Поставщик продаж по умолчанию", "delete": "Удалить", @@ -809,4 +810,4 @@ "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", "yy": "ГГ" -} +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index a71bc6b36..0795faf2e 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -175,6 +175,7 @@ "debit_card": "บัตรเดบิต", "debit_card_terms": "การเก็บรักษาและใช้หมายเลขบัตรจ่ายเงิน (และข้อมูลประจำตัวที่เกี่ยวข้องกับหมายเลขบัตรจ่ายเงิน) ในกระเป๋าดิจิทัลนี้ จะต้องยึดถือข้อกำหนดและเงื่อนไขของข้อตกลงผู้ใช้บัตรของผู้ถือบัตรที่เกี่ยวข้องกับบัตรผู้ถือบัตร ซึ่งจะมีผลตั้งแต่เวลานั้น", "decimal_places_error": "ทศนิยมมากเกินไป", + "decimals_cannot_be_zero": "ทศนิยมโทเค็นไม่สามารถเป็นศูนย์ได้", "default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น", "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "delete": "ลบ", @@ -808,4 +809,4 @@ "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", "yy": "ปี" -} +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 73cd8a1f7..91ca5a548 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -175,6 +175,7 @@ "debit_card": "Debit card", "debit_card_terms": "Ang pag -iimbak at paggamit ng numero ng iyong card ng pagbabayad (at mga kredensyal na naaayon sa iyong numero ng card ng pagbabayad) sa digital na pitaka na ito ay napapailalim sa mga termino at kundisyon ng naaangkop na kasunduan sa cardholder kasama ang nagbigay ng card ng pagbabayad, tulad ng sa oras -oras.", "decimal_places_error": "Masyadong maraming mga lugar na desimal", + "decimals_cannot_be_zero": "Ang Token Decimal ay hindi maaaring maging zero.", "default_buy_provider": "Default na Provider ng Pagbili", "default_sell_provider": "Default na Sell Provider", "delete": "Tanggalin", @@ -808,4 +809,4 @@ "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index de197c1b1..784ebfb7e 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -175,6 +175,7 @@ "debit_card": "Ön ödemeli Kart", "debit_card_terms": "Ödeme kartı numaranızın (ve kart numaranıza karşılık gelen kimlik bilgilerinin) bu dijital cüzdanda saklanması ve kullanılması, zaman zaman yürürlükte olan ödeme kartı veren kuruluşla yapılan ilgili kart sahibi sözleşmesinin Hüküm ve Koşullarına tabidir.", "decimal_places_error": "Çok fazla ondalık basamak", + "decimals_cannot_be_zero": "Token oncial sıfır olamaz.", "default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı", "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "delete": "Sil", @@ -808,4 +809,4 @@ "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 86e60214b..65a1f5c96 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -175,6 +175,7 @@ "debit_card": "Дебетова картка", "debit_card_terms": "Зберігання та використання номера вашої платіжної картки (та облікових даних, які відповідають номеру вашої платіжної картки) у цьому цифровому гаманці регулюються Умовами відповідної угоди власника картки з емітентом платіжної картки, що діє з час від часу.", "decimal_places_error": "Забагато знаків після коми", + "decimals_cannot_be_zero": "Десятковий знак не може бути нульовим.", "default_buy_provider": "Постачальник покупки за замовчуванням", "default_sell_provider": "Постачальник продажу за замовчуванням", "delete": "Видалити", @@ -809,4 +810,4 @@ "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 725a1d895..6c768daa8 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -175,6 +175,7 @@ "debit_card": "ڈیبٹ کارڈ", "debit_card_terms": "اس ڈیجیٹل والیٹ میں آپ کے ادائیگی کارڈ نمبر (اور آپ کے ادائیگی کارڈ نمبر سے متعلقہ اسناد) کا ذخیرہ اور استعمال ادائیگی کارڈ جاری کنندہ کے ساتھ قابل اطلاق کارڈ ہولڈر کے معاہدے کی شرائط و ضوابط کے ساتھ مشروط ہے، جیسا کہ وقتاً فوقتاً نافذ ہوتا ہے۔", "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", + "decimals_cannot_be_zero": "ٹوکن اعشاریہ صفر نہیں ہوسکتا۔", "default_buy_provider": "پہلے سے طے شدہ خریدنے والا", "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "delete": "حذف کریں۔", @@ -810,4 +811,4 @@ "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 517757716..b5f2d69a3 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -175,6 +175,7 @@ "debit_card": "Káàdì ìrajà", "debit_card_terms": "Òfin ti olùṣe àjọrò káàdì ìrajà bójú irú ọ̀nà t'á pamọ́ àti a lo òǹkà ti káàdì ìrajà yín (àti ọ̀rọ̀ ìdánimọ̀ tí káàdì náà) nínú àpamọ́wọ́ yìí.", "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", + "decimals_cannot_be_zero": "Token eleemel ko le jẹ odo.", "default_buy_provider": "Aiyipada Ra Olupese", "default_sell_provider": "Aiyipada Olupese Tita", "delete": "Pa á", @@ -809,4 +810,4 @@ "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", "yy": "Ọd" -} +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 104848996..e9a6b63f2 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -175,6 +175,7 @@ "debit_card": "借记卡", "debit_card_terms": "您的支付卡号(以及与您的支付卡号对应的凭证)在此数字钱包中的存储和使用受适用的持卡人与支付卡发卡机构签订的协议的条款和条件的约束,自时不时。", "decimal_places_error": "小数位太多", + "decimals_cannot_be_zero": "代币十进制不能为零。", "default_buy_provider": "默认购买提供商", "default_sell_provider": "默认销售提供商", "delete": "删除", @@ -808,4 +809,4 @@ "you_will_get": "转换到", "you_will_send": "转换自", "yy": "YY" -} +} \ No newline at end of file diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 430de03b6..8fedbb12a 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -42,6 +42,7 @@ class SecretKey { static final evmChainsSecrets = [ SecretKey('etherScanApiKey', () => ''), SecretKey('polygonScanApiKey', () => ''), + SecretKey('moralisApiKey', () => ''), ]; static final solanaSecrets = [ From 69587e813fb0bba4686d79626baa9baf72a50ed6 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Mon, 8 Apr 2024 19:04:16 -0400 Subject: [PATCH 3/9] Always show addresses page for Monero and remove unused text showing up for wallets it shouldn't be (#1363) --- .../screens/dashboard/pages/address_page.dart | 19 +++------- lib/src/screens/receive/receive_page.dart | 35 ++----------------- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index 0d7c4f11c..3c77cad48 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -163,12 +163,7 @@ class AddressPage extends BasePage { if (addressListViewModel.hasAddressList) { return SelectButton( text: addressListViewModel.buttonTitle, - onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled && - (WalletType.monero == addressListViewModel.wallet.type || - WalletType.haven == addressListViewModel.wallet.type) - ? await showPopUp( - context: context, builder: (_) => getIt.get()) - : Navigator.of(context).pushNamed(Routes.receive), + onTap: () async => Navigator.of(context).pushNamed(Routes.receive), textColor: Theme.of(context).extension()!.textColor, color: Theme.of(context).extension()!.syncedBackgroundColor, borderColor: Theme.of(context).extension()!.cardBorderColor, @@ -176,17 +171,11 @@ class AddressPage extends BasePage { textSize: 14, height: 50, ); - } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || - addressListViewModel.isElectrumWallet) { - return Text(S.of(context).electrum_address_disclaimer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - color: Theme.of(context).extension()!.labelTextColor)); - } else { + } + else { return const SizedBox(); } - }) + }), ], ), )); diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 75719d123..ecba4acf5 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -99,12 +99,7 @@ class ReceivePage extends BasePage { @override Widget body(BuildContext context) { - final isElectrumWallet = addressListViewModel.isElectrumWallet; - return (addressListViewModel.type == WalletType.monero || - addressListViewModel.type == WalletType.haven || - addressListViewModel.type == WalletType.nano || - isElectrumWallet) - ? KeyboardActions( + return KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, keyboardBarColor: Theme.of(context).extension()!.keyboardBarColor, @@ -213,32 +208,6 @@ class ReceivePage extends BasePage { })), ], ), - )) - : Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Column( - children: [ - Expanded( - flex: 7, - child: QRWidget( - formKey: _formKey, - heroTag: _heroTag, - addressListViewModel: addressListViewModel, - amountTextFieldFocusNode: _cryptoAmountFocus, - amountController: _amountController, - isLight: currentTheme.type == ThemeType.light), - ), - Expanded( - flex: 2, - child: SizedBox(), - ), - Text(S.of(context).electrum_address_disclaimer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - color: Theme.of(context).extension()!.labelTextColor)), - ], - ), - ); + )); } } From f9679fecbeaacbbf3d4694a14a00cf47e5262448 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:26:11 +0100 Subject: [PATCH 4/9] CW-584-WalletConnect-For-Solana (#1362) * chore: Create cw_solana package and clean up files * feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens * fix: Make transactions file specific to solana only for solana transactions * chore: Revert inject app details script * fix: Fix issue with node and switch current node to main beta instead of testnet * fix: Fix merge conflicts and adjust migration version * fix: Fetch spl token error Signed-off-by: Blazebrain * fix: Diplay and activate spl tokens bug * fix: Review and fixes * fix: reverted formatting for cryptocurrency class * fix: Review comments, split sending flow into signing and sending separately, fix issues * fix: Revert throwing unimplenented error * chore: Fix comment * chore: Fix comment * fix: Errors in flow * Update provider_types.dart [skip ci] * fix: Issues with solana wallet * Update solana_wallet.dart [skip ci] * fix: Review comments * fix: Date time config * fix: Revert bash script for app details * fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list * fix: Issues with address validation when sending spl tokens and walletconnect initial setup * fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect * fix: Adjust imports that would affect monerocom building successfully * fix: Refine transaction direction and continue work on walletconnect * feat: Display SPL token transfers in the transaction history and finally settle the transaction direction * fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions * feat: Switch node and revert solana chain id to previous id * fix: Remove print statement * fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message * chore: Code refactoring and streamlined wallet type check for solana send success message * fix: Make timeout error for node silent and add spl token images * fix: Still trying to figure out what's wrong * Sync with remote * feat: First run for walletconnect for solana * chore: Add ankr api key to secrets * remove duplicate transaction [skip ci] --------- Signed-off-by: Blazebrain Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 1 + .../chain_service/solana/solana_chain_id.dart | 19 +++++++++------- .../solana/solana_chain_service.dart | 14 +++++++----- .../wallet_connect/web3wallet_service.dart | 22 +++++++++++++++---- lib/reactions/wallet_connect.dart | 1 + tool/utils/secret_key.dart | 1 + 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index db9870412..dc231df42 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -139,6 +139,7 @@ jobs: echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart + echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart index bdc8a7d20..ed80a4f3f 100644 --- a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart @@ -2,8 +2,8 @@ import 'solana_chain_service.dart'; enum SolanaChainId { mainnet, - testnet, - devnet, + // testnet, + // devnet, } extension SolanaChainIdX on SolanaChainId { @@ -13,13 +13,16 @@ extension SolanaChainIdX on SolanaChainId { switch (this) { case SolanaChainId.mainnet: name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ'; + // solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp break; - case SolanaChainId.testnet: - name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; - break; - case SolanaChainId.devnet: - name = ''; - break; + // case SolanaChainId.devnet: + // name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; + // // solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 + // break; + // case SolanaChainId.testnet: + // name = ''; + // // solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z + // break; } return '${SolanaChainServiceImpl.namespace}:$name'; diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart index f5c696be6..efbf9df74 100644 --- a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart @@ -43,7 +43,7 @@ class SolanaChainServiceImpl implements ChainService { SolanaClient( rpcUrl: rpcUrl, websocketUrl: Uri.parse(webSocketUrl), - timeout: const Duration(minutes: 2), + timeout: const Duration(minutes: 5), ) { for (final String event in getEvents()) { wallet.registerEventEmitter(chainId: getChainId(), event: event); @@ -72,7 +72,7 @@ class SolanaChainServiceImpl implements ChainService { @override List getEvents() { - return ['']; + return ['chainChanged', 'accountsChanged']; } Future requestAuthorization(String? text) async { @@ -100,8 +100,7 @@ class SolanaChainServiceImpl implements ChainService { Future solanaSignTransaction(String topic, dynamic parameters) async { log('received solana sign transaction request $parameters'); - final solanaSignTx = - SolanaSignTransaction.fromJson(parameters as Map); + final solanaSignTx = SolanaSignTransaction.fromJson(parameters as Map); final String? authError = await requestAuthorization('Confirm request to sign transaction?'); @@ -122,10 +121,13 @@ class SolanaChainServiceImpl implements ChainService { return ''; } - String signature = sign.signatures.first.toBase58(); + String signature = await solanaClient.sendAndConfirmTransaction( + message: message, + signers: [ownerKeyPair!], + commitment: Commitment.confirmed, + ); print(signature); - print(signature.runtimeType); bottomSheetService.queueBottomSheet( isModalDismissible: true, diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 4c71abe48..66ccb2d76 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -133,13 +133,27 @@ abstract class Web3WalletServiceBase with Store { if (appStore.wallet!.type == WalletType.solana) { for (final cId in SolanaChainId.values) { final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type); - final rpcUri = node.uri; - final webSocketUri = 'wss://${node.uriRaw}/ws${node.uri.path}'; + + Uri? rpcUri; + String webSocketUrl; + bool isModifiedNodeUri = false; + + if (node.uriRaw == 'rpc.ankr.com') { + isModifiedNodeUri = true; + + //A better way to handle this instead of adding this to the general secrets? + String ankrApiKey = secrets.ankrApiKey; + + rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey'); + webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey'; + } else { + webSocketUrl = 'wss://${node.uriRaw}'; + } SolanaChainServiceImpl( reference: cId, - rpcUrl: rpcUri, - webSocketUrl: webSocketUri, + rpcUrl: isModifiedNodeUri ? rpcUri! : node.uri, + webSocketUrl: webSocketUrl, wcKeyService: walletKeyService, bottomSheetService: _bottomSheetHandler, wallet: _web3Wallet, diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index f4487123e..ca908bc65 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -16,6 +16,7 @@ bool isWalletConnectCompatibleChain(WalletType walletType) { switch (walletType) { case WalletType.polygon: case WalletType.ethereum: + case WalletType.solana: return true; default: return false; diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 8fedbb12a..5d5e61cec 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -37,6 +37,7 @@ class SecretKey { SecretKey('exchangeHelperApiKey', () => ''), SecretKey('walletConnectProjectId', () => ''), SecretKey('moralisApiKey', () => ''), + SecretKey('ankrApiKey', () => ''), ]; static final evmChainsSecrets = [ From 8a61ab77800ca2c896d88cbe28e6b9eddecd617f Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 10 Apr 2024 03:28:31 +0200 Subject: [PATCH 5/9] enhance UI for used addresses (#1337) * enhance UI for used addresses * Update electrum_wallet_addresses.dart * fix tablet UI --------- Co-authored-by: Serhii --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 2 + .../screens/receive/widgets/address_cell.dart | 63 ++++++++++--------- lib/src/screens/settings/privacy_page.dart | 4 +- lib/utils/responsive_layout_util.dart | 4 ++ .../settings/privacy_settings_view_model.dart | 2 + res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 3 +- 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 + 31 files changed, 72 insertions(+), 31 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ac2397561..c43d4988a 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -241,6 +241,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final index = _addresses.indexOf(addressRecord); _addresses.remove(addressRecord); _addresses.insert(index, addressRecord); + + updateAddressesByMatch(); } @action diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index a07456284..9385a4df8 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -1,5 +1,6 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; @@ -81,41 +82,45 @@ class AddressCell extends StatelessWidget { child: Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: name.isNotEmpty ? MainAxisAlignment.spaceBetween : MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ - if (isChange) - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: Container( - height: 20, - padding: EdgeInsets.all(4), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(8.5)), - color: textColor), - alignment: Alignment.center, - child: Text( - S.of(context).unspent_change, - style: TextStyle( - color: backgroundColor, - fontSize: 10, - fontWeight: FontWeight.w600, + Row( + children: [ + if (isChange) + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Container( + height: 20, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.5)), + color: textColor), + alignment: Alignment.center, + child: Text( + S.of(context).unspent_change, + style: TextStyle( + color: backgroundColor, + fontSize: 10, + fontWeight: FontWeight.w600, + ), + ), ), ), - ), - ), - if (name.isNotEmpty) - Text( - '$name - ', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: textColor, - ), - ), + if (name.isNotEmpty) + Text( + '$name', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + ], + ), Flexible( child: AutoSizeText( - formattedAddress, + responsiveLayoutUtil.shouldRenderTabletUI ? address : formattedAddress, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 444457d1c..7e7f3589b 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -55,7 +55,9 @@ class PrivacyPage extends BasePage { }), if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) SettingsSwitcherCell( - title: S.current.auto_generate_subaddresses, + title: _privacySettingsViewModel.isMoneroWallet + ? S.current.auto_generate_subaddresses + : S.current.auto_generate_addresses, value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, onValueChange: (BuildContext _, bool value) { _privacySettingsViewModel.setAutoGenerateSubaddresses(value); diff --git a/lib/utils/responsive_layout_util.dart b/lib/utils/responsive_layout_util.dart index 428ab61cc..86a4a3776 100644 --- a/lib/utils/responsive_layout_util.dart +++ b/lib/utils/responsive_layout_util.dart @@ -46,6 +46,10 @@ abstract class ResponsiveLayoutUtilBase with Store, WidgetsBindingObserver { (orientation == Orientation.portrait && screenWidth < screenHeight) || (orientation == Orientation.landscape && screenWidth < screenHeight); } + + bool get shouldRenderTabletUI { + return screenWidth > _kMobileThreshold && screenWidth < kDesktopMaxDashBoardWidthConstraint; + } } _ResponsiveLayoutUtil _singletonResponsiveLayoutUtil = _ResponsiveLayoutUtil(); diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 831a45357..9ebbd92bb 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -44,6 +44,8 @@ abstract class PrivacySettingsViewModelBase with Store { _wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash; + bool get isMoneroWallet => _wallet.type == WalletType.monero; + @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index d0f1a2043..6b3aae14e 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN خطأ", "authenticated": "تم المصادقة", "authentication": "المصادقة", + "auto_generate_addresses": "تلقائي توليد العناوين", "auto_generate_subaddresses": "تلقائي توليد subddresses", "automatic": "تلقائي", "available_balance": "الرصيد المتوفر", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 249952d75..30d9945d1 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Грешен PIN", "authenticated": "Удостоверено", "authentication": "Удостоверяване", + "auto_generate_addresses": "Автоматично генериране на адреси", "auto_generate_subaddresses": "Автоматично генериране на подадреси", "automatic": "Автоматично", "available_balance": "Наличен баланс", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 9b3b06ffd..577cd9813 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Nesprávný PIN", "authenticated": "Ověřeno", "authentication": "Ověřování", + "auto_generate_addresses": "Automatické generování adres", "auto_generate_subaddresses": "Automaticky generovat podadresy", "automatic": "Automatický", "available_balance": "Dostupný zůstatek", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8a914628f..f0ba70c84 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Falsche PIN", "authenticated": "Authentifiziert", "authentication": "Authentifizierung", + "auto_generate_addresses": "Automatisch generieren Adressen", "auto_generate_subaddresses": "Unteradressen automatisch generieren", "automatic": "Automatisch", "available_balance": "Verfügbares Guthaben", @@ -422,8 +423,8 @@ "placeholder_transactions": "Ihre Transaktionen werden hier angezeigt", "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", "please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.", - "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.", + "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "please_select": "Bitte auswählen:", "please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.", "please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3fe9474c5..f8bd6b3a2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Wrong PIN", "authenticated": "Authenticated", "authentication": "Authentication", + "auto_generate_addresses": "Auto generate addresses", "auto_generate_subaddresses": "Auto generate subaddresses", "automatic": "Automatic", "available_balance": "Available Balance", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 47b11bc48..cf70a2c2d 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Contraseña PIN", "authenticated": "Autenticados", "authentication": "Autenticación", + "auto_generate_addresses": "Auto Generar direcciones", "auto_generate_subaddresses": "Generar subdirecciones automáticamente", "automatic": "Automático", "available_balance": "Balance disponible", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index edae901a3..d21e21dae 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Mauvais code PIN", "authenticated": "Authentifié", "authentication": "Authentification", + "auto_generate_addresses": "Adresses de génération automatique", "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "automatic": "Automatique", "available_balance": "Solde Disponible", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index c7174d23f..35a6be1b8 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN na gaskiya", "authenticated": "Ingantacce", "authentication": "Tabbatarwa", + "auto_generate_addresses": "Adireshin Auto", "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", "automatic": "Na atomatik", "available_balance": "KUDI", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 4ee9bd4f8..a6bcab4ab 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "गलत पिन", "authenticated": "प्रमाणीकृत", "authentication": "प्रमाणीकरण", + "auto_generate_addresses": "ऑटो उत्पन्न पते", "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", "automatic": "स्वचालित", "available_balance": "उपलब्ध शेष राशि", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index a4de56dcf..e01857a94 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Pogrešan PIN", "authenticated": "Autentificiran", "authentication": "Autentifikacija", + "auto_generate_addresses": "Automatsko generiranje adresa", "auto_generate_subaddresses": "Automatski generirajte podadrese", "automatic": "Automatski", "available_balance": "Raspoloživ iznos", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 411daf9e0..c487a6750 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN yang salah", "authenticated": "Terotentikasi", "authentication": "Otentikasi", + "auto_generate_addresses": "Auto menghasilkan alamat", "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", "automatic": "Otomatis", "available_balance": "Saldo Tersedia", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 7cf298cae..0af315426 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN non corretto", "authenticated": "Autenticato", "authentication": "Autenticazione", + "auto_generate_addresses": "Auto Genera indirizzi", "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", "automatic": "Automatico", "available_balance": "Saldo Disponibile", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 42377fa85..a0b3973b2 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "間違ったPIN", "authenticated": "認証済み", "authentication": "認証", + "auto_generate_addresses": "Autoはアドレスを生成します", "auto_generate_subaddresses": "Autoはサブアドレスを生成します", "automatic": "自動", "available_balance": "利用可能残高", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index c67d531ce..98bc40e77 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "잘못된 PIN", "authenticated": "인증", "authentication": "입증", + "auto_generate_addresses": "자동 생성 주소", "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", "automatic": "자동적 인", "available_balance": "사용 가능한 잔액", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index e373eefc0..8d846f3d6 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "ပင်နံပါတ် မှားနေသည်။", "authenticated": "အစစ်အမှန်", "authentication": "စစ်ဆေးခြင်း", + "auto_generate_addresses": "Auto Generate လိပ်စာများ", "auto_generate_subaddresses": "အော်တို Generate Subaddresses", "automatic": "အလိုအလျောက်", "available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 1fc85a28b..8b3edee4b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Incorrect PIN", "authenticated": "Authenticated", "authentication": "Authenticatie", + "auto_generate_addresses": "Auto -genereer adressen", "auto_generate_subaddresses": "Automatisch subadressen genereren", "automatic": "automatisch", "available_balance": "Beschikbaar saldo", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f279dbaa7..93dafa352 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Niepoprawny PIN", "authenticated": "Uwierzytelniony", "authentication": "Uwierzytelnianie", + "auto_generate_addresses": "Auto generują adresy", "auto_generate_subaddresses": "Automatycznie generuj podadresy", "automatic": "Automatyczny", "available_balance": "Dostępne środki", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ba3acae88..ae07bb177 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN incorreto", "authenticated": "Autenticado", "authentication": "Autenticação", + "auto_generate_addresses": "Endereços gerados automaticamente", "auto_generate_subaddresses": "Gerar subendereços automaticamente", "automatic": "Automático", "available_balance": "Saldo disponível", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b24f940dd..5e75631c6 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Некорректный PIN", "authenticated": "Аутентифицировано", "authentication": "Аутентификация", + "auto_generate_addresses": "Авто генерируйте адреса", "auto_generate_subaddresses": "Авто генерируйте Subaddresses", "automatic": "автоматический", "available_balance": "Доступный баланс", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0795faf2e..c8183c031 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "รหัสผ่านไม่ถูกต้อง", "authenticated": "ได้รับการยืนยันสิทธิ์", "authentication": "การยืนยันสิทธิ์", + "auto_generate_addresses": "สร้างที่อยู่อัตโนมัติ", "auto_generate_subaddresses": "Auto สร้าง subaddresses", "automatic": "อัตโนมัติ", "available_balance": "ยอดคงเหลือที่ใช้งานได้", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 91ca5a548..def38820c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Maling pin", "authenticated": "Napatunayan", "authentication": "Pagpapatunay", + "auto_generate_addresses": "Auto bumuo ng mga address", "auto_generate_subaddresses": "Ang Auto ay bumubuo ng mga subaddresses", "automatic": "Awtomatiko", "available_balance": "Magagamit na balanse", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 784ebfb7e..111ff91f4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Hatalı PIN", "authenticated": "Doğrulandı", "authentication": "Doğrulama", + "auto_generate_addresses": "Otomatik Adres Oluşturma", "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", "automatic": "Otomatik", "available_balance": "Kullanılabilir Bakiye", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 65a1f5c96..a0000418d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Некоректний PIN", "authenticated": "Аутентифіковано", "authentication": "Аутентифікація", + "auto_generate_addresses": "Авто генерувати адреси", "auto_generate_subaddresses": "Автоматично генерувати підадреси", "automatic": "Автоматичний", "available_balance": "Доступний баланс", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 6c768daa8..a7d4b896d 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "غلط PIN", "authenticated": "تصدیق شدہ", "authentication": "تصدیق", + "auto_generate_addresses": "آٹو پیدا کرنے والے پتے", "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", "automatic": "خودکار", "available_balance": "دستیاب بیلنس", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index b5f2d69a3..9ac033917 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Òǹkà ìdánimọ̀ àdáni kọ́ ni èyí", "authenticated": "A ti jẹ́rìísí yín", "authentication": "Ìfẹ̀rílàdí", + "auto_generate_addresses": "Awọn adirẹsi ṣe agbekalẹ awọn adirẹsi", "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", "automatic": "Ó máa ń ṣàdédé", "available_balance": "Ìyókù owó tó wà níbẹ̀", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e9a6b63f2..26bb1b286 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN码错误", "authenticated": "已认证", "authentication": "认证方式", + "auto_generate_addresses": "自动生成地址", "auto_generate_subaddresses": "自动生成子辅助", "automatic": "自动的", "available_balance": "可用余额", From dcf8ef0d715e4475efdd1e9ee4006d1bdc31329f Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Tue, 9 Apr 2024 21:32:43 -0400 Subject: [PATCH 6/9] Create SECURITY.md (#1375) * Create SECURITY.md * Update SECURITY.md --- SECURITY.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..a1b489b76 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,12 @@ +# Security Policy + +## Reporting a Vulnerability + +If you need to report a vulnerability, please either: + +* Open a security advisory: https://github.com/cake-tech/cake_wallet/security/advisories/new +* Send an email to `dev@cakewallet.com` with details on the vulnerability + +## Supported Versions + +As we don't maintain prevoius versions of the app, only the latest release for each platform is supported and any updates will bump the version number. From 7abe5735c0d03f65a0b3576170e8814e159b3a0f Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:33:43 +0100 Subject: [PATCH 7/9] CW-589-WalletConnect-Connections-Independent (#1361) * chore: Create cw_solana package and clean up files * feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens * fix: Make transactions file specific to solana only for solana transactions * chore: Revert inject app details script * fix: Fix issue with node and switch current node to main beta instead of testnet * fix: Fix merge conflicts and adjust migration version * fix: Fetch spl token error Signed-off-by: Blazebrain * fix: Diplay and activate spl tokens bug * fix: Review and fixes * fix: reverted formatting for cryptocurrency class * fix: Review comments, split sending flow into signing and sending separately, fix issues * fix: Revert throwing unimplenented error * chore: Fix comment * chore: Fix comment * fix: Errors in flow * Update provider_types.dart [skip ci] * fix: Issues with solana wallet * Update solana_wallet.dart [skip ci] * fix: Review comments * fix: Date time config * fix: Revert bash script for app details * fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list * fix: Issues with address validation when sending spl tokens and walletconnect initial setup * fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect * fix: Adjust imports that would affect monerocom building successfully * fix: Refine transaction direction and continue work on walletconnect * feat: Display SPL token transfers in the transaction history and finally settle the transaction direction * fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions * feat: Switch node and revert solana chain id to previous id * fix: Remove print statement * fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message * chore: Code refactoring and streamlined wallet type check for solana send success message * fix: Make timeout error for node silent and add spl token images * fix: Still trying to figure out what's wrong * feat: Make walletconnect connections independent to wallet * fix: Add proper return type to method * fix: Alphabetizing translation files --------- Signed-off-by: Blazebrain Co-authored-by: Omar Hatem --- .../wallet_connect/web3wallet_service.dart | 88 +++++++++++++++++-- lib/di.dart | 1 + lib/entities/preferences_key.dart | 3 + .../widgets/pairing_item_widget.dart | 2 +- 4 files changed, 84 insertions(+), 10 deletions(-) diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 66ccb2d76..adb516817 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -1,10 +1,12 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'dart:typed_data'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; +import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; @@ -19,6 +21,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'chain_service/solana/solana_chain_id.dart'; @@ -32,6 +35,7 @@ class Web3WalletService = Web3WalletServiceBase with _$Web3WalletService; abstract class Web3WalletServiceBase with Store { final AppStore appStore; + final SharedPreferences sharedPreferences; final BottomSheetService _bottomSheetHandler; final WalletConnectKeyService walletKeyService; @@ -52,7 +56,8 @@ abstract class Web3WalletServiceBase with Store { @observable ObservableList auth; - Web3WalletServiceBase(this._bottomSheetHandler, this.walletKeyService, this.appStore) + Web3WalletServiceBase( + this._bottomSheetHandler, this.walletKeyService, this.appStore, this.sharedPreferences) : pairings = ObservableList(), sessions = ObservableList(), auth = ObservableList(), @@ -191,13 +196,6 @@ abstract class Web3WalletServiceBase with Store { _refreshPairings(); } - @action - void _refreshPairings() { - pairings.clear(); - final allPairings = _web3Wallet.pairings.getAll(); - pairings.addAll(allPairings); - } - Future _onSessionProposalError(SessionProposalErrorEvent? args) async { log(args.toString()); } @@ -260,14 +258,37 @@ abstract class Web3WalletServiceBase with Store { } } + @action + void _refreshPairings() { + print('Refreshing pairings'); + pairings.clear(); + + final allPairings = _web3Wallet.pairings.getAll(); + + final keyForWallet = getKeyForStoringTopicsForWallet(); + + final currentTopicsForWallet = getPairingTopicsForWallet(keyForWallet); + + final filteredPairings = + allPairings.where((pairing) => currentTopicsForWallet.contains(pairing.topic)).toList(); + + pairings.addAll(filteredPairings); + } + void _onPairingCreate(PairingEvent? args) { log('Pairing Create Event: $args'); } @action - void _onSessionConnect(SessionConnect? args) { + Future _onSessionConnect(SessionConnect? args) async { if (args != null) { + log('Session Connected $args'); + + await savePairingTopicToLocalStorage(args.session.pairingTopic); + sessions.add(args.session); + + _refreshPairings(); } } @@ -335,4 +356,53 @@ abstract class Web3WalletServiceBase with Store { List getSessionsForPairingInfo(PairingInfo pairing) { return sessions.where((element) => element.pairingTopic == pairing.topic).toList(); } + + String getKeyForStoringTopicsForWallet() { + List chainKeys = walletKeyService.getKeysForChain(appStore.wallet!); + + final keyForPairingTopic = + PreferencesKey.walletConnectPairingTopicsListForWallet(chainKeys.first.publicKey); + + return keyForPairingTopic; + } + + List getPairingTopicsForWallet(String key) { + // Get the JSON-encoded string from shared preferences + final jsonString = sharedPreferences.getString(key); + + // If the string is null, return an empty list + if (jsonString == null) { + return []; + } + + // Decode the JSON string to a list of strings + final List jsonList = jsonDecode(jsonString) as List; + + // Cast each item to a string + return jsonList.map((item) => item as String).toList(); + } + + Future savePairingTopicToLocalStorage(String pairingTopic) async { + // Get key specific to the current wallet + final key = getKeyForStoringTopicsForWallet(); + + // Get all pairing topics attached to this key + final pairingTopicsForWallet = getPairingTopicsForWallet(key); + + print(pairingTopicsForWallet); + + bool isPairingTopicAlreadySaved = pairingTopicsForWallet.contains(pairingTopic); + print('Is Pairing Topic Saved: $isPairingTopicAlreadySaved'); + + if (!isPairingTopicAlreadySaved) { + // Update the list with the most recent pairing topic + pairingTopicsForWallet.add(pairingTopic); + + // Convert the list of updated pairing topics to a JSON-encoded string + final jsonString = jsonEncode(pairingTopicsForWallet); + + // Save the encoded string to shared preferences + await sharedPreferences.setString(key, jsonString); + } + } } diff --git a/lib/di.dart b/lib/di.dart index 5262a01e6..d78da638c 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -493,6 +493,7 @@ Future setup({ getIt.get(), getIt.get(), appStore, + getIt.get() ); web3WalletService.create(); return web3WalletService; diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index ba6d6ef4f..80a7acba1 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -75,4 +75,7 @@ class PreferencesKey { static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; static const isNewInstall = 'is_new_install'; static const serviceStatusShaKey = 'service_status_sha_key'; + static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list'; + static String walletConnectPairingTopicsListForWallet(String publicKey) => + '${PreferencesKey.walletConnectPairingTopicsList}_${publicKey}'; } diff --git a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart index 0d425f904..518cf32f7 100644 --- a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart +++ b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart @@ -30,7 +30,7 @@ class PairingItemWidget extends StatelessWidget { leading: CakeImageWidget( imageUrl: metadata.icons.isNotEmpty ? metadata.icons[0]: null, displayOnError: CircleAvatar( - backgroundImage: AssetImage('assets/images/default_icon.png'), + backgroundImage: AssetImage('assets/images/walletconnect_logo.png'), ), ), title: Text( From fce6394bca336eb2a28e78650fa9eb34ceef80fe Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 12 Apr 2024 05:36:42 -0700 Subject: [PATCH 8/9] Cw 602 nano bad rep (#1356) * add support for paths in node settings * update translations and fixes * fix node path * add rep warning flag * update translations * code cleanup [skip ci] * add additional node options * add migration * update transaction history rpc to be under the limit * review fixes [skip ci] * [skip ci] updates * move n2_node.dart * minor code improvements * more minor code cleanup --- assets/nano_node_list.yml | 24 +- cw_core/lib/n2_node.dart | 31 ++ cw_core/lib/node.dart | 18 +- cw_nano/lib/nano_client.dart | 38 +- cw_nano/lib/nano_wallet.dart | 13 +- lib/core/node_address_validator.dart | 5 + lib/entities/default_settings_migration.dart | 34 +- lib/entities/preferences_key.dart | 1 + lib/main.dart | 2 +- lib/nano/cw_nano.dart | 10 + .../screens/dashboard/pages/balance_page.dart | 17 + .../screens/nano/nano_change_rep_page.dart | 393 ++++++++++++++---- .../nodes/node_create_or_edit_page.dart | 4 + lib/src/screens/nodes/widgets/node_form.dart | 128 +++--- lib/src/widgets/dashboard_card_widget.dart | 58 +-- .../scollable_with_bottom_section.dart | 21 +- lib/store/settings_store.dart | 151 ++++--- .../dashboard/dashboard_view_model.dart | 13 + .../node_create_or_edit_view_model.dart | 23 +- res/values/strings_ar.arb | 6 + res/values/strings_bg.arb | 6 + res/values/strings_cs.arb | 6 + res/values/strings_de.arb | 6 + res/values/strings_en.arb | 6 + res/values/strings_es.arb | 6 + res/values/strings_fr.arb | 6 + res/values/strings_ha.arb | 6 + res/values/strings_hi.arb | 6 + res/values/strings_hr.arb | 6 + res/values/strings_id.arb | 6 + res/values/strings_it.arb | 6 + res/values/strings_ja.arb | 6 + res/values/strings_ko.arb | 8 +- res/values/strings_my.arb | 6 + res/values/strings_nl.arb | 6 + res/values/strings_pl.arb | 6 + res/values/strings_pt.arb | 6 + res/values/strings_ru.arb | 6 + res/values/strings_th.arb | 6 + res/values/strings_tl.arb | 6 + res/values/strings_tr.arb | 6 + res/values/strings_uk.arb | 6 + res/values/strings_ur.arb | 6 + res/values/strings_yo.arb | 6 + res/values/strings_zh.arb | 6 + tool/configure.dart | 3 + 46 files changed, 881 insertions(+), 264 deletions(-) create mode 100644 cw_core/lib/n2_node.dart diff --git a/assets/nano_node_list.yml b/assets/nano_node_list.yml index 63b4baec1..2e4d1ec3c 100644 --- a/assets/nano_node_list.yml +++ b/assets/nano_node_list.yml @@ -3,4 +3,26 @@ useSSL: true is_default: true - - uri: node.perish.co:9076 \ No newline at end of file + uri: node.nautilus.io + path: /api + useSSL: true +- + uri: app.natrium.io + path: /api + useSSL: true +- + uri: rainstorm.city + path: /api + useSSL: true +- + uri: node.somenano.com + path: /proxy + useSSL: true +- + uri: nanoslo.0x.no + path: /proxy + useSSL: true +- + uri: www.bitrequest.app + port: 8020 + useSSL: true \ No newline at end of file diff --git a/cw_core/lib/n2_node.dart b/cw_core/lib/n2_node.dart new file mode 100644 index 000000000..0fad9d1b5 --- /dev/null +++ b/cw_core/lib/n2_node.dart @@ -0,0 +1,31 @@ +class N2Node { + N2Node({ + this.weight, + this.uptime, + this.score, + this.account, + this.alias, + }); + + String? uptime; + double? weight; + int? score; + String? account; + String? alias; + + factory N2Node.fromJson(Map json) => N2Node( + weight: double.tryParse((json['weight'] as num).toString()), + uptime: json['uptime'] as String?, + score: json['score'] as int?, + account: json['rep_address'] as String?, + alias: json['alias'] as String?, + ); + + Map toJson() => { + 'uptime': uptime, + 'weight': weight, + 'score': score, + 'rep_address': account, + 'alias': alias, + }; +} diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 585bc3c38..d7e91d692 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -21,6 +21,7 @@ class Node extends HiveObject with Keyable { this.trusted = false, this.socksProxyAddress, String? uri, + String? path, WalletType? type, }) { if (uri != null) { @@ -29,10 +30,14 @@ class Node extends HiveObject with Keyable { if (type != null) { this.type = type; } + if (path != null) { + this.path = path; + } } Node.fromMap(Map map) : uriRaw = map['uri'] as String? ?? '', + path = map['path'] as String? ?? '', login = map['login'] as String?, password = map['password'] as String?, useSSL = map['useSSL'] as bool?, @@ -63,6 +68,9 @@ class Node extends HiveObject with Keyable { @HiveField(6) String? socksProxyAddress; + @HiveField(7, defaultValue: '') + String? path; + bool get isSSL => useSSL ?? false; bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty; @@ -79,9 +87,9 @@ class Node extends HiveObject with Keyable { case WalletType.nano: case WalletType.banano: if (isSSL) { - return Uri.https(uriRaw, ''); + return Uri.https(uriRaw, path ?? ''); } else { - return Uri.http(uriRaw, ''); + return Uri.http(uriRaw, path ?? ''); } case WalletType.ethereum: case WalletType.polygon: @@ -103,7 +111,8 @@ class Node extends HiveObject with Keyable { other.typeRaw == typeRaw && other.useSSL == useSSL && other.trusted == trusted && - other.socksProxyAddress == socksProxyAddress); + other.socksProxyAddress == socksProxyAddress && + other.path == path); @override int get hashCode => @@ -113,7 +122,8 @@ class Node extends HiveObject with Keyable { typeRaw.hashCode ^ useSSL.hashCode ^ trusted.hashCode ^ - socksProxyAddress.hashCode; + socksProxyAddress.hashCode ^ + path.hashCode; @override dynamic get keyIndex { diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 661fbcab8..064a0bdee 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:cw_core/nano_account_info_response.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_transaction_model.dart'; import 'package:http/http.dart' as http; @@ -16,6 +17,8 @@ class NanoClient { "nano-app": "cake-wallet" }; + static const String N2_REPS_ENDPOINT = "https://rpc.nano.to"; + NanoClient() { SharedPreferences.getInstance().then((value) => prefs = value); } @@ -418,7 +421,7 @@ class NanoClient { body: jsonEncode({ "action": "account_history", "account": address, - "count": "250", // TODO: pick a number + "count": "100", // "raw": true, })); final data = await jsonDecode(response.body); @@ -434,4 +437,37 @@ class NanoClient { return []; } } + + Future> getN2Reps() async { + final response = await http.post( + Uri.parse(N2_REPS_ENDPOINT), + headers: CAKE_HEADERS, + body: jsonEncode({"action": "reps"}), + ); + try { + final List nodes = (json.decode(response.body) as List) + .map((dynamic e) => N2Node.fromJson(e as Map)) + .toList(); + return nodes; + } catch (error) { + return []; + } + } + + Future getRepScore(String rep) async { + final response = await http.post( + Uri.parse(N2_REPS_ENDPOINT), + headers: CAKE_HEADERS, + body: jsonEncode({ + "action": "rep_info", + "account": rep, + }), + ); + try { + final N2Node node = N2Node.fromJson(json.decode(response.body) as Map); + return node.score ?? 100; + } catch (error) { + return 100; + } + } } diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 1f6ec36ae..265f78eb7 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -13,6 +13,7 @@ import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_nano/file.dart'; import 'package:cw_core/nano_account.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_client.dart'; import 'package:cw_nano/nano_transaction_credentials.dart'; @@ -65,9 +66,11 @@ abstract class NanoWalletBase String? _privateKey; String? _publicAddress; String? _hexSeed; + Timer? _receiveTimer; String? _representativeAddress; - Timer? _receiveTimer; + int repScore = 100; + bool get isRepOk => repScore >= 90; late final NanoClient _client; bool _isTransactionUpdating; @@ -375,7 +378,7 @@ abstract class NanoWalletBase final data = json.decode(jsonSource) as Map; final mnemonic = data['mnemonic'] as String; - + final balance = NanoBalance.fromRawString( currentBalance: data['currentBalance'] as String? ?? "0", receivableBalance: data['receivableBalance'] as String? ?? "0", @@ -429,6 +432,8 @@ abstract class NanoWalletBase _representativeAddress = await _client.getRepFromPrefs(); throw Exception("Failed to get representative address $e"); } + + repScore = await _client.getRepScore(_representativeAddress!); } Future regenerateAddress() async { @@ -465,6 +470,10 @@ abstract class NanoWalletBase } } + Future> getN2Reps() async { + return _client.getN2Reps(); + } + Future? updateBalance() async => await _updateBalance(); @override diff --git a/lib/core/node_address_validator.dart b/lib/core/node_address_validator.dart index 0e034dabc..c1fe4ba91 100644 --- a/lib/core/node_address_validator.dart +++ b/lib/core/node_address_validator.dart @@ -8,3 +8,8 @@ class NodeAddressValidator extends TextValidator { pattern: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$|^[0-9a-zA-Z.\-]+\$'); } + +class NodePathValidator extends TextValidator { + NodePathValidator() + : super(errorMessage: S.current.error_text_node_address, pattern: '^([/0-9a-zA-Z.\-]+)?\$'); +} diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 9a2db56af..a0f570e95 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -216,6 +216,10 @@ Future defaultSettingsMigration( await disableServiceStatusFiatDisabled(sharedPreferences); break; + case 31: + await updateNanoNodeList(nodes: nodes); + break; + default: break; } @@ -230,9 +234,35 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future updateNanoNodeList({required Box nodes}) async { + final nodeList = await loadDefaultNanoNodes(); + var listOfNewEndpoints = [ + "app.natrium.io", + "rainstorm.city", + "node.somenano.com", + "nanoslo.0x.no", + "www.bitrequest.app", + ]; + // add new nodes: + for (final node in nodeList) { + if (listOfNewEndpoints.contains(node.uriRaw)) { + await nodes.add(node); + } + } + + // update the nautilus node: + final nautilusNode = + nodes.values.firstWhereOrNull((element) => element.uriRaw == "node.perish.co"); + if (nautilusNode != null) { + nautilusNode.uriRaw = "node.nautilus.io"; + nautilusNode.path = "/api"; + nautilusNode.useSSL = true; + await nautilusNode.save(); + } +} + Future disableServiceStatusFiatDisabled(SharedPreferences sharedPreferences) async { - final currentFiat = - await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; + final currentFiat = await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; if (currentFiat == -1 || currentFiat == FiatApiMode.enabled.raw) { return; } diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 80a7acba1..f512d6b72 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -45,6 +45,7 @@ class PreferencesKey { static const customBitcoinFeeRate = 'custom_electrum_fee_rate'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; + static const shouldShowRepWarning = 'should_show_rep_warning'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; static const syncModeKey = 'sync_mode'; static const syncAllKey = 'sync_all'; diff --git a/lib/main.dart b/lib/main.dart index 6868348f6..b80c9eb85 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 30, + initialMigrationVersion: 31, ); } diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 06ebf60c2..5896f7c26 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -186,6 +186,16 @@ class CWNano extends Nano { String getRepresentative(Object wallet) { return (wallet as NanoWallet).representative; } + + @override + Future> getN2Reps(Object wallet) async { + return (wallet as NanoWallet).getN2Reps(); + } + + @override + bool isRepOk(Object wallet) { + return (wallet as NanoWallet).isRepOk; + } } class CWNanoUtil extends NanoUtil { diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 0b7596469..a2ad3fb80 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; +import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; import 'package:cake_wallet/src/widgets/introducing_card.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; @@ -183,6 +184,22 @@ class CryptoBalanceWidget extends StatelessWidget { return Container(); }, ), + Observer(builder: (_) { + if (!dashboardViewModel.showRepWarning) { + return const SizedBox(); + } + return Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + title: S.current.rep_warning, + subTitle: S.current.rep_warning_sub, + onTap: () => Navigator.of(context).pushNamed(Routes.changeRep), + onClose: () { + dashboardViewModel.settingsStore.shouldShowRepWarning = false; + }, + ), + ); + }), Observer( builder: (_) { return ListView.separated( diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart index a625f7e29..9f71bb59c 100644 --- a/lib/src/screens/nano/nano_change_rep_page.dart +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -5,10 +5,12 @@ 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/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_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'; +import 'package:cw_core/n2_node.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -21,9 +23,7 @@ class NanoChangeRepPage extends BasePage { : _wallet = wallet, _settingsStore = settingsStore, _addressController = TextEditingController(), - _formKey = GlobalKey() { - _addressController.text = nano!.getRepresentative(wallet); - } + _formKey = GlobalKey() {} final TextEditingController _addressController; final WalletBase _wallet; @@ -34,105 +34,314 @@ class NanoChangeRepPage extends BasePage { @override String get title => S.current.change_rep; + N2Node getCurrentRepNode(List nodes) { + final currentRepAccount = nano!.getRepresentative(_wallet); + final currentNode = nodes.firstWhere( + (node) => node.account == currentRepAccount, + orElse: () => N2Node( + account: currentRepAccount, + alias: currentRepAccount, + score: 0, + uptime: "???", + weight: 0, + ), + ); + + return currentNode; + } + @override Widget body(BuildContext context) { return Form( key: _formKey, - child: Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24.0), - content: Container( - child: Column( - children: [ - Row( - children: [ - Expanded( - child: AddressTextField( - controller: _addressController, - 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), + child: FutureBuilder( + future: nano!.getN2Reps(_wallet), + builder: (context, snapshot) { + if (snapshot.data == null) { + return SizedBox(); + } + + return Container( + padding: EdgeInsets.only(left: 24, right: 24), + child: ScrollableWithBottomSection( + topSectionPadding: EdgeInsets.only(bottom: 24), + topSection: Column( + children: [ + Row( + children: [ + Expanded( + child: AddressTextField( + controller: _addressController, + 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), + ), + ) + ], + ), + Column( + children: [ + Container( + margin: EdgeInsets.only(top: 12), + child: Text( + S.current.nano_current_rep, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ), ), - ) - ], + _buildSingleRepresentative( + context, + getCurrentRepNode(snapshot.data as List), + isList: false, + ), + Divider(height: 20), + Container( + margin: EdgeInsets.only(top: 12), + child: Text( + S.current.nano_pick_new_rep, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ), + ), + ], + ), + ], + ), + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + child: Column( + children: _getRepresentativeWidgets(context, snapshot.data as List), + ), + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24), + bottomSection: Observer( + builder: (_) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( + onPressed: () => _onSubmit(context), + text: S.of(context).change, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + )), + ], + )), + ), + ); + }, + ), + ); + } + + Future _onSubmit(BuildContext context) async { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { + return; + } + + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_rep, + alertContent: S.of(context).change_rep_message, + rightButtonText: S.of(context).change, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + try { + _settingsStore.defaultNanoRep = _addressController.text; + + await nano!.changeRep(_wallet, _addressController.text); + + // reset this flag whenever we successfully change reps: + _settingsStore.shouldShowRepWarning = true; + + 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, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: e.toString(), + buttonText: S.of(context).ok, + buttonAction: () => Navigator.pop(context)); + }); + throw e; + } + } + } + + List _getRepresentativeWidgets(BuildContext context, List? list) { + if (list == null) { + return []; + } + final List ret = []; + for (final N2Node node in list) { + if (node.alias != null && node.alias!.trim().isNotEmpty) { + ret.add(_buildSingleRepresentative(context, node)); + } + } + return ret; + } + + Widget _buildSingleRepresentative(BuildContext context, N2Node rep, {bool isList = true}) { + return Column( + children: [ + if (isList) + Divider( + height: 2, + ), + TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + ), + onPressed: () async { + if (!isList) { + return; + } + _addressController.text = rep.account!; + }, + child: Container( + margin: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsetsDirectional.only(start: 24), + width: MediaQuery.of(context).size.width * 0.50, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _sanitizeAlias(rep.alias), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontWeight: FontWeight.w700, + fontSize: 18, + ), + ), + Container( + margin: const EdgeInsets.only(top: 7), + child: RichText( + text: TextSpan( + text: "${S.current.voting_weight}: ${rep.weight.toString()}%", + style: TextStyle( + color: + Theme.of(context).extension()!.secondaryTextColor, + fontWeight: FontWeight.w700, + fontSize: 14.0, + ), + ), + ), + ), + Container( + margin: const EdgeInsets.only(top: 4), + child: RichText( + text: TextSpan( + text: '', + children: [ + TextSpan( + text: "${S.current.uptime}: ", + style: TextStyle( + color: Theme.of(context) + .extension()! + .secondaryTextColor, + fontWeight: FontWeight.w700, + fontSize: 14, + ), + ), + TextSpan( + text: rep.uptime, + style: TextStyle( + color: Theme.of(context) + .extension()! + .secondaryTextColor, + fontWeight: FontWeight.w900, + fontSize: 14, + ), + ), + ], + ), + ), + ), + ], + ), + ), + Container( + margin: const EdgeInsetsDirectional.only(end: 24, start: 14), + child: Stack( + children: [ + Icon( + Icons.verified, + color: Theme.of(context).primaryColor, + size: 50, + ), + Positioned.fill( + child: Container( + margin: EdgeInsets.all(13), + color: Theme.of(context).primaryColor, + ), + ), + Container( + alignment: const AlignmentDirectional(-0.03, 0.03), + width: 50, + height: 50, + child: Text( + (rep.score).toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 13, + fontWeight: FontWeight.w800, + ), + ), + ), + ], + ), ), ], ), ), - bottomSectionPadding: EdgeInsets.only(bottom: 24), - bottomSection: Observer( - builder: (_) => Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Container( - 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) { - return AlertWithTwoActions( - alertTitle: S.of(context).change_rep, - alertContent: S.of(context).change_rep_message, - rightButtonText: S.of(context).change, - leftButtonText: S.of(context).cancel, - actionRightButton: () => Navigator.pop(context, true), - actionLeftButton: () => Navigator.pop(context, false)); - }) ?? - false; - - if (confirmed) { - try { - _settingsStore.defaultNanoRep = _addressController.text; - - await nano!.changeRep(_wallet, _addressController.text); - - 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, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: e.toString(), - buttonText: S.of(context).ok, - buttonAction: () => Navigator.pop(context)); - }); - throw e; - } - } - }, - text: S.of(context).change, - color: Theme.of(context).primaryColor, - textColor: Colors.white, - ), - )), - ], - )), ), - ), + ], ); } + + String _sanitizeAlias(String? alias) { + if (alias != null) { + return alias.replaceAll(RegExp(r'[^a-zA-Z_.!?_;:-]'), ''); + } + return ''; + } } 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 50c1c3be5..53c34f302 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -18,6 +18,7 @@ class NodeCreateOrEditPage extends BasePage { NodeCreateOrEditPage({required this.nodeCreateOrEditViewModel,this.editingNode, this.isSelected}) : _formKey = GlobalKey(), _addressController = TextEditingController(), + _pathController = TextEditingController(), _portController = TextEditingController(), _loginController = TextEditingController(), _passwordController = TextEditingController() { @@ -49,6 +50,8 @@ class NodeCreateOrEditPage extends BasePage { _addressController.addListener( () => nodeCreateOrEditViewModel.address = _addressController.text); + _pathController.addListener( + () => nodeCreateOrEditViewModel.path = _pathController.text); _portController.addListener( () => nodeCreateOrEditViewModel.port = _portController.text); _loginController.addListener( @@ -59,6 +62,7 @@ class NodeCreateOrEditPage extends BasePage { final GlobalKey _formKey; final TextEditingController _addressController; + final TextEditingController _pathController; final TextEditingController _portController; final TextEditingController _loginController; final TextEditingController _passwordController; diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart index ab8dcafdf..e8c4b0ab3 100644 --- a/lib/src/screens/nodes/widgets/node_form.dart +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -16,13 +16,15 @@ class NodeForm extends StatelessWidget { required this.formKey, this.editingNode, }) : _addressController = TextEditingController(text: editingNode?.uri.host.toString()), + _pathController = TextEditingController(text: editingNode?.path.toString()), _portController = TextEditingController(text: editingNode?.uri.port.toString()), _loginController = TextEditingController(text: editingNode?.login), _passwordController = TextEditingController(text: editingNode?.password), - _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress){ + _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress) { if (editingNode != null) { nodeViewModel ..setAddress((editingNode!.uri.host.toString())) + ..setPath((editingNode!.path.toString())) ..setPort((editingNode!.uri.port.toString())) ..setPassword((editingNode!.password ?? '')) ..setLogin((editingNode!.login ?? '')) @@ -57,10 +59,12 @@ class NodeForm extends StatelessWidget { }); _addressController.addListener(() => nodeViewModel.address = _addressController.text); + _pathController.addListener(() => nodeViewModel.path = _pathController.text); _portController.addListener(() => nodeViewModel.port = _portController.text); _loginController.addListener(() => nodeViewModel.login = _loginController.text); _passwordController.addListener(() => nodeViewModel.password = _passwordController.text); - _socksAddressController.addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); + _socksAddressController + .addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); } final NodeCreateOrEditViewModel nodeViewModel; @@ -68,6 +72,7 @@ class NodeForm extends StatelessWidget { final Node? editingNode; final TextEditingController _addressController; + final TextEditingController _pathController; final TextEditingController _portController; final TextEditingController _loginController; final TextEditingController _passwordController; @@ -91,6 +96,18 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _pathController, + hintText: "/path", + validator: NodePathValidator(), + ), + ) + ], + ), + SizedBox(height: 10.0), Row( children: [ Expanded( @@ -103,6 +120,26 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.useSSL, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) => nodeViewModel.useSSL = value, + caption: S.of(context).use_ssl, + ), + ) + ], + ), + ), + SizedBox(height: 10.0), if (nodeViewModel.hasAuthCredentials) ...[ Row( children: [ @@ -123,25 +160,6 @@ class NodeForm extends StatelessWidget { )) ], ), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeViewModel.useSSL, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) => nodeViewModel.useSSL = value, - caption: S.of(context).use_ssl, - ), - ) - ], - ), - ), Padding( padding: EdgeInsets.only(top: 20), child: Row( @@ -163,44 +181,44 @@ class NodeForm extends StatelessWidget { ), Observer( builder: (_) => Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - StandardCheckbox( - value: nodeViewModel.useSocksProxy, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) { - if (!value) { - _socksAddressController.text = ''; - } - nodeViewModel.useSocksProxy = value; - }, - caption: 'SOCKS Proxy', - ), - ], - ), - ), - if (nodeViewModel.useSocksProxy) ...[ - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( + children: [ + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + StandardCheckbox( + value: nodeViewModel.useSocksProxy, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) { + if (!value) { + _socksAddressController.text = ''; + } + nodeViewModel.useSocksProxy = value; + }, + caption: 'SOCKS Proxy', + ), + ], + ), + ), + if (nodeViewModel.useSocksProxy) ...[ + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( controller: _socksAddressController, hintText: '[:]', validator: SocksProxyNodeAddressValidator(), )) - ], - ), - ] - ], - )), + ], + ), + ] + ], + )), ] ], ), diff --git a/lib/src/widgets/dashboard_card_widget.dart b/lib/src/widgets/dashboard_card_widget.dart index b3f92123a..74f2d598b 100644 --- a/lib/src/widgets/dashboard_card_widget.dart +++ b/lib/src/widgets/dashboard_card_widget.dart @@ -4,15 +4,15 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class DashBoardRoundedCardWidget extends StatelessWidget { - - DashBoardRoundedCardWidget({ required this.onTap, required this.title, required this.subTitle, + this.onClose, }); final VoidCallback onTap; + final VoidCallback? onClose; final String title; final String subTitle; @@ -26,7 +26,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget { child: Stack( children: [ Container( - padding: EdgeInsets.all(20), + padding: EdgeInsets.fromLTRB(20, 20, 40, 20), width: double.infinity, decoration: BoxDecoration( color: Theme.of(context).extension()!.syncedBackgroundColor, @@ -35,32 +35,40 @@ class DashBoardRoundedCardWidget extends StatelessWidget { color: Theme.of(context).extension()!.cardBorderColor, ), ), - child: - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - color: Theme.of(context).extension()!.cardTextColor, - fontSize: 24, - fontWeight: FontWeight.w900, - ), - ), - SizedBox(height: 5), - Text( - subTitle, - style: TextStyle( - color: Theme.of(context).extension()!.cardTextColor, - fontWeight: FontWeight.w500, - fontFamily: 'Lato'), - ) - ], + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + color: Theme.of(context).extension()!.cardTextColor, + fontSize: 24, + fontWeight: FontWeight.w900, + ), ), + SizedBox(height: 5), + Text( + subTitle, + style: TextStyle( + color: Theme.of(context).extension()!.cardTextColor, + fontWeight: FontWeight.w500, + fontFamily: 'Lato'), + ) + ], + ), ), + if (onClose != null) + Positioned( + top: 10, + right: 10, + child: IconButton( + icon: Icon(Icons.close), + onPressed: onClose, + color: Theme.of(context).extension()!.cardTextColor, + ), + ), ], ), ); } } - diff --git a/lib/src/widgets/scollable_with_bottom_section.dart b/lib/src/widgets/scollable_with_bottom_section.dart index 2487e6130..e15be610e 100644 --- a/lib/src/widgets/scollable_with_bottom_section.dart +++ b/lib/src/widgets/scollable_with_bottom_section.dart @@ -2,16 +2,21 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ScrollableWithBottomSection extends StatefulWidget { - ScrollableWithBottomSection( - {required this.content, - required this.bottomSection, - this.contentPadding, - this.bottomSectionPadding}); + ScrollableWithBottomSection({ + required this.content, + required this.bottomSection, + this.topSection, + this.contentPadding, + this.bottomSectionPadding, + this.topSectionPadding, + }); final Widget content; final Widget bottomSection; + final Widget? topSection; final EdgeInsets? contentPadding; final EdgeInsets? bottomSectionPadding; + final EdgeInsets? topSectionPadding; @override ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState(); @@ -22,6 +27,12 @@ class ScrollableWithBottomSectionState extends State nodes, required Map powNodes, required this.shouldShowYatPopup, + required this.shouldShowRepWarning, required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, required this.pinTimeOutDuration, @@ -225,6 +226,9 @@ abstract class SettingsStoreBase with Store { (bool shouldShowYatPopup) => sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup)); + reaction((_) => shouldShowRepWarning, + (bool val) => sharedPreferences.setBool(PreferencesKey.shouldShowRepWarning, val)); + defaultBuyProviders.observe((change) { final String key = 'buyProvider_${change.key.toString()}'; if (change.newValue != null) { @@ -536,6 +540,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldShowYatPopup; + @observable + bool shouldShowRepWarning; + @observable bool shouldShowMarketPlaceInDashboard; @@ -878,6 +885,8 @@ abstract class SettingsStoreBase with Store { final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; + final shouldShowRepWarning = + sharedPreferences.getBool(PreferencesKey.shouldShowRepWarning) ?? true; final generateSubaddresses = sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); @@ -1034,75 +1043,77 @@ abstract class SettingsStoreBase with Store { ''; return SettingsStore( - secureStorage: secureStorage, - sharedPreferences: sharedPreferences, - initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, - nodes: nodes, - powNodes: powNodes, - appVersion: packageInfo.version, - deviceName: deviceName, - isBitcoinBuyEnabled: isBitcoinBuyEnabled, - initialFiatCurrency: currentFiatCurrency, - initialBalanceDisplayMode: currentBalanceDisplayMode, - initialSaveRecipientAddress: shouldSaveRecipientAddress, - initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, - initialMoneroSeedType: moneroSeedType, - initialAppSecure: isAppSecure, - initialDisableBuy: disableBuy, - initialDisableSell: disableSell, - initialDisableBulletin: disableBulletin, - initialWalletListOrder: walletListOrder, - initialWalletListAscending: walletListAscending, - initialFiatMode: currentFiatApiMode, - initialAllowBiometricalAuthentication: allowBiometricalAuthentication, - initialCake2FAPresetOptions: selectedCake2FAPreset, - initialUseTOTP2FA: useTOTP2FA, - initialTotpSecretKey: totpSecretKey, - initialFailedTokenTrial: tokenTrialNumber, - initialExchangeStatus: exchangeStatus, - initialTheme: savedTheme, - actionlistDisplayMode: actionListDisplayMode, - initialPinLength: pinLength, - pinTimeOutDuration: pinCodeTimeOutDuration, - seedPhraseLength: seedPhraseWordCount, - initialLanguageCode: savedLanguageCode, - sortBalanceBy: sortBalanceBy, - pinNativeTokenAtTop: pinNativeTokenAtTop, - useEtherscan: useEtherscan, - usePolygonScan: usePolygonScan, - defaultNanoRep: defaultNanoRep, - defaultBananoRep: defaultBananoRep, - lookupsTwitter: lookupsTwitter, - lookupsMastodon: lookupsMastodon, - lookupsYatService: lookupsYatService, - lookupsUnstoppableDomains: lookupsUnstoppableDomains, - lookupsOpenAlias: lookupsOpenAlias, - lookupsENS: lookupsENS, - customBitcoinFeeRate: customBitcoinFeeRate, - initialMoneroTransactionPriority: moneroTransactionPriority, - initialBitcoinTransactionPriority: bitcoinTransactionPriority, - initialHavenTransactionPriority: havenTransactionPriority, - initialLitecoinTransactionPriority: litecoinTransactionPriority, - initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, - initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, - initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, - initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, - initialShouldRequireTOTP2FAForSendsToInternalWallets: - shouldRequireTOTP2FAForSendsToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToInternalWallets: - shouldRequireTOTP2FAForExchangesToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToExternalWallets: - shouldRequireTOTP2FAForExchangesToExternalWallets, - initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, - initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, - initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: - shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - initialEthereumTransactionPriority: ethereumTransactionPriority, - initialPolygonTransactionPriority: polygonTransactionPriority, - backgroundTasks: backgroundTasks, - initialSyncMode: savedSyncMode, - initialSyncAll: savedSyncAll, - shouldShowYatPopup: shouldShowYatPopup); + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, + nodes: nodes, + powNodes: powNodes, + appVersion: packageInfo.version, + deviceName: deviceName, + isBitcoinBuyEnabled: isBitcoinBuyEnabled, + initialFiatCurrency: currentFiatCurrency, + initialBalanceDisplayMode: currentBalanceDisplayMode, + initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, + initialMoneroSeedType: moneroSeedType, + initialAppSecure: isAppSecure, + initialDisableBuy: disableBuy, + initialDisableSell: disableSell, + initialDisableBulletin: disableBulletin, + initialWalletListOrder: walletListOrder, + initialWalletListAscending: walletListAscending, + initialFiatMode: currentFiatApiMode, + initialAllowBiometricalAuthentication: allowBiometricalAuthentication, + initialCake2FAPresetOptions: selectedCake2FAPreset, + initialUseTOTP2FA: useTOTP2FA, + initialTotpSecretKey: totpSecretKey, + initialFailedTokenTrial: tokenTrialNumber, + initialExchangeStatus: exchangeStatus, + initialTheme: savedTheme, + actionlistDisplayMode: actionListDisplayMode, + initialPinLength: pinLength, + pinTimeOutDuration: pinCodeTimeOutDuration, + seedPhraseLength: seedPhraseWordCount, + initialLanguageCode: savedLanguageCode, + sortBalanceBy: sortBalanceBy, + pinNativeTokenAtTop: pinNativeTokenAtTop, + useEtherscan: useEtherscan, + usePolygonScan: usePolygonScan, + defaultNanoRep: defaultNanoRep, + defaultBananoRep: defaultBananoRep, + lookupsTwitter: lookupsTwitter, + lookupsMastodon: lookupsMastodon, + lookupsYatService: lookupsYatService, + lookupsUnstoppableDomains: lookupsUnstoppableDomains, + lookupsOpenAlias: lookupsOpenAlias, + lookupsENS: lookupsENS, + customBitcoinFeeRate: customBitcoinFeeRate, + initialMoneroTransactionPriority: moneroTransactionPriority, + initialBitcoinTransactionPriority: bitcoinTransactionPriority, + initialHavenTransactionPriority: havenTransactionPriority, + initialLitecoinTransactionPriority: litecoinTransactionPriority, + initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, + initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, + initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, + initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, + initialShouldRequireTOTP2FAForSendsToInternalWallets: + shouldRequireTOTP2FAForSendsToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToInternalWallets: + shouldRequireTOTP2FAForExchangesToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToExternalWallets: + shouldRequireTOTP2FAForExchangesToExternalWallets, + initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, + initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, + initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: + shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + initialEthereumTransactionPriority: ethereumTransactionPriority, + initialPolygonTransactionPriority: polygonTransactionPriority, + backgroundTasks: backgroundTasks, + initialSyncMode: savedSyncMode, + initialSyncAll: savedSyncAll, + shouldShowYatPopup: shouldShowYatPopup, + shouldShowRepWarning: shouldShowRepWarning, + ); } Future reload({required Box nodeSource}) async { @@ -1198,6 +1209,8 @@ abstract class SettingsStoreBase with Store { languageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ?? languageCode; shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? shouldShowYatPopup; + shouldShowRepWarning = + sharedPreferences.getBool(PreferencesKey.shouldShowRepWarning) ?? shouldShowRepWarning; sortBalanceBy = SortBalanceBy .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 66d179523..ef43ddf40 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/entities/service_status.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; @@ -370,6 +371,18 @@ abstract class DashboardViewModelBase with Store { @computed bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type == WalletType.banano; + bool get showRepWarning { + if (wallet.type != WalletType.nano) { + return false; + } + + if (!settingsStore.shouldShowRepWarning) { + return false; + } + + return !nano!.isRepOk(wallet); + } + Future reconnect() async { final node = appStore.settingsStore.getCurrentNode(wallet.type); await wallet.connectToNode(node: node); diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index e323268a0..283a32cbf 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -12,16 +12,15 @@ import 'package:permission_handler/permission_handler.dart'; part 'node_create_or_edit_view_model.g.dart'; -class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase - with _$NodeCreateOrEditViewModel; +class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel; abstract class NodeCreateOrEditViewModelBase with Store { - NodeCreateOrEditViewModelBase( - this._nodeSource, this._walletType, this._settingsStore) + NodeCreateOrEditViewModelBase(this._nodeSource, this._walletType, this._settingsStore) : state = InitialExecutionState(), connectionState = InitialExecutionState(), useSSL = false, address = '', + path = '', port = '', login = '', password = '', @@ -35,6 +34,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { @observable String address; + @observable + String path; + @observable String port; @@ -84,6 +86,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { @action void reset() { address = ''; + path = ''; port = ''; login = ''; password = ''; @@ -99,6 +102,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { @action void setAddress(String val) => address = val; + @action + void setPath(String val) => path = val; + @action void setLogin(String val) => login = val; @@ -121,6 +127,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future save({Node? editingNode, bool saveAsCurrent = false}) async { final node = Node( uri: uri, + path: path, type: _walletType, login: login, password: password, @@ -151,6 +158,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future connect() async { final node = Node( uri: uri, + path: path, type: _walletType, login: login, password: password, @@ -183,7 +191,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future scanQRCodeForNewNode(BuildContext context) async { try { bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; String code = await presentQRScanner(); @@ -198,7 +206,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { } final userInfo = uri.userInfo.split(':'); - + if (userInfo.length < 2) { throw Exception('Unexpected scan QR code value: Value is invalid'); } @@ -207,8 +215,11 @@ abstract class NodeCreateOrEditViewModelBase with Store { final rpcPassword = userInfo[1]; final ipAddress = uri.host; final port = uri.port.toString(); + final path = uri.path; + setAddress(ipAddress); + setPath(path); setPassword(rpcPassword); setLogin(rpcUser); setPort(port); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 6b3aae14e..f5b2dd5dd 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", "more_options": "المزيد من الخيارات", "name": "ﻢﺳﺍ", + "nano_current_rep": "الممثل الحالي", + "nano_pick_new_rep": "اختر ممثلًا جديدًا", "narrow": "ضيق", "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", "new_node_testing": "تجربة العقدة الجديدة", @@ -465,6 +467,8 @@ "remove_node": "إزالة العقدة", "remove_node_message": "هل أنت متأكد أنك تريد إزالة العقدة المحددة؟", "rename": "إعادة تسمية", + "rep_warning": "تحذير تمثيلي", + "rep_warning_sub": "لا يبدو أن ممثلك في وضع جيد. اضغط هنا لاختيار واحدة جديدة", "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "تفاصيل العملات الغير المنفقة", "unspent_coins_title": "العملات الغير المنفقة", "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", + "uptime": "مدة التشغيل", "upto": "حتى ${value}", "use": "التبديل إلى", "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.", @@ -758,6 +763,7 @@ "view_key_private": "مفتاح العرض (خاص)", "view_key_public": "مفتاح العرض (عام)", "view_transaction_on": "عرض العملية على", + "voting_weight": "وزن التصويت", "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", "wallet_keys": "سييد المحفظة / المفاتيح", "wallet_list_create_new_wallet": "إنشاء محفظة جديدة", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 30d9945d1..511a04e39 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", "more_options": "Още настройки", "name": "Име", + "nano_current_rep": "Настоящ представител", + "nano_pick_new_rep": "Изберете нов представител", "narrow": "Тесен", "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", "new_node_testing": "Тестване на нов node", @@ -465,6 +467,8 @@ "remove_node": "Премахни node", "remove_node_message": "Сигурни ли сте, че искате да премахнете избрания node?", "rename": "Промяна на името", + "rep_warning": "Представително предупреждение", + "rep_warning_sub": "Вашият представител изглежда не е в добро състояние. Докоснете тук, за да изберете нов", "require_for_adding_contacts": "Изисква се за добавяне на контакти", "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", "require_for_assessing_wallet": "Изискване за достъп до портфейла", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Подробности за неизползваните монети", "unspent_coins_title": "Неизползвани монети", "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", + "uptime": "Време за работа", "upto": "до ${value}", "use": "Смяна на ", "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.", @@ -758,6 +763,7 @@ "view_key_private": "View key (таен)", "view_key_public": "View key (публичен)", "view_transaction_on": "Вижте транзакция на ", + "voting_weight": "Тегло на гласуване", "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите", "wallet_keys": "Seed/keys на портфейла", "wallet_list_create_new_wallet": "Създаване на нов портфейл", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 577cd9813..8457de560 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", "more_options": "Více možností", "name": "název", + "nano_current_rep": "Současný zástupce", + "nano_pick_new_rep": "Vyberte nového zástupce", "narrow": "Úzký", "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", "new_node_testing": "Testování nového uzlu", @@ -465,6 +467,8 @@ "remove_node": "Odstranit uzel", "remove_node_message": "Opravdu chcete odstranit označený uzel?", "rename": "Přejmenovat", + "rep_warning": "Reprezentativní varování", + "rep_warning_sub": "Zdá se, že váš zástupce není v dobrém stavu. Klepnutím zde vyberte nový", "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Podrobnosti o neutracených mincích", "unspent_coins_title": "Neutracené mince", "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", + "uptime": "Uptime", "upto": "až ${value}", "use": "Přepnout na ", "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.", @@ -758,6 +763,7 @@ "view_key_private": "Klíč pro zobrazení (soukromý)", "view_key_public": "Klíč pro zobrazení (veřejný)", "view_transaction_on": "Zobrazit transakci na ", + "voting_weight": "Hlasová váha", "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí", "wallet_keys": "Seed/klíče peněženky", "wallet_list_create_new_wallet": "Vytvořit novou peněženku", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f0ba70c84..7caf82efa 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "more_options": "Weitere Optionen", "name": "Name", + "nano_current_rep": "Aktueller Vertreter", + "nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus", "narrow": "Eng", "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", "new_node_testing": "Neuen Knoten testen", @@ -466,6 +468,8 @@ "remove_node": "Knoten entfernen", "remove_node_message": "Möchten Sie den ausgewählten Knoten wirklich entfernen?", "rename": "Umbenennen", + "rep_warning": "Repräsentative Warnung", + "rep_warning_sub": "Ihr Vertreter scheint nicht gut zu sein. Tippen Sie hier, um eine neue auszuwählen", "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Details zu nicht ausgegebenen Coins", "unspent_coins_title": "Nicht ausgegebene Coins", "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", + "uptime": "Betriebszeit", "upto": "bis zu ${value}", "use": "Wechsel zu ", "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.", @@ -760,6 +765,7 @@ "view_key_private": "View Key (geheim)", "view_key_public": "View Key (öffentlich)", "view_transaction_on": "Anzeigen der Transaktion auf ", + "voting_weight": "Stimmgewicht", "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird", "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", "wallet_keys": "Wallet-Seed/-Schlüssel", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f8bd6b3a2..e75bda358 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "more_options": "More Options", "name": "Name", + "nano_current_rep": "Current Representative", + "nano_pick_new_rep": "Pick a new representative", "narrow": "Narrow", "new_first_wallet_text": "Keep your crypto safe, piece of cake", "new_node_testing": "New node testing", @@ -465,6 +467,8 @@ "remove_node": "Remove node", "remove_node_message": "Are you sure that you want to remove selected node?", "rename": "Rename", + "rep_warning": "Representative Warning", + "rep_warning_sub": "Your representative does not appear to be in good standing. Tap here to select a new one", "require_for_adding_contacts": "Require for adding contacts", "require_for_all_security_and_backup_settings": "Require for all security and backup settings", "require_for_assessing_wallet": "Require for accessing wallet", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Unspent coins details", "unspent_coins_title": "Unspent coins", "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", + "uptime": "Uptime", "upto": "up to ${value}", "use": "Switch to ", "use_card_info_three": "Use the digital card online or with contactless payment methods.", @@ -758,6 +763,7 @@ "view_key_private": "View key (private)", "view_key_public": "View key (public)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Voting Weight", "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history", "wallet_keys": "Wallet seed/keys", "wallet_list_create_new_wallet": "Create New Wallet", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index cf70a2c2d..c8a56bc66 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", "more_options": "Más Opciones", "name": "Nombre", + "nano_current_rep": "Representante actual", + "nano_pick_new_rep": "Elija un nuevo representante", "narrow": "Angosto", "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", "new_node_testing": "Prueba de nuevos nodos", @@ -466,6 +468,8 @@ "remove_node": "Eliminar nodo", "remove_node_message": "¿Está seguro de que desea eliminar el nodo seleccionado?", "rename": "Rebautizar", + "rep_warning": "Advertencia representativa", + "rep_warning_sub": "Su representante no parece estar en buena posición. Toque aquí para seleccionar uno nuevo", "require_for_adding_contacts": "Requerido para agregar contactos", "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", "require_for_assessing_wallet": "Requerido para acceder a la billetera", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Detalles de monedas no gastadas", "unspent_coins_title": "Monedas no gastadas", "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", + "uptime": "Tiempo de actividad", "upto": "hasta ${value}", "use": "Utilizar a ", "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.", @@ -759,6 +764,7 @@ "view_key_private": "View clave (privado)", "view_key_public": "View clave (público)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso de votación", "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones.", "wallet_keys": "Billetera semilla/claves", "wallet_list_create_new_wallet": "Crear nueva billetera", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d21e21dae..bbd2bde2b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", "more_options": "Plus d'options", "name": "Nom", + "nano_current_rep": "Représentant actuel", + "nano_pick_new_rep": "Choisissez un nouveau représentant", "narrow": "Étroit", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "new_node_testing": "Test du nouveau nœud", @@ -465,6 +467,8 @@ "remove_node": "Supprimer le nœud", "remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", "rename": "Renommer", + "rep_warning": "Avertissement représentatif", + "rep_warning_sub": "Votre représentant ne semble pas être en règle. Appuyez ici pour en sélectionner un nouveau", "require_for_adding_contacts": "Requis pour ajouter des contacts", "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Détails des pièces (coins) non dépensées", "unspent_coins_title": "Pièces (coins) non dépensées", "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", + "uptime": "Durée de la baisse", "upto": "jusqu'à ${value}", "use": "Changer vers code PIN à ", "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.", @@ -758,6 +763,7 @@ "view_key_private": "Clef d'audit (view key) (privée)", "view_key_public": "Clef d'audit (view key) (publique)", "view_transaction_on": "Voir la Transaction sur ", + "voting_weight": "Poids de vote", "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions.", "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", "wallet_list_create_new_wallet": "Créer un Nouveau Portefeuille (Wallet)", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 35a6be1b8..a38f04fa4 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", "more_options": "Ƙarin Zaɓuɓɓuka", "name": "Suna", + "nano_current_rep": "Wakilin Yanzu", + "nano_pick_new_rep": "Dauki sabon wakili", "narrow": "kunkuntar", "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", "new_node_testing": "Sabbin gwajin kumburi", @@ -467,6 +469,8 @@ "remove_node": "Cire node", "remove_node_message": "Kuna tabbatar kuna so ku cire wannan node?", "rename": "Sake suna", + "rep_warning": "Gargadi Wakilin", + "rep_warning_sub": "Wakilinku bai bayyana ya kasance cikin kyakkyawan yanayi ba. Matsa nan don zaɓar sabon", "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", "require_for_assessing_wallet": "Bukatar samun damar walat", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Bayanan tsabar kudi da ba a kashe ba", "unspent_coins_title": "Tsabar da ba a kashe ba", "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", + "uptime": "Sama", "upto": "har zuwa ${value}", "use": "Canja zuwa", "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.", @@ -760,6 +765,7 @@ "view_key_private": "Duba maɓallin (maɓallin kalmar sirri)", "view_key_public": "Maɓallin Duba (maɓallin jama'a)", "view_transaction_on": "Dubo aikace-aikacen akan", + "voting_weight": "Nauyi mai nauyi", "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala", "wallet_keys": "Iri/maɓalli na walat", "wallet_list_create_new_wallet": "Ƙirƙiri Sabon Wallet", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a6bcab4ab..0131baa8b 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", "more_options": "और विकल्प", "name": "नाम", + "nano_current_rep": "वर्तमान प्रतिनिधि", + "nano_pick_new_rep": "एक नया प्रतिनिधि चुनें", "narrow": "सँकरा", "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", "new_node_testing": "नई नोड परीक्षण", @@ -467,6 +469,8 @@ "remove_node": "नोड निकालें", "remove_node_message": "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?", "rename": "नाम बदलें", + "rep_warning": "प्रतिनिधि चेतावनी", + "rep_warning_sub": "आपका प्रतिनिधि अच्छी स्थिति में नहीं दिखाई देता है। एक नया चयन करने के लिए यहां टैप करें", "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "अव्ययित सिक्कों का विवरण", "unspent_coins_title": "खर्च न किए गए सिक्के", "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", + "uptime": "अपटाइम", "upto": "${value} तक", "use": "उपयोग ", "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।", @@ -760,6 +765,7 @@ "view_key_private": "कुंजी देखें(निजी)", "view_key_public": "कुंजी देखें (जनता)", "view_transaction_on": "View Transaction on ", + "voting_weight": "वोटिंग वेट", "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें", "wallet_keys": "बटुआ बीज / चाबियाँ", "wallet_list_create_new_wallet": "नया बटुआ बनाएँ", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e01857a94..af53376cd 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", "more_options": "Više opcija", "name": "Ime", + "nano_current_rep": "Trenutni predstavnik", + "nano_pick_new_rep": "Odaberite novog predstavnika", "narrow": "Usko", "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", "new_node_testing": "Provjera novog nodea", @@ -465,6 +467,8 @@ "remove_node": "Ukloni node", "remove_node_message": "Jeste li sigurni da želite ukloniti odabrani node?", "rename": "Preimenuj", + "rep_warning": "Reprezentativno upozorenje", + "rep_warning_sub": "Čini se da vaš predstavnik nije u dobrom stanju. Dodirnite ovdje za odabir novog", "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", "require_for_assessing_wallet": "Potreban za pristup novčaniku", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Nepotrošeni detalji o novčićima", "unspent_coins_title": "Nepotrošeni novčići", "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", + "uptime": "Radno vrijeme", "upto": "do ${value}", "use": "Prebaci na", "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.", @@ -758,6 +763,7 @@ "view_key_private": "View key (privatni)", "view_key_public": "View key (javni)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Težina glasanja", "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija", "wallet_keys": "Pristupni izraz/ključ novčanika", "wallet_list_create_new_wallet": "Izradi novi novčanik", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c487a6750..0e0beb57e 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", "more_options": "Opsi Lainnya", "name": "Nama", + "nano_current_rep": "Perwakilan saat ini", + "nano_pick_new_rep": "Pilih perwakilan baru", "narrow": "Sempit", "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", "new_node_testing": "Pengujian node baru", @@ -467,6 +469,8 @@ "remove_node": "Hapus node", "remove_node_message": "Apakah Anda yakin ingin menghapus node yang dipilih?", "rename": "Ganti nama", + "rep_warning": "Peringatan Perwakilan", + "rep_warning_sub": "Perwakilan Anda tampaknya tidak bereputasi baik. Ketuk di sini untuk memilih yang baru", "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", @@ -745,6 +749,7 @@ "unspent_coins_details_title": "Rincian koin yang tidak terpakai", "unspent_coins_title": "Koin yang tidak terpakai", "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", + "uptime": "Uptime", "upto": "hingga ${value}", "use": "Beralih ke ", "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.", @@ -761,6 +766,7 @@ "view_key_private": "Kunci tampilan (privat)", "view_key_public": "Kunci tampilan (publik)", "view_transaction_on": "Lihat Transaksi di ", + "voting_weight": "Berat voting", "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi", "wallet_keys": "Seed/kunci dompet", "wallet_list_create_new_wallet": "Buat Dompet Baru", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0af315426..c73fa7080 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", "more_options": "Altre opzioni", "name": "Nome", + "nano_current_rep": "Rappresentante attuale", + "nano_pick_new_rep": "Scegli un nuovo rappresentante", "narrow": "Stretto", "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", "new_node_testing": "Test novo nodo", @@ -467,6 +469,8 @@ "remove_node": "Rimuovi nodo", "remove_node_message": "Sei sicuro di voler rimuovere il nodo selezionato?", "rename": "Rinomina", + "rep_warning": "Avvertenza rappresentativa", + "rep_warning_sub": "Il tuo rappresentante non sembra essere in regola. Tocca qui per selezionarne uno nuovo", "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Dettagli sulle monete non spese", "unspent_coins_title": "Monete non spese", "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", + "uptime": "Uptime", "upto": "fino a ${value}", "use": "Passa a ", "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.", @@ -760,6 +765,7 @@ "view_key_private": "Chiave di visualizzazione (privata)", "view_key_public": "Chiave di visualizzazione (pubblica)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso di voto", "waitFewSecondForTxUpdate": "Attendi qualche secondo affinché la transazione venga riflessa nella cronologia delle transazioni", "waiting_payment_confirmation": "In attesa di conferma del pagamento", "wallet_keys": "Seme Portafoglio /chiavi", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a0b3973b2..65f2642d7 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", "more_options": "その他のオプション", "name": "名前", + "nano_current_rep": "現在の代表", + "nano_pick_new_rep": "新しい代表者を選びます", "narrow": "狭い", "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", "new_node_testing": "新しいノードのテスト", @@ -466,6 +468,8 @@ "remove_node": "ノードを削除", "remove_node_message": "選択したノードを削除してもよろしいですか?", "rename": "リネーム", + "rep_warning": "代表的な警告", + "rep_warning_sub": "あなたの代表者は良好な状態ではないようです。ここをタップして、新しいものを選択します", "require_for_adding_contacts": "連絡先の追加に必要", "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "未使用のコインの詳細", "unspent_coins_title": "未使用のコイン", "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", + "uptime": "稼働時間", "upto": "up up ${value}", "use": "使用する ", "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。", @@ -759,6 +764,7 @@ "view_key_private": "ビューキー (プライベート)", "view_key_public": "ビューキー (パブリック)", "view_transaction_on": "View Transaction on ", + "voting_weight": "投票重み", "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。", "wallet_keys": "ウォレットシード/キー", "wallet_list_create_new_wallet": "新しいウォレットを作成", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 98bc40e77..e9fab7d6f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", "more_options": "추가 옵션", "name": "이름", + "nano_current_rep": "현재 대표", + "nano_pick_new_rep": "새로운 담당자를 선택하십시오", "narrow": "좁은", "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", "new_node_testing": "새로운 노드 테스트", @@ -423,8 +425,8 @@ "placeholder_transactions": "거래가 여기에 표시됩니다", "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", - "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", + "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_select": "선택 해주세요:", "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", @@ -466,6 +468,8 @@ "remove_node": "노드 제거", "remove_node_message": "선택한 노드를 제거 하시겠습니까?", "rename": "이름 바꾸기", + "rep_warning": "대표 경고", + "rep_warning_sub": "귀하의 대표는 양호한 상태가 아닌 것 같습니다. 새 것을 선택하려면 여기를 탭하십시오", "require_for_adding_contacts": "연락처 추가에 필요", "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", "require_for_assessing_wallet": "지갑 접근을 위해 필요", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "사용하지 않은 동전 세부 정보", "unspent_coins_title": "사용하지 않은 동전", "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", + "uptime": "가동 시간", "upto": "최대 ${value}", "use": "사용하다 ", "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.", @@ -759,6 +764,7 @@ "view_key_private": "키보기(은밀한)", "view_key_public": "키보기 (공공의)", "view_transaction_on": "View Transaction on ", + "voting_weight": "투표 중량", "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요.", "wallet_keys": "지갑 시드 / 키", "wallet_list_create_new_wallet": "새 월렛 만들기", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 8d846f3d6..fb3832f05 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", "name": "နာမည်", + "nano_current_rep": "လက်ရှိကိုယ်စားလှယ်", + "nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ", "narrow": "ကျဉ်းသော", "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", @@ -465,6 +467,8 @@ "remove_node": "နှာခေါင်း ကို ဖယ်ရှားပါ။", "remove_node_message": "ရွေးချယ်ထားသော ကုဒ်ကို ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။", "rename": "အမည်ပြောင်းပါ။", + "rep_warning": "ကိုယ်စားလှယ်သတိပေးချက်", + "rep_warning_sub": "သင်၏ကိုယ်စားလှယ်သည်ကောင်းမွန်သောရပ်တည်မှုတွင်မဖြစ်သင့်ပါ။ အသစ်တစ်ခုကိုရွေးချယ်ရန်ဤနေရာတွင်အသာပုတ်ပါ", "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "အသုံးမဝင်သော အကြွေစေ့အသေးစိတ်များ", "unspent_coins_title": "အသုံးမဝင်သော အကြွေစေ့များ", "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", + "uptime": "အထက်က", "upto": "${value} အထိ", "use": "သို့ပြောင်းပါ။", "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။", @@ -758,6 +763,7 @@ "view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", "view_key_public": "သော့ကိုကြည့်ရန် (အများပြည်သူ)", "view_transaction_on": "ငွေလွှဲခြင်းကို ဖွင့်ကြည့်ပါ။", + "voting_weight": "မဲပေးအလေးချိန်", "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။", "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", "wallet_list_create_new_wallet": "Wallet အသစ်ဖန်တီးပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 8b3edee4b..0db2f4ebf 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", "more_options": "Meer opties", "name": "Naam", + "nano_current_rep": "Huidige vertegenwoordiger", + "nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger", "narrow": "Smal", "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", "new_node_testing": "Nieuwe knooppunttest", @@ -465,6 +467,8 @@ "remove_node": "Knoop verwijderen", "remove_node_message": "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?", "rename": "Hernoemen", + "rep_warning": "Representatieve waarschuwing", + "rep_warning_sub": "Uw vertegenwoordiger lijkt niet goed te staan. Tik hier om een ​​nieuwe te selecteren", "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Details van niet-uitgegeven munten", "unspent_coins_title": "Ongebruikte munten", "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", + "uptime": "Uptime", "upto": "tot ${value}", "use": "Gebruik ", "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.", @@ -758,6 +763,7 @@ "view_key_private": "Bekijk sleutel (privaat)", "view_key_public": "Bekijk sleutel (openbaar)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Stemgewicht", "waitFewSecondForTxUpdate": "Wacht een paar seconden totdat de transactie wordt weergegeven in de transactiegeschiedenis", "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", "wallet_keys": "Portemonnee zaad/sleutels", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 93dafa352..3c5e9024e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", "more_options": "Więcej opcji", "name": "Nazwa", + "nano_current_rep": "Obecny przedstawiciel", + "nano_pick_new_rep": "Wybierz nowego przedstawiciela", "narrow": "Wąski", "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", "new_node_testing": "Testowanie nowych węzłów", @@ -465,6 +467,8 @@ "remove_node": "Usuń węzeł", "remove_node_message": "Czy na pewno chcesz usunąć wybrany węzeł?", "rename": "Zmień nazwę", + "rep_warning": "Przedstawicielskie ostrzeżenie", + "rep_warning_sub": "Twój przedstawiciel nie wydaje się mieć dobrej opinii. Stuknij tutaj, aby wybrać nowy", "require_for_adding_contacts": "Wymagane do dodania kontaktów", "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", "require_for_assessing_wallet": "Wymagaj dostępu do portfela", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Szczegóły niewydanych monet", "unspent_coins_title": "Niewydane monety", "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", + "uptime": "Czas aktu", "upto": "do ${value}", "use": "Użyj ", "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.", @@ -758,6 +763,7 @@ "view_key_private": "Prywatny Klucz Wglądu", "view_key_public": "Publiczny Klucz Wglądu", "view_transaction_on": "Zobacz transakcje na ", + "voting_weight": "Waga głosu", "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji", "wallet_keys": "Klucze portfela", "wallet_list_create_new_wallet": "Utwórz nowy portfel", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ae07bb177..e8ac0af2e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", "more_options": "Mais opções", "name": "Nome", + "nano_current_rep": "Representante atual", + "nano_pick_new_rep": "Escolha um novo representante", "narrow": "Estreito", "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", "new_node_testing": "Teste de novo nó", @@ -467,6 +469,8 @@ "remove_node": "Remover nó", "remove_node_message": "Você realmente deseja remover o nó selecionado?", "rename": "Renomear", + "rep_warning": "Aviso representativo", + "rep_warning_sub": "Seu representante não parece estar em boa posição. Toque aqui para selecionar um novo", "require_for_adding_contacts": "Requer para adicionar contatos", "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", "require_for_assessing_wallet": "Requer para acessar a carteira", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Detalhes de moedas não gastas", "unspent_coins_title": "Moedas não gastas", "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", + "uptime": "Tempo de atividade", "upto": "até ${value}", "use": "Use PIN de ", "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.", @@ -760,6 +765,7 @@ "view_key_private": "Chave de visualização (privada)", "view_key_public": "Chave de visualização (pública)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso de votação", "waitFewSecondForTxUpdate": "Aguarde alguns segundos para que a transação seja refletida no histórico de transações", "waiting_payment_confirmation": "Aguardando confirmação de pagamento", "wallet_keys": "Semente/chaves da carteira", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 5e75631c6..b049ab843 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", "more_options": "Дополнительные параметры", "name": "Имя", + "nano_current_rep": "Нынешний представитель", + "nano_pick_new_rep": "Выберите нового представителя", "narrow": "Узкий", "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", "new_node_testing": "Тестирование новой ноды", @@ -466,6 +468,8 @@ "remove_node": "Удалить ноду", "remove_node_message": "Вы уверены, что хотите удалить текущую ноду?", "rename": "Переименовать", + "rep_warning": "Представительное предупреждение", + "rep_warning_sub": "Ваш представитель, похоже, не в хорошей репутации. Нажмите здесь, чтобы выбрать новый", "require_for_adding_contacts": "Требовать добавления контактов", "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", "require_for_assessing_wallet": "Требовать для доступа к кошельку", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Сведения о неизрасходованных монетах", "unspent_coins_title": "Неизрасходованные монеты", "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", + "uptime": "Время безотказной работы", "upto": "до ${value}", "use": "Использовать ", "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.", @@ -759,6 +764,7 @@ "view_key_private": "Приватный ключ просмотра", "view_key_public": "Публичный ключ просмотра", "view_transaction_on": "View Transaction on ", + "voting_weight": "Вес голоса", "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций.", "wallet_keys": "Мнемоническая фраза/ключи кошелька", "wallet_list_create_new_wallet": "Создать новый кошелёк", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index c8183c031..eebcaf4e5 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", "more_options": "ตัวเลือกเพิ่มเติม", "name": "ชื่อ", + "nano_current_rep": "ตัวแทนปัจจุบัน", + "nano_pick_new_rep": "เลือกตัวแทนใหม่", "narrow": "แคบ", "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", "new_node_testing": "การทดสอบโหนดใหม่", @@ -465,6 +467,8 @@ "remove_node": "ลบโหนด", "remove_node_message": "คุณแน่ใจหรือว่าต้องการลบโหนดที่เลือก?", "rename": "เปลี่ยนชื่อ", + "rep_warning": "คำเตือนตัวแทน", + "rep_warning_sub": "ตัวแทนของคุณดูเหมือนจะไม่อยู่ในสถานะที่ดี แตะที่นี่เพื่อเลือกอันใหม่", "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "รายละเอียดเหรียญที่ไม่ได้ใช้", "unspent_coins_title": "เหรียญที่ไม่ได้ใช้", "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", + "uptime": "เวลาทำงาน", "upto": "สูงสุด ${value}", "use": "สลับไปที่ ", "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", @@ -758,6 +763,7 @@ "view_key_private": "คีย์มุมมอง (ส่วนตัว)", "view_key_public": "คีย์มุมมอง (สาธารณะ)", "view_transaction_on": "ดูการทำธุรกรรมบน ", + "voting_weight": "น้ำหนักโหวต", "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม", "wallet_keys": "ซีดของกระเป๋า/คีย์", "wallet_list_create_new_wallet": "สร้างกระเป๋าใหม่", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index def38820c..1e85e5fb9 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", "more_options": "Higit pang mga pagpipilian", "name": "Pangalan", + "nano_current_rep": "Kasalukuyang kinatawan", + "nano_pick_new_rep": "Pumili ng isang bagong kinatawan", "narrow": "Makitid", "new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake", "new_node_testing": "Bagong pagsubok sa node", @@ -465,6 +467,8 @@ "remove_node": "Alisin ang node", "remove_node_message": "Sigurado ka bang nais mong alisin ang napiling node?", "rename": "Palitan ang pangalan", + "rep_warning": "Babala ng kinatawan", + "rep_warning_sub": "Ang iyong kinatawan ay hindi lilitaw na nasa mabuting kalagayan. Tapikin dito upang pumili ng bago", "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", "unspent_coins_title": "Unspent barya", "unsupported_asset": "Hindi namin sinusuportahan ang pagkilos na ito para sa asset na ito. Mangyaring lumikha o lumipat sa isang pitaka ng isang suportadong uri ng pag -aari.", + "uptime": "Uptime", "upto": "Hanggang sa ${value}", "use": "Lumipat sa", "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", @@ -758,6 +763,7 @@ "view_key_private": "Tingnan ang Key (Pribado)", "view_key_public": "Tingnan ang Key (Publiko)", "view_transaction_on": "Tingnan ang transaksyon sa", + "voting_weight": "Bigat ng pagboto", "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon", "wallet_keys": "Mga buto/susi ng pitaka", "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 111ff91f4..73a911671 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", "more_options": "Daha Fazla Seçenek", "name": "İsim", + "nano_current_rep": "Mevcut temsilci", + "nano_pick_new_rep": "Yeni bir temsilci seçin", "narrow": "Dar", "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", "new_node_testing": "Yeni düğüm test ediliyor", @@ -465,6 +467,8 @@ "remove_node": "Düğümü kaldır", "remove_node_message": "Seçili düğümü kaldırmak istediğinden emin misin?", "rename": "Yeniden adlandır", + "rep_warning": "Temsilci uyarı", + "rep_warning_sub": "Temsilciniz iyi durumda görünmüyor. Yeni bir tane seçmek için buraya dokunun", "require_for_adding_contacts": "Kişi eklemek için gerekli", "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Harcanmamış koin detayları", "unspent_coins_title": "Harcanmamış koinler", "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", + "uptime": "Çalışma süresi", "upto": "Şu miktara kadar: ${value}", "use": "Şuna geç: ", "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.", @@ -758,6 +763,7 @@ "view_key_private": "İzleme anahtarı (özel)", "view_key_public": "İzleme anahtarı (genel)", "view_transaction_on": "İşlemi şurada görüntüle ", + "voting_weight": "Oy kullanma", "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin", "wallet_keys": "Cüzdan tohumu/anahtarları", "wallet_list_create_new_wallet": "Yeni Cüzdan Oluştur", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index a0000418d..c38d2918a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", "more_options": "Більше параметрів", "name": "Ім'я", + "nano_current_rep": "Поточний представник", + "nano_pick_new_rep": "Виберіть нового представника", "narrow": "вузькі", "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", "new_node_testing": "Тестування нового вузла", @@ -466,6 +468,8 @@ "remove_node": "Видалити вузол", "remove_node_message": "Ви впевнені, що хочете видалити поточний вузол?", "rename": "Перейменувати", + "rep_warning": "Представницьке попередження", + "rep_warning_sub": "Ваш представник, схоже, не має доброго становища. Торкніться тут, щоб вибрати новий", "require_for_adding_contacts": "Потрібен для додавання контактів", "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", "require_for_assessing_wallet": "Потрібен доступ до гаманця", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Відомості про невитрачені монети", "unspent_coins_title": "Невитрачені монети", "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", + "uptime": "Час роботи", "upto": "до ${value}", "use": "Використати ", "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.", @@ -759,6 +764,7 @@ "view_key_private": "Приватний ключ перегляду", "view_key_public": "Публічний ключ перегляду", "view_transaction_on": "View Transaction on ", + "voting_weight": "Вага голосування", "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій", "wallet_keys": "Мнемонічна фраза/ключі гаманця", "wallet_list_create_new_wallet": "Створити новий гаманець", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a7d4b896d..de9a4eb4c 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", "more_options": "مزید زرائے", "name": "ﻡﺎﻧ", + "nano_current_rep": "موجودہ نمائندہ", + "nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں", "narrow": "تنگ", "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", "new_node_testing": "نیا نوڈ ٹیسٹنگ", @@ -467,6 +469,8 @@ "remove_node": "نوڈ کو ہٹا دیں۔", "remove_node_message": "کیا آپ واقعی منتخب نوڈ کو ہٹانا چاہتے ہیں؟", "rename": "نام تبدیل کریں۔", + "rep_warning": "نمائندہ انتباہ", + "rep_warning_sub": "آپ کا نمائندہ اچھ standing ے مقام پر نہیں دکھائی دیتا ہے۔ نیا منتخب کرنے کے لئے یہاں ٹیپ کریں", "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "غیر خرچ شدہ سککوں کی تفصیلات", "unspent_coins_title": "غیر خرچ شدہ سکے ۔", "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", + "uptime": "اپ ٹائم", "upto": "${value} تک", "use": "تبدیل کرنا", "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔", @@ -760,6 +765,7 @@ "view_key_private": "کلید دیکھیں (نجی)", "view_key_public": "کلید دیکھیں (عوامی)", "view_transaction_on": "لین دین دیکھیں آن", + "voting_weight": "ووٹ کا وزن", "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ", "wallet_keys": "بٹوے کے بیج / چابیاں", "wallet_list_create_new_wallet": "نیا والیٹ بنائیں", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9ac033917..9a84c86c4 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", "more_options": "Ìyàn àfikún", "name": "Oruko", + "nano_current_rep": "Aṣoju lọwọlọwọ", + "nano_pick_new_rep": "Mu aṣoju tuntun kan", "narrow": "Taara", "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", "new_node_testing": "A ń dán apẹka títun wò", @@ -466,6 +468,8 @@ "remove_node": "Yọ apẹka kúrò", "remove_node_message": "Ṣé ó da yín lójú pé ẹ fẹ́ yọ apẹka lọwọ́ kúrò?", "rename": "Pààrọ̀ orúkọ", + "rep_warning": "Ikilọ aṣoju", + "rep_warning_sub": "Aṣoju rẹ ko han lati wa ni iduro to dara. Fọwọ ba ibi lati yan ọkan titun kan", "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Àwọn owó ẹyọ t'á kò tí ì san", "unspent_coins_title": "Àwọn owó ẹyọ t'á kò tí ì san", "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", + "uptime": "Iduro", "upto": "kò tóbi ju ${value}", "use": "Lo", "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.", @@ -759,6 +764,7 @@ "view_key_private": "Kọ́kọ́rọ́ ìwò (àdáni)", "view_key_public": "Kọ́kọ́rọ́ ìwò (kò àdáni)", "view_transaction_on": "Wo pàṣípààrọ̀ lórí ", + "voting_weight": "Idibo iwuwo", "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo", "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 26bb1b286..1c568174d 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", "more_options": "更多选项", "name": "姓名", + "nano_current_rep": "当前代表", + "nano_pick_new_rep": "选择新代表", "narrow": "狭窄的", "new_first_wallet_text": "轻松确保您的加密货币安全", "new_node_testing": "新节点测试", @@ -465,6 +467,8 @@ "remove_node": "删除节点", "remove_node_message": "您确定要删除所选节点吗?", "rename": "重命名", + "rep_warning": "代表性警告", + "rep_warning_sub": "您的代表似乎并不信誉良好。点击这里选择一个新的", "require_for_adding_contacts": "需要添加联系人", "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", "require_for_assessing_wallet": "需要访问钱包", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "未使用代幣詳情", "unspent_coins_title": "未使用的硬幣", "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", + "uptime": "正常运行时间", "upto": "最高 ${value}", "use": "切换使用", "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。", @@ -758,6 +763,7 @@ "view_key_private": "View 密钥(私钥)", "view_key_public": "View 密钥(公钥)", "view_transaction_on": "View Transaction on ", + "voting_weight": "投票权重", "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中", "wallet_keys": "钱包种子/密钥", "wallet_list_create_new_wallet": "创建新钱包", diff --git a/tool/configure.dart b/tool/configure.dart index 06243e8ab..6ee84d63a 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -795,6 +795,7 @@ import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/nano_account_info_response.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:mobx/mobx.dart'; import 'package:hive/hive.dart'; import 'package:cake_wallet/view_model/send/output.dart'; @@ -853,6 +854,8 @@ abstract class Nano { Future updateTransactions(Object wallet); BigInt getTransactionAmountRaw(TransactionInfo transactionInfo); String getRepresentative(Object wallet); + Future> getN2Reps(Object wallet); + bool isRepOk(Object wallet); } abstract class NanoAccountList { From 1769db1641c37aa6d829bb0270c6d72ed78b3fb8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 12 Apr 2024 16:01:21 +0200 Subject: [PATCH 9/9] Generic Fixes (#1373) * Fix exchanges not showing * Fix button text on Monero receive screen * Temp fix for ERC20 and SPL tokens not having raw value * Manually Add Trocador new providers temporarily until API integration * properly handle nullability of n2 node [skip ci] --------- Co-authored-by: tuxsudo --- cw_core/lib/n2_node.dart | 2 +- cw_core/lib/wallet_addresses.dart | 3 ++- .../provider/trocador_exchange_provider.dart | 12 +++++++++++- lib/view_model/send/send_view_model.dart | 8 +++++--- .../wallet_address_list_view_model.dart | 4 ---- scripts/ios/app_env.sh | 4 ++-- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/cw_core/lib/n2_node.dart b/cw_core/lib/n2_node.dart index 0fad9d1b5..a2eb6e4d3 100644 --- a/cw_core/lib/n2_node.dart +++ b/cw_core/lib/n2_node.dart @@ -14,7 +14,7 @@ class N2Node { String? alias; factory N2Node.fromJson(Map json) => N2Node( - weight: double.tryParse((json['weight'] as num).toString()), + weight: double.tryParse((json['weight'] as num?).toString()), uptime: json['uptime'] as String?, score: json['score'] as int?, account: json['rep_address'] as String?, diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index a2a2a50a3..e987b5d0e 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -41,5 +41,6 @@ abstract class WalletAddresses { } } - bool containsAddress(String address) => allAddressesMap.containsKey(address); + bool containsAddress(String address) => + addressesMap.containsKey(address) || allAddressesMap.containsKey(address); } diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index 326573016..688bf15c9 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -32,7 +32,17 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'Exolix', 'Godex', 'Exch', - 'CoinCraddle' + 'CoinCraddle', + 'Alfacash', + 'LocalMonero', + 'XChange', + 'NeroSwap', + 'Changee', + 'BitcoinVN', + 'EasyBit', + 'WizardSwap', + 'Quantex', + 'SwapSpace', ]; static const List _notSupported = [ diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 28cd0128f..038301db4 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -156,10 +156,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return priority; } - int? getCustomPriorityIndex(List priorities) { if (wallet.type == WalletType.bitcoin) { - final customItem = priorities.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); + final customItem = priorities + .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); return customItem != null ? priorities.indexOf(customItem) : null; } @@ -503,7 +503,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor address = output.address; } - if (address.isNotEmpty && !contactAddresses.contains(address)) { + if (address.isNotEmpty && + !contactAddresses.contains(address) && + selectedCryptoCurrency.raw != -1) { return ContactRecord( contactListViewModel.contactSource, Contact( diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index a2aab5251..20980f5f0 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -213,10 +213,6 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return S.current.addresses; } - if (isAutoGenerateSubaddressEnabled) { - return hasAccounts ? S.current.accounts : S.current.account; - } - return hasAccounts ? S.current.accounts_subaddresses : S.current.addresses; } diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 7e4f214ab..61f690c0b 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.3" -CAKEWALLET_BUILD_NUMBER=221 +CAKEWALLET_VERSION="4.16.0" +CAKEWALLET_BUILD_NUMBER=226 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven"