From 03ff2287dbb42ef4092ceaa43f5dc087f05b2d7f Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 9 Dec 2024 22:37:06 +0200 Subject: [PATCH 01/26] Cw 658 make the addressbook popup can be turned off from the settings (#1856) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make ‘Add to Addressbook’ popup optional in settings * localisation * fix contacts page background color --- lib/entities/preferences_key.dart | 1 + lib/src/screens/contact/contact_list_page.dart | 1 + lib/src/screens/send/send_page.dart | 4 ++-- .../screens/settings/other_settings_page.dart | 8 ++++++++ lib/store/settings_store.dart | 16 ++++++++++++++++ lib/view_model/send/send_view_model.dart | 2 ++ .../settings/other_settings_view_model.dart | 7 +++++++ 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_hy.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 | 3 ++- 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_vi.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 35 files changed, 67 insertions(+), 4 deletions(-) diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 5ed7a7ed6..58a540278 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -91,6 +91,7 @@ class PreferencesKey { static const donationLinkWalletName = 'donation_link_wallet_name'; static const lastSeenAppVersion = 'last_seen_app_version'; static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; + static const showAddressBookPopupEnabled = 'show_address_book_popup_enabled'; static const isNewInstall = 'is_new_install'; static const serviceStatusShaKey = 'service_status_sha_key'; static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list'; diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 166288135..50b4ae7c0 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -322,6 +322,7 @@ class _ContactListBodyState extends State { ? widget.contactListViewModel.contacts : widget.contactListViewModel.contactsToShow; return Scaffold( + backgroundColor: Theme.of(context).colorScheme.background, body: Container( child: FilteredList( list: contacts, diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 1941c8061..4b1227751 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -525,14 +525,14 @@ class SendPage extends BasePage { ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' : ''; - final newContactMessage = newContactAddress != null + final newContactMessage = newContactAddress != null && sendViewModel.showAddressBookPopup ? '\n${S.of(_dialogContext).add_contact_to_address_book}' : ''; String alertContent = "$successMessage$waitMessage$newContactMessage"; - if (newContactAddress != null) { + if (newContactMessage.isNotEmpty) { return AlertWithTwoActions( alertDialogKey: ValueKey('send_page_sent_dialog_key'), alertTitle: '', diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index f6a6288f5..24f321798 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/settings/widgets/setting_priority_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart'; import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:cw_core/wallet_type.dart'; @@ -62,6 +63,13 @@ class OtherSettingsPage extends BasePage { handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.readDisclaimer), ), + SettingsSwitcherCell( + title: S.of(context).show_address_book_popup, + value: _otherSettingsViewModel.showAddressBookPopup, + onValueChange: (_, bool value) { + _otherSettingsViewModel.setShowAddressBookPopup(value); + }, + ), Spacer(), SettingsVersionCell( title: S.of(context).version(_otherSettingsViewModel.currentVersion)), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 93299a575..aa7df4ba9 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -54,6 +54,7 @@ abstract class SettingsStoreBase with Store { required BackgroundTasks backgroundTasks, required SharedPreferences sharedPreferences, required bool initialShouldShowMarketPlaceInDashboard, + required bool initialShowAddressBookPopupEnabled, required FiatCurrency initialFiatCurrency, required BalanceDisplayMode initialBalanceDisplayMode, required bool initialSaveRecipientAddress, @@ -157,6 +158,7 @@ abstract class SettingsStoreBase with Store { walletListAscending = initialWalletListAscending, contactListAscending = initialContactListAscending, shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard, + showAddressBookPopupEnabled = initialShowAddressBookPopupEnabled, exchangeStatus = initialExchangeStatus, currentTheme = initialTheme, pinCodeLength = initialPinLength, @@ -354,6 +356,11 @@ abstract class SettingsStoreBase with Store { (bool value) => sharedPreferences.setBool(PreferencesKey.shouldShowMarketPlaceInDashboard, value)); + reaction( + (_) => showAddressBookPopupEnabled, + (bool value) => + sharedPreferences.setBool(PreferencesKey.showAddressBookPopupEnabled, value)); + reaction((_) => pinCodeLength, (int pinLength) => sharedPreferences.setInt(PreferencesKey.currentPinLength, pinLength)); @@ -606,6 +613,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldShowMarketPlaceInDashboard; + @observable + bool showAddressBookPopupEnabled; + @observable ObservableList actionlistDisplayMode; @@ -917,6 +927,8 @@ abstract class SettingsStoreBase with Store { final tokenTrialNumber = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? 0; final shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true; + final showAddressBookPopupEnabled = + sharedPreferences.getBool(PreferencesKey.showAddressBookPopupEnabled) ?? true; final exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); @@ -1185,6 +1197,7 @@ abstract class SettingsStoreBase with Store { secureStorage: secureStorage, sharedPreferences: sharedPreferences, initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, + initialShowAddressBookPopupEnabled: showAddressBookPopupEnabled, nodes: nodes, powNodes: powNodes, appVersion: packageInfo.version, @@ -1361,6 +1374,9 @@ abstract class SettingsStoreBase with Store { shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? shouldShowMarketPlaceInDashboard; + showAddressBookPopupEnabled = + sharedPreferences.getBool(PreferencesKey.showAddressBookPopupEnabled) ?? + showAddressBookPopupEnabled; exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 70958fb99..61474d6c9 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -109,6 +109,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor final UnspentCoinType coinTypeToSpendFrom; + bool get showAddressBookPopup => _settingsStore.showAddressBookPopupEnabled; + @action void addOutput() { outputs diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 3036e8ae9..c7a5d0b90 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -60,6 +60,10 @@ abstract class OtherSettingsViewModelBase with Store { bool get changeRepresentativeEnabled => _wallet.type == WalletType.nano || _wallet.type == WalletType.banano; + @computed + bool get showAddressBookPopup => _settingsStore.showAddressBookPopupEnabled; + + @computed bool get displayTransactionPriority => !(changeRepresentativeEnabled || _wallet.type == WalletType.solana || @@ -114,6 +118,9 @@ abstract class OtherSettingsViewModelBase with Store { return customItem != null ? priorities.indexOf(customItem) : null; } + @action + void setShowAddressBookPopup(bool value) => _settingsStore.showAddressBookPopupEnabled = value; + int? get maxCustomFeeRate { if (_wallet.type == WalletType.bitcoin) { return bitcoin!.getMaxCustomFeeRate(_wallet); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 308427296..cfcbca163 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -710,6 +710,7 @@ "share_address": "شارك العنوان", "shared_seed_wallet_groups": "مجموعات محفظة البذور المشتركة", "show": "يعرض", + "show_address_book_popup": "عرض \"إضافة إلى كتاب العناوين\" المنبثقة بعد الإرسال", "show_details": "اظهر التفاصيل", "show_keys": "اظهار السييد / المفاتيح", "show_market_place": "إظهار السوق", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index a2a5e6485..b9197a8ea 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -710,6 +710,7 @@ "share_address": "Сподели адрес", "shared_seed_wallet_groups": "Споделени групи за портфейли за семена", "show": "Показване", + "show_address_book_popup": "Показване на изскачането на „Добавяне към адресната книга“ след изпращане", "show_details": "Показване на подробностите", "show_keys": "Покажи seed/keys", "show_market_place": "Покажи пазар", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 0234be2b6..a3c3c03d6 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -710,6 +710,7 @@ "share_address": "Sdílet adresu", "shared_seed_wallet_groups": "Skupiny sdílených semen", "show": "Show", + "show_address_book_popup": "Po odeslání zobrazíte vyskakovací okno „Přidat do adresáře“", "show_details": "Zobrazit detaily", "show_keys": "Zobrazit seed/klíče", "show_market_place": "Zobrazit trh", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 55c26e4db..39b239f97 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -498,8 +498,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", @@ -711,6 +711,7 @@ "share_address": "Adresse teilen ", "shared_seed_wallet_groups": "Gemeinsame Walletsseed Gruppen", "show": "Zeigen", + "show_address_book_popup": "Popup \"zum Adressbuch hinzufügen\" nach dem Senden anzeigen", "show_details": "Details anzeigen", "show_keys": "Seed/Schlüssel anzeigen", "show_market_place": "Marktplatz anzeigen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f2ddb3c9b..496ac1afc 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -710,6 +710,7 @@ "share_address": "Share address", "shared_seed_wallet_groups": "Shared Seed Wallet Groups", "show": "Show", + "show_address_book_popup": "Show 'Add to Address Book' popup after sending", "show_details": "Show Details", "show_keys": "Show seed/keys", "show_market_place": "Show Marketplace", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 32ee3d8d1..f44909fe4 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -711,6 +711,7 @@ "share_address": "Compartir dirección", "shared_seed_wallet_groups": "Grupos de billetera de semillas compartidas", "show": "Espectáculo", + "show_address_book_popup": "Mostrar ventana emergente 'Agregar a la libreta de direcciones' después de enviar", "show_details": "Mostrar detalles", "show_keys": "Mostrar semilla/claves", "show_market_place": "Mostrar mercado", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 47c6addb6..fd22e40fc 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -710,6 +710,7 @@ "share_address": "Partager l'adresse", "shared_seed_wallet_groups": "Groupes de portefeuilles partagés", "show": "Montrer", + "show_address_book_popup": "Afficher la popup `` Ajouter au carnet d'adresses '' après avoir envoyé", "show_details": "Afficher les détails", "show_keys": "Visualiser la phrase secrète (seed) et les clefs", "show_market_place": "Afficher la place de marché", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 3586998af..4efffb579 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -712,6 +712,7 @@ "share_address": "Raba adireshin", "shared_seed_wallet_groups": "Raba ƙungiya walat", "show": "Nuna", + "show_address_book_popup": "Nuna 'ƙara don magance littafin' Popup bayan aikawa", "show_details": "Nuna Cikakkun bayanai", "show_keys": "Nuna iri/maɓallai", "show_market_place": "Nuna dan kasuwa", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f812caf0e..4659b45eb 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -712,6 +712,7 @@ "share_address": "पता साझा करें", "shared_seed_wallet_groups": "साझा बीज बटुए समूह", "show": "दिखाओ", + "show_address_book_popup": "भेजने के बाद 'एड एड्रेस बुक' पॉपअप दिखाएं", "show_details": "विवरण दिखाएं", "show_keys": "बीज / कुंजियाँ दिखाएँ", "show_market_place": "बाज़ार दिखाएँ", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 9252b19bf..d7f9293db 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -710,6 +710,7 @@ "share_address": "Podijeli adresu", "shared_seed_wallet_groups": "Zajedničke grupe za sjeme novčanika", "show": "Pokazati", + "show_address_book_popup": "Pokažite \"dodaj u adresar\" skočni prozor nakon slanja", "show_details": "Prikaži pojedinosti", "show_keys": "Prikaži pristupni izraz/ključ", "show_market_place": "Prikaži tržište", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index b442defbc..d323844da 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -710,6 +710,7 @@ "share_address": "Կիսվել հասցեով", "shared_seed_wallet_groups": "Համօգտագործված սերմերի դրամապանակների խմբեր", "show": "Ցուցահանդես", + "show_address_book_popup": "Show ույց տալ «Ուղարկելուց հետո« Հասցեների գրքի »թռուցիկ", "show_details": "Ցուցադրել մանրամասներ", "show_keys": "Ցուցադրել բանալիներ", "show_market_place": "Ցուցադրել շուկան", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index a730832dc..bde875a49 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -713,6 +713,7 @@ "share_address": "Bagikan alamat", "shared_seed_wallet_groups": "Kelompok dompet benih bersama", "show": "Menunjukkan", + "show_address_book_popup": "Tampilkan popup 'Tambahkan ke Alamat' setelah mengirim", "show_details": "Tampilkan Rincian", "show_keys": "Tampilkan seed/kunci", "show_market_place": "Tampilkan Pasar", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 00b9810b2..5b719d4ec 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -712,6 +712,7 @@ "share_address": "Condividi indirizzo", "shared_seed_wallet_groups": "Gruppi di portafoglio di semi condivisi", "show": "Spettacolo", + "show_address_book_popup": "Mostra il popup \"Aggiungi alla rubrica\" ​​dopo l'invio", "show_details": "Mostra dettagli", "show_keys": "Mostra seme/chiavi", "show_market_place": "Mostra mercato", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index df1a47c51..631af702c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -711,6 +711,7 @@ "share_address": "住所を共有する", "shared_seed_wallet_groups": "共有シードウォレットグループ", "show": "見せる", + "show_address_book_popup": "送信後に「アドレスブックに追加」ポップアップを表示します", "show_details": "詳細を表示", "show_keys": "シード/キーを表示する", "show_market_place": "マーケットプレイスを表示", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index bea17fb4b..74b4d4b31 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -711,6 +711,7 @@ "share_address": "주소 공유", "shared_seed_wallet_groups": "공유 종자 지갑 그룹", "show": "보여주다", + "show_address_book_popup": "전송 후 '주소 책에 추가'팝업을 표시하십시오", "show_details": "세부정보 표시", "show_keys": "시드 / 키 표시", "show_market_place": "마켓플레이스 표시", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 05ed163c4..88719b1ba 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -710,6 +710,7 @@ "share_address": "လိပ်စာမျှဝေပါ။", "shared_seed_wallet_groups": "shared မျိုးစေ့ပိုက်ဆံအိတ်အုပ်စုများ", "show": "ပြသ", + "show_address_book_popup": "ပေးပို့ပြီးနောက် 'address book' popup ကိုပြပါ", "show_details": "အသေးစိတ်ပြ", "show_keys": "မျိုးစေ့ /သော့များကို ပြပါ။", "show_market_place": "စျေးကွက်ကိုပြသပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 449e1ad27..59d8c05ee 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -710,6 +710,7 @@ "share_address": "Deel adres", "shared_seed_wallet_groups": "Gedeelde zaadportelgroepen", "show": "Show", + "show_address_book_popup": "Toon 'Toevoegen aan adresboek' pop -up na verzenden", "show_details": "Toon details", "show_keys": "Toon zaad/sleutels", "show_market_place": "Toon Marktplaats", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 67ef4f50c..a2793fccf 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -710,6 +710,7 @@ "share_address": "Udostępnij adres", "shared_seed_wallet_groups": "Wspólne grupy portfeli nasion", "show": "Pokazywać", + "show_address_book_popup": "Pokaż wysypkę „Dodaj do książki” po wysłaniu", "show_details": "Pokaż szczegóły", "show_keys": "Pokaż seed/klucze", "show_market_place": "Pokaż rynek", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 6bf05ae46..46309f90a 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -712,6 +712,7 @@ "share_address": "Compartilhar endereço", "shared_seed_wallet_groups": "Grupos de carteira de sementes compartilhados", "show": "Mostrar", + "show_address_book_popup": "Mostre pop -up 'Adicionar ao livro de endereços' depois de enviar", "show_details": "Mostrar detalhes", "show_keys": "Mostrar semente/chaves", "show_market_place": "Mostrar mercado", @@ -963,4 +964,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 daa615f6c..8492f6053 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -711,6 +711,7 @@ "share_address": "Поделиться адресом", "shared_seed_wallet_groups": "Общие группы кошелька семян", "show": "Показывать", + "show_address_book_popup": "Покажите всплывающее окно «Добавить в адрес адреса» после отправки", "show_details": "Показать детали", "show_keys": "Показать мнемоническую фразу/ключи", "show_market_place": "Показать торговую площадку", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 28a25d88b..bf45b6747 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -710,6 +710,7 @@ "share_address": "แชร์ที่อยู่", "shared_seed_wallet_groups": "กลุ่มกระเป๋าเงินที่ใช้ร่วมกัน", "show": "แสดง", + "show_address_book_popup": "แสดง 'เพิ่มในสมุดรายชื่อ' ป๊อปอัพหลังจากส่ง", "show_details": "แสดงรายละเอียด", "show_keys": "แสดงซีด/คีย์", "show_market_place": "แสดงตลาดกลาง", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e0ac804a5..cb868028c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -710,6 +710,7 @@ "share_address": "Ibahagi ang address", "shared_seed_wallet_groups": "Ibinahaging mga pangkat ng pitaka ng binhi", "show": "Ipakita", + "show_address_book_popup": "Ipakita ang popup na 'Idagdag sa Address Book' pagkatapos magpadala", "show_details": "Ipakita ang mga detalye", "show_keys": "Ipakita ang mga seed/key", "show_market_place": "Ipakita ang Marketplace", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 87ad65450..a56478474 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -710,6 +710,7 @@ "share_address": "Adresi paylaş", "shared_seed_wallet_groups": "Paylaşılan tohum cüzdan grupları", "show": "Göstermek", + "show_address_book_popup": "Gönderdikten sonra 'adres defterine ekle' açılır", "show_details": "Detayları Göster", "show_keys": "Tohumları/anahtarları göster", "show_market_place": "Pazar Yerini Göster", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 876ae8993..7e2213a0a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -711,6 +711,7 @@ "share_address": "Поділитися адресою", "shared_seed_wallet_groups": "Спільні групи насіннєвих гаманців", "show": "Показувати", + "show_address_book_popup": "Показати спливаюче вікно \"Додати до адресної книги\" після надсилання", "show_details": "Показати деталі", "show_keys": "Показати мнемонічну фразу/ключі", "show_market_place": "Відображати маркетплейс", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 7bb22a0d0..9dd5ab282 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -712,6 +712,7 @@ "share_address": "پتہ شیئر کریں۔", "shared_seed_wallet_groups": "مشترکہ بیج پرس گروپ", "show": "دکھائیں", + "show_address_book_popup": "بھیجنے کے بعد 'ایڈریس میں شامل کریں کتاب' پاپ اپ دکھائیں", "show_details": "تفصیلات دکھائیں", "show_keys": "بیج / چابیاں دکھائیں۔", "show_market_place": "بازار دکھائیں۔", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 6eeed916e..b26420fea 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -709,6 +709,7 @@ "share_address": "Chia sẻ địa chỉ", "shared_seed_wallet_groups": "Nhóm ví hạt được chia sẻ", "show": "Trình diễn", + "show_address_book_popup": "Hiển thị cửa sổ bật lên 'Thêm vào sổ địa chỉ' sau khi gửi", "show_details": "Hiển thị chi tiết", "show_keys": "Hiển thị hạt giống/khóa", "show_market_place": "Hiển thị Thị trường", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index cb446b421..eb446e984 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -711,6 +711,7 @@ "share_address": "Pín àdírẹ́sì", "shared_seed_wallet_groups": "Awọn ẹgbẹ ti a pin irugbin", "show": "Fihan", + "show_address_book_popup": "Fihan 'ṣafikun si Agbejade Iwe' Lẹhin fifiranṣẹ", "show_details": "Fi ìsọfúnni kékeré hàn", "show_keys": "Wo hóró / àwọn kọ́kọ́rọ́", "show_market_place": "Wa Sopọ Pataki", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 86090f11f..0d3187dc8 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -710,6 +710,7 @@ "share_address": "分享地址", "shared_seed_wallet_groups": "共享种子钱包组", "show": "展示", + "show_address_book_popup": "发送后显示“添加到通讯簿”弹出窗口", "show_details": "显示详细信息", "show_keys": "显示种子/密钥", "show_market_place": "显示市场", From 6744bb8d52099ee7f3689f9dd5b2c5a096c2b7fc Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 10 Dec 2024 00:18:00 +0200 Subject: [PATCH 02/26] try another approach (don't know how it used to work but not with the global cached version) (#1797) --- .github/workflows/cache_dependencies.yml | 9 ++++++-- .github/workflows/pr_test_build_android.yml | 23 +++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 938027e81..014afdcad 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -62,6 +62,7 @@ jobs: /opt/android/cake_wallet/cw_haven/android/.cxx /opt/android/cake_wallet/scripts/monero_c/release key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }} + - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} name: Generate Externals run: | @@ -69,12 +70,16 @@ jobs: source ./app_env.sh cakewallet ./build_monero_all.sh + - name: Set up cache path + id: cache-path + run: echo "cache-file-path=/opt/android/cake_wallet/android/app/key.jks" >> $GITHUB_ENV + - name: Cache Keystore id: cache-keystore uses: actions/cache@v3 with: - path: /opt/android/cake_wallet/android/app/key.jks - key: $STORE_PASS + path: ${{ env.cache-file-path }} + key: keystore - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} name: Generate KeyStore diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index 9df11f7ab..d128d2a1a 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -115,15 +115,20 @@ jobs: cd /opt/android/cake_wallet/scripts/android/ ./build_mwebd.sh --dont-install -# - name: Cache Keystore -# id: cache-keystore -# uses: actions/cache@v3 -# with: -# path: /opt/android/cake_wallet/android/app/key.jks -# key: $STORE_PASS -# -# - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} - - name: Generate KeyStore + + - name: Set up cache path + id: cache-path + run: echo "cache-file-path=/opt/android/cake_wallet/android/app/key.jks" >> $GITHUB_ENV + + - name: Cache Keystore + id: cache-keystore + uses: actions/cache@v3 + with: + path: ${{ env.cache-file-path }} + key: keystore + + - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} + name: Generate KeyStore run: | cd /opt/android/cake_wallet/android/app keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS From 5553d5c9cbdcde8ff427b2ebb46cfddbbb07992a Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 10 Dec 2024 11:52:04 +0200 Subject: [PATCH 03/26] potential fix for cached jks --- .github/workflows/cache_dependencies.yml | 6 +--- .github/workflows/pr_test_build_android.yml | 31 +++++++++------------ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 014afdcad..cb2afa396 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -70,15 +70,11 @@ jobs: source ./app_env.sh cakewallet ./build_monero_all.sh - - name: Set up cache path - id: cache-path - run: echo "cache-file-path=/opt/android/cake_wallet/android/app/key.jks" >> $GITHUB_ENV - - name: Cache Keystore id: cache-keystore uses: actions/cache@v3 with: - path: ${{ env.cache-file-path }} + path: /opt/android/cake_wallet/android/app key: keystore - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index d128d2a1a..1b1566aba 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -61,6 +61,19 @@ jobs: sudo apt update sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + - name: Cache Keystore + id: cache-keystore + uses: actions/cache@v3 + with: + path: /opt/android/cake_wallet/android/app + key: keystore + + - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} + name: Generate KeyStore + run: | + cd /opt/android/cake_wallet/android/app + keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS + - name: Execute Build and Setup Commands run: | sudo mkdir -p /opt/android @@ -115,24 +128,6 @@ jobs: cd /opt/android/cake_wallet/scripts/android/ ./build_mwebd.sh --dont-install - - - name: Set up cache path - id: cache-path - run: echo "cache-file-path=/opt/android/cake_wallet/android/app/key.jks" >> $GITHUB_ENV - - - name: Cache Keystore - id: cache-keystore - uses: actions/cache@v3 - with: - path: ${{ env.cache-file-path }} - key: keystore - - - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} - name: Generate KeyStore - run: | - cd /opt/android/cake_wallet/android/app - keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS - - name: Generate key properties run: | cd /opt/android/cake_wallet From 35cf4a716ff99f22d91e7180fc7a3c402a750b86 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 10 Dec 2024 14:06:56 +0200 Subject: [PATCH 04/26] separate CI steps more clearly Add more info to error reports --- .github/workflows/pr_test_build_android.yml | 11 ++++++++--- .../setup_2fa/setup_2fa_enter_code_page.dart | 5 +++-- lib/utils/exception_handler.dart | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index 1b1566aba..f6d203331 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -61,6 +61,14 @@ jobs: sudo apt update sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang + + - name: Clone Repo + run: | + sudo mkdir -p /opt/android + sudo chown $USER /opt/android + cd /opt/android + git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} + - name: Cache Keystore id: cache-keystore uses: actions/cache@v3 @@ -76,12 +84,9 @@ jobs: - name: Execute Build and Setup Commands run: | - sudo mkdir -p /opt/android - sudo chown $USER /opt/android cd /opt/android -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh cargo install cargo-ndk - git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} cd cake_wallet/scripts/android/ ./install_ndk.sh source ./app_env.sh cakewallet diff --git a/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart b/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart index fad86e94d..64e8f3aab 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart @@ -198,8 +198,9 @@ class TOTPEnterCode extends BasePage { }, ); if (isForSetup && result) { - Navigator.pushReplacementNamed( - context, Routes.modify2FAPage); + if (context.mounted) { + Navigator.pushReplacementNamed(context, Routes.modify2FAPage); + } } }, diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index f7fc3684e..d79dfe314 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -1,9 +1,11 @@ import 'dart:io'; +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/root_dir.dart'; @@ -29,9 +31,21 @@ class ExceptionHandler { _file = File('${appDocDir.path}/error.txt'); } + String? walletType; + CustomTrace? programInfo; + + try { + walletType = getIt.get().wallet?.type.name; + + programInfo = CustomTrace(stackTrace ?? StackTrace.current); + } catch (_) {} + final exception = { "${DateTime.now()}": { "Error": "$error\n\n", + "WalletType": "$walletType\n\n", + "VerboseLog": + "${programInfo?.fileName}#${programInfo?.lineNumber}:${programInfo?.columnNumber} ${programInfo?.callerFunctionName}\n\n", "Library": "$library\n\n", "StackTrace": stackTrace.toString(), } From ed600f9b8b064edc6f09f4ba6c7fa7c370e3211e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 10 Dec 2024 15:26:06 +0200 Subject: [PATCH 05/26] disable cache key for now --- .github/workflows/pr_test_build_android.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index f6d203331..2b605c775 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -69,15 +69,15 @@ jobs: cd /opt/android git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} - - name: Cache Keystore - id: cache-keystore - uses: actions/cache@v3 - with: - path: /opt/android/cake_wallet/android/app - key: keystore - - - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} - name: Generate KeyStore +# - name: Cache Keystore +# id: cache-keystore +# uses: actions/cache@v3 +# with: +# path: /opt/android/cake_wallet/android/app +# key: keystore +# +# - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} + - name: Generate KeyStore run: | cd /opt/android/cake_wallet/android/app keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS From 9590aa25b6b679a19c69db313cde84087eb1ede5 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:45:15 +0100 Subject: [PATCH 06/26] CW-802: Ethereum enhancements (#1826) * fix: Ethereum enhancements around fees and computations relating to signing and sending transactions * feat: Add nownodes key for evm to workflow * feat: Reactivate send all on both eth and polygon wallet types * fix: Add generic function for updating the node for a wallet type, move ethereum transaction error fees handler to a new file * fix: Revert podfile.lock --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build_android.yml | 1 + .github/workflows/pr_test_build_linux.yml | 1 + assets/ethereum_server_list.yml | 2 + assets/polygon_node_list.yml | 4 +- cw_evm/lib/evm_chain_client.dart | 36 ++++++--- cw_evm/lib/evm_chain_wallet.dart | 61 +++++++++++--- cw_polygon/lib/polygon_client.dart | 8 ++ lib/entities/default_settings_migration.dart | 36 ++++++++- .../evm_transaction_error_fees_handler.dart | 81 +++++++++++++++++++ lib/main.dart | 2 +- lib/view_model/send/send_view_model.dart | 36 ++++++--- res/values/strings_ar.arb | 4 + res/values/strings_bg.arb | 4 + res/values/strings_cs.arb | 4 + res/values/strings_de.arb | 4 + res/values/strings_en.arb | 4 + res/values/strings_es.arb | 4 + res/values/strings_fr.arb | 4 + res/values/strings_ha.arb | 4 + res/values/strings_hi.arb | 4 + res/values/strings_hr.arb | 4 + res/values/strings_hy.arb | 4 + res/values/strings_id.arb | 4 + res/values/strings_it.arb | 4 + res/values/strings_ja.arb | 4 + res/values/strings_ko.arb | 4 + res/values/strings_my.arb | 4 + res/values/strings_nl.arb | 4 + res/values/strings_pl.arb | 4 + res/values/strings_pt.arb | 4 + res/values/strings_ru.arb | 4 + res/values/strings_th.arb | 4 + res/values/strings_tl.arb | 4 + res/values/strings_tr.arb | 4 + res/values/strings_uk.arb | 4 + res/values/strings_ur.arb | 4 + res/values/strings_vi.arb | 4 + res/values/strings_yo.arb | 4 + res/values/strings_zh.arb | 4 + tool/utils/secret_key.dart | 1 + 40 files changed, 346 insertions(+), 35 deletions(-) create mode 100644 lib/entities/evm_transaction_error_fees_handler.dart diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index 2b605c775..ab198dfb2 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -188,6 +188,7 @@ jobs: echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_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 nowNodesApiKey = '${{ secrets.EVM_NOWNODES_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/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml index c37b11582..f690e0236 100644 --- a/.github/workflows/pr_test_build_linux.yml +++ b/.github/workflows/pr_test_build_linux.yml @@ -165,6 +165,7 @@ jobs: echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart + echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart diff --git a/assets/ethereum_server_list.yml b/assets/ethereum_server_list.yml index 125085d88..965638471 100644 --- a/assets/ethereum_server_list.yml +++ b/assets/ethereum_server_list.yml @@ -6,5 +6,7 @@ uri: rpc.flashbots.net - uri: eth-mainnet.public.blastapi.io +- + uri: eth.nownodes.io - uri: ethereum.publicnode.com \ No newline at end of file diff --git a/assets/polygon_node_list.yml b/assets/polygon_node_list.yml index 34504269d..63878bc0c 100644 --- a/assets/polygon_node_list.yml +++ b/assets/polygon_node_list.yml @@ -3,4 +3,6 @@ - uri: polygon-bor.publicnode.com - - uri: polygon.llamarpc.com \ No newline at end of file + uri: polygon.llamarpc.com +- + uri: matic.nownodes.io \ No newline at end of file diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 1935df2af..7dad39f7a 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -36,7 +36,18 @@ abstract class EVMChainClient { bool connect(Node node) { try { - _client = Web3Client(node.uri.toString(), httpClient); + Uri? rpcUri; + bool isModifiedNodeUri = false; + + if (node.uriRaw == 'eth.nownodes.io' || node.uriRaw == 'matic.nownodes.io') { + isModifiedNodeUri = true; + String nowNodeApiKey = secrets.nowNodesApiKey; + + rpcUri = Uri.https(node.uriRaw, '/$nowNodeApiKey'); + } + + _client = + Web3Client(isModifiedNodeUri ? rpcUri!.toString() : node.uri.toString(), httpClient); return true; } catch (e) { @@ -83,23 +94,20 @@ abstract class EVMChainClient { } } - Future getEstimatedGas({ - String? contractAddress, + Future getEstimatedGasUnitsForTransaction({ required EthereumAddress toAddress, required EthereumAddress senderAddress, required EtherAmount value, + String? contractAddress, EtherAmount? gasPrice, - // EtherAmount? maxFeePerGas, - // EtherAmount? maxPriorityFeePerGas, + EtherAmount? maxFeePerGas, }) async { try { if (contractAddress == null) { final estimatedGas = await _client!.estimateGas( sender: senderAddress, - gasPrice: gasPrice, to: toAddress, value: value, - // maxPriorityFeePerGas: maxPriorityFeePerGas, // maxFeePerGas: maxFeePerGas, ); @@ -133,7 +141,9 @@ abstract class EVMChainClient { required Credentials privateKey, required String toAddress, required BigInt amount, - required BigInt gas, + required BigInt gasFee, + required int estimatedGasUnits, + required int maxFeePerGas, required EVMChainTransactionPriority priority, required CryptoCurrency currency, required int exponent, @@ -152,6 +162,8 @@ abstract class EVMChainClient { maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), amount: isNativeToken ? EtherAmount.inWei(amount) : EtherAmount.zero(), data: data != null ? hexToBytes(data) : null, + maxGas: estimatedGasUnits, + maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), ); Uint8List signedTransaction; @@ -180,7 +192,7 @@ abstract class EVMChainClient { return PendingEVMChainTransaction( signedTransaction: signedTransaction, amount: amount.toString(), - fee: gas, + fee: gasFee, sendTransaction: _sendTransaction, exponent: exponent, ); @@ -191,7 +203,10 @@ abstract class EVMChainClient { required EthereumAddress to, required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, + EtherAmount? gasPrice, + EtherAmount? maxFeePerGas, Uint8List? data, + int? maxGas, }) { return Transaction( from: from, @@ -199,6 +214,9 @@ abstract class EVMChainClient { maxPriorityFeePerGas: maxPriorityFeePerGas, value: amount, data: data, + maxGas: maxGas, + gasPrice: gasPrice, + maxFeePerGas: maxFeePerGas, ); } diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index eeb86c5bd..eb93bd94f 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -221,7 +221,7 @@ abstract class EVMChainWalletBase /// - The exact amount the user wants to send, /// - The addressHex for the receiving wallet, /// - A contract address which would be essential in determining if to calcualate the estimate for ERC20 or native ETH - Future calculateActualEstimatedFeeForCreateTransaction({ + Future calculateActualEstimatedFeeForCreateTransaction({ required amount, required String? contractAddress, required String receivingAddressHex, @@ -240,22 +240,27 @@ abstract class EVMChainWalletBase maxFeePerGas = gasPrice; } - final estimatedGas = await _client.getEstimatedGas( + final estimatedGas = await _client.getEstimatedGasUnitsForTransaction( contractAddress: contractAddress, senderAddress: _evmChainPrivateKey.address, value: EtherAmount.fromBigInt(EtherUnit.wei, amount!), gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice), toAddress: EthereumAddress.fromHex(receivingAddressHex), - // maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), - // maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), + maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas), ); final totalGasFee = estimatedGas * maxFeePerGas; - return totalGasFee; + + return GasParamsHandler( + estimatedGasUnits: estimatedGas, + estimatedGasFee: totalGasFee, + maxFeePerGas: maxFeePerGas, + gasPrice: gasPrice, + ); } - return 0; + return GasParamsHandler.zero(); } catch (e) { - return 0; + return GasParamsHandler.zero(); } } @@ -318,7 +323,7 @@ abstract class EVMChainWalletBase gasPrice = await _client.getGasUnitPrice(); - estimatedGasUnits = await _client.getEstimatedGas( + estimatedGasUnits = await _client.getEstimatedGasUnitsForTransaction( senderAddress: _evmChainPrivateKey.address, toAddress: _evmChainPrivateKey.address, gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice), @@ -349,6 +354,8 @@ abstract class EVMChainWalletBase int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; num amountToEVMChainMultiplier = pow(10, exponent); String? contractAddress; + int estimatedGasUnitsForTransaction = 0; + int maxFeePerGasForTransaction = 0; String toAddress = _credentials.outputs.first.isParsedAddress ? _credentials.outputs.first.extractedAddress! : _credentials.outputs.first.address; @@ -367,14 +374,16 @@ abstract class EVMChainWalletBase outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); - final estimateFees = await calculateActualEstimatedFeeForCreateTransaction( + final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction( amount: totalAmount, receivingAddressHex: toAddress, priority: _credentials.priority!, contractAddress: contractAddress, ); - estimatedFeesForTransaction = BigInt.from(estimateFees); + estimatedFeesForTransaction = BigInt.from(gasFeesModel.estimatedGasFee); + estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits; + maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas; if (erc20Balance.balance < totalAmount) { throw EVMChainTransactionCreationException(transactionCurrency); @@ -392,14 +401,16 @@ abstract class EVMChainWalletBase totalAmount = erc20Balance.balance; } - final estimateFees = await calculateActualEstimatedFeeForCreateTransaction( + final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction( amount: totalAmount, receivingAddressHex: toAddress, priority: _credentials.priority!, contractAddress: contractAddress, ); - estimatedFeesForTransaction = BigInt.from(estimateFees); + estimatedFeesForTransaction = BigInt.from(gasFeesModel.estimatedGasFee); + estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits; + maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas; if (output.sendAll && transactionCurrency is! Erc20Token) { totalAmount = (erc20Balance.balance - estimatedFeesForTransaction); @@ -420,12 +431,14 @@ abstract class EVMChainWalletBase } final pendingEVMChainTransaction = await _client.signTransaction( + estimatedGasUnits: estimatedGasUnitsForTransaction, privateKey: _evmChainPrivateKey, toAddress: toAddress, amount: totalAmount, - gas: estimatedFeesForTransaction, + gasFee: estimatedFeesForTransaction, priority: _credentials.priority!, currency: transactionCurrency, + maxFeePerGas: maxFeePerGasForTransaction, exponent: exponent, contractAddress: transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, @@ -728,3 +741,25 @@ abstract class EVMChainWalletBase @override final String? passphrase; } + +class GasParamsHandler { + final int estimatedGasUnits; + final int estimatedGasFee; + final int maxFeePerGas; + final int gasPrice; + + GasParamsHandler( + {required this.estimatedGasUnits, + required this.estimatedGasFee, + required this.maxFeePerGas, + required this.gasPrice}); + + static GasParamsHandler zero() { + return GasParamsHandler( + estimatedGasUnits: 0, + estimatedGasFee: 0, + maxFeePerGas: 0, + gasPrice: 0, + ); + } +} diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index d55ee2269..d9f96d1c9 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -14,11 +14,19 @@ class PolygonClient extends EVMChainClient { required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, Uint8List? data, + int? maxGas, + EtherAmount? gasPrice, + EtherAmount? maxFeePerGas, }) { return Transaction( from: from, to: to, value: amount, + data: data, + maxGas: maxGas, + gasPrice: gasPrice, + maxFeePerGas: maxFeePerGas, + maxPriorityFeePerGas: maxPriorityFeePerGas, ); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index f2cfe79b7..d91ad6442 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -289,7 +289,21 @@ Future defaultSettingsMigration( ], ); break; - + case 45: + await updateWalletTypeNodesWithNewNode( + newNodeUri: 'matic.nownodes.io', + sharedPreferences: sharedPreferences, + nodes: nodes, + type: WalletType.polygon, + useSSL: true, + ); + await updateWalletTypeNodesWithNewNode( + newNodeUri: 'eth.nownodes.io', + sharedPreferences: sharedPreferences, + nodes: nodes, + type: WalletType.ethereum, + useSSL: true, + ); default: break; } @@ -339,6 +353,26 @@ Future _changeDefaultNode({ } } +/// Generic function for adding a new Node for a Wallet Type. +Future updateWalletTypeNodesWithNewNode({ + required SharedPreferences sharedPreferences, + required Box nodes, + required WalletType type, + required String newNodeUri, + required bool useSSL, +}) async { + // If it already exists in the box of nodes, no need to add it annymore. + if (nodes.values.any((node) => node.uriRaw == newNodeUri)) return; + + await nodes.add( + Node( + uri: newNodeUri, + type: type, + useSSL: useSSL, + ), + ); +} + Future _updateCakeXmrNode(Box nodes) async { final node = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletMoneroUri); diff --git a/lib/entities/evm_transaction_error_fees_handler.dart b/lib/entities/evm_transaction_error_fees_handler.dart new file mode 100644 index 000000000..63f6e164d --- /dev/null +++ b/lib/entities/evm_transaction_error_fees_handler.dart @@ -0,0 +1,81 @@ +class EVMTransactionErrorFeesHandler { + EVMTransactionErrorFeesHandler({ + this.balanceWei, + this.balanceEth, + this.balanceUsd, + this.txCostWei, + this.txCostEth, + this.txCostUsd, + this.overshotWei, + this.overshotEth, + this.overshotUsd, + this.error, + }); + + String? balanceWei; + String? balanceEth; + String? balanceUsd; + + String? txCostWei; + String? txCostEth; + String? txCostUsd; + + String? overshotWei; + String? overshotEth; + String? overshotUsd; + + String? error; + + factory EVMTransactionErrorFeesHandler.parseEthereumFeesErrorMessage( + String errorMessage, + double assetPriceUsd, + ) { + // Define Regular Expressions to extract the numerical values + RegExp balanceRegExp = RegExp(r'balance (\d+)'); + RegExp txCostRegExp = RegExp(r'tx cost (\d+)'); + RegExp overshotRegExp = RegExp(r'overshot (\d+)'); + + // Match the patterns in the error message + Match? balanceMatch = balanceRegExp.firstMatch(errorMessage); + Match? txCostMatch = txCostRegExp.firstMatch(errorMessage); + Match? overshotMatch = overshotRegExp.firstMatch(errorMessage); + + // Check if all required values are found + if (balanceMatch != null && txCostMatch != null && overshotMatch != null) { + // Extract the numerical strings + String balanceStr = balanceMatch.group(1)!; + String txCostStr = txCostMatch.group(1)!; + String overshotStr = overshotMatch.group(1)!; + + // Parse the numerical strings to BigInt + BigInt balanceWei = BigInt.parse(balanceStr); + BigInt txCostWei = BigInt.parse(txCostStr); + BigInt overshotWei = BigInt.parse(overshotStr); + + // Convert wei to ETH (1 ETH = 1e18 wei) + double balanceEth = balanceWei.toDouble() / 1e18; + double txCostEth = txCostWei.toDouble() / 1e18; + double overshotEth = overshotWei.toDouble() / 1e18; + + // Calculate the USD values + double balanceUsd = balanceEth * assetPriceUsd; + double txCostUsd = txCostEth * assetPriceUsd; + double overshotUsd = overshotEth * assetPriceUsd; + + return EVMTransactionErrorFeesHandler( + balanceWei: balanceWei.toString(), + balanceEth: balanceEth.toString().substring(0, 12), + balanceUsd: balanceUsd.toString().substring(0, 4), + txCostWei: txCostWei.toString(), + txCostEth: txCostEth.toString().substring(0, 12), + txCostUsd: txCostUsd.toString().substring(0, 4), + overshotWei: overshotWei.toString(), + overshotEth: overshotEth.toString().substring(0, 12), + overshotUsd: overshotUsd.toString().substring(0, 4), + ); + } else { + // If any value is missing, return an error message + return EVMTransactionErrorFeesHandler(error: 'Could not parse the error message.'); + } + } +} diff --git a/lib/main.dart b/lib/main.dart index 72818a1d4..00d76800d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -203,7 +203,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 44, + initialMigrationVersion: 45, ); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 61474d6c9..dc3b2701d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/contact.dart'; +import 'package:cake_wallet/entities/evm_transaction_error_fees_handler.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; @@ -136,11 +137,11 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor bool get shouldDisplaySendALL { if (walletType == WalletType.solana) return false; - if (walletType == WalletType.ethereum && selectedCryptoCurrency == CryptoCurrency.eth) - return false; + // if (walletType == WalletType.ethereum && selectedCryptoCurrency == CryptoCurrency.eth) + // return false; - if (walletType == WalletType.polygon && selectedCryptoCurrency == CryptoCurrency.matic) - return false; + // if (walletType == WalletType.polygon && selectedCryptoCurrency == CryptoCurrency.maticpoly) + // return false; return true; } @@ -502,9 +503,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor nano!.updateTransactions(wallet); } - if (pendingTransaction!.id.isNotEmpty) { - final descriptionKey = '${pendingTransaction!.id}_${wallet.walletAddresses.primaryAddress}'; _settingsStore.shouldSaveRecipientAddress ? await transactionDescriptionBox.add(TransactionDescription( @@ -688,9 +687,26 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor if (walletType == WalletType.ethereum || walletType == WalletType.polygon || walletType == WalletType.haven) { - if (errorMessage.contains('gas required exceeds allowance') || - errorMessage.contains('insufficient funds')) { - return S.current.do_not_have_enough_gas_asset(currency.toString()); + if (errorMessage.contains('gas required exceeds allowance')) { + return S.current.gas_exceeds_allowance; + } + + if (errorMessage.contains('insufficient funds')) { + final parsedErrorMessageResult = + EVMTransactionErrorFeesHandler.parseEthereumFeesErrorMessage( + errorMessage, + _fiatConversationStore.prices[currency]!, + ); + + if (parsedErrorMessageResult.error != null) { + return S.current.insufficient_funds_for_tx; + } + + return + '''${S.current.insufficient_funds_for_tx} \n\n''' + '''${S.current.balance}: ${parsedErrorMessageResult.balanceEth} ETH (${parsedErrorMessageResult.balanceUsd} USD)\n\n''' + '''${S.current.transaction_cost}: ${parsedErrorMessageResult.txCostEth} ETH (${parsedErrorMessageResult.txCostUsd} USD)\n\n''' + '''${S.current.overshot}: ${parsedErrorMessageResult.overshotEth} ETH (${parsedErrorMessageResult.overshotUsd} USD)'''; } return errorMessage; @@ -767,4 +783,4 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return false; } -} +} \ No newline at end of file diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index cfcbca163..1b1f37e1e 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "الأسئلة الشائعة", "frozen": "مجمدة", "full_balance": "الرصيد الكامل", + "gas_exceeds_allowance": "الغاز المطلوب بالمعاملة يتجاوز البدل.", "generate_name": "توليد الاسم", "generating_gift_card": "يتم توليد بطاقة هدية", "get_a": "احصل على", @@ -360,6 +361,7 @@ "incoming": "الواردة", "incorrect_seed": "النص الذي تم إدخاله غير صالح.", "inputs": "المدخلات", + "insufficient_funds_for_tx": "أموال غير كافية لتنفيذ المعاملة بنجاح.", "insufficient_lamport_for_tx": "ليس لديك ما يكفي من SOL لتغطية المعاملة ورسوم المعاملات الخاصة بها. يرجى إضافة المزيد من SOL إلى محفظتك أو تقليل كمية SOL التي ترسلها.", "insufficient_lamports": "ليس لديك ما يكفي من SOL لتغطية المعاملة ورسوم المعاملات الخاصة بها. تحتاج على الأقل ${solValueNeeded} sol. يرجى إضافة المزيد من sol إلى محفظتك أو تقليل مبلغ sol الذي ترسله", "insufficientFundsForRentError": "ليس لديك ما يكفي من SOL لتغطية رسوم المعاملة والإيجار للحساب. يرجى إضافة المزيد من sol إلى محفظتك أو تقليل مبلغ sol الذي ترسله", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "إذا كانت هذه المحفظة تحتوي على سييد مكونة من 12 كلمة وتم إنشاؤها في Cake ، فلا تقم بإيداع Bitcoin في هذه المحفظة. قد يتم فقد أي BTC تم تحويله إلى هذه المحفظة. قم بإنشاء محفظة جديدة مكونة من 24 كلمة (انقر فوق القائمة في الجزء العلوي الأيمن ، وحدد محافظ ، واختر إنشاء محفظة جديدة ، ثم حدد Bitcoin) وقم على الفور بنقل BTC الخاص بك هناك. محافظ BTC الجديدة (24 كلمة) من Cake آمنة", "outgoing": "الصادره", "outputs": "المخرجات", + "overshot": "طغمة", "overwrite_amount": "تغير المبلغ", "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", "passphrase": "عبارة الممر (اختياري)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "أجر أقل من اللازم", "trade_state_unpaid": "غير مدفوعة", "trades": "عمليات التداول", + "transaction_cost": "تكلفة المعاملة", "transaction_details_amount": "مقدار", "transaction_details_copied": "تم نسخ ${title} إلى الحافظة", "transaction_details_date": "تاريخ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b9197a8ea..36ecd4b5d 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Често задавани въпроси", "frozen": "Замразени", "full_balance": "Пълен баланс", + "gas_exceeds_allowance": "Газът, изискван от транзакцията, надвишава надбавката.", "generate_name": "Генериране на име", "generating_gift_card": "Създаване на Gift Card", "get_a": "Вземете ", @@ -360,6 +361,7 @@ "incoming": "Входящи", "incorrect_seed": "Въведеният текст е невалиден.", "inputs": "Входове", + "insufficient_funds_for_tx": "Недостатъчни средства за успешно извършване на транзакция.", "insufficient_lamport_for_tx": "Нямате достатъчно SOL, за да покриете транзакцията и таксата му за транзакция. Моля, добавете повече SOL към портфейла си или намалете сумата на SOL, която изпращате.", "insufficient_lamports": "Нямате достатъчно SOL, за да покриете транзакцията и таксата му за транзакция. Имате нужда от поне ${solValueNeeded} sol. Моля, добавете повече SOL към портфейла си или намалете сумата на SOL, която изпращате", "insufficientFundsForRentError": "Нямате достатъчно SOL, за да покриете таксата за транзакцията и наемането на сметката. Моля, добавете повече SOL към портфейла си или намалете сумата на SOL, която изпращате", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Ако този адрес има seed от 12 думи и е създаден чрез Cake, НЕ добавяйте Bitcoin в него. Всякакъв Bitcoin, изпратен на този адрес, може да бъде загубен завинаги. Създайте нов портфейл от 24 думи (натиснете менюто горе, вдясно, изберете Портфейли, изберете Създаване на нов портфейл, след това изберете Bitcoin) и НЕЗАБАВНО преместете своя Bitcoin там. Нови (такива с 24 думи) Bitcoin портфейли от Cake са надеждни", "outgoing": "Изходящи", "outputs": "Изходи", + "overshot": "Превишаване", "overwrite_amount": "Промени сума", "pairingInvalidEvent": "Невалидно събитие при сдвояване", "passphrase": "Passphrase (по избор)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Недостатъчно плащане", "trade_state_unpaid": "Неплатено", "trades": "Trades", + "transaction_cost": "Транзакционни разходи", "transaction_details_amount": "Сума", "transaction_details_copied": "${title} копирано", "transaction_details_date": "Дата", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index a3c3c03d6..af91ea643 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Často kladené otázky", "frozen": "Zmraženo", "full_balance": "Celkový zůstatek", + "gas_exceeds_allowance": "Plyn vyžadovaný transakcí přesahuje příspěvek.", "generate_name": "Generovat jméno", "generating_gift_card": "Generuji dárkovou kartu", "get_a": "Získejte ", @@ -360,6 +361,7 @@ "incoming": "Příchozí", "incorrect_seed": "Zadaný text není správný.", "inputs": "Vstupy", + "insufficient_funds_for_tx": "Nedostatečné prostředky na úspěšné provedení transakce.", "insufficient_lamport_for_tx": "Nemáte dostatek SOL na pokrytí transakce a jejího transakčního poplatku. Laskavě přidejte do své peněženky více solu nebo snižte množství Sol, kterou odesíláte.", "insufficient_lamports": "Nemáte dostatek SOL na pokrytí transakce a jejího transakčního poplatku. Potřebujete alespoň ${solValueNeeded} sol. Laskavě přidejte do své peněženky více SOL nebo snižte množství Sol, kterou odesíláte", "insufficientFundsForRentError": "Nemáte dostatek SOL na pokrytí transakčního poplatku a nájemného za účet. Laskavě přidejte do své peněženky více SOL nebo snižte množství Sol, kterou odesíláte", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Tato peněženka má seed se 12 slovy a byla vytvořena pomocí Cake, NEUKLÁDEJTE Bitcoin na tuto peněženku. Jakékoliv BTC převedené na tuto peněženku může být ztraceno. Vytvořte si novou peněženku s 24 slovy (otevřete menu vpravo nahoře, vyberte Peněženky, zvolte Vytvořit novou peněženku a pak zvolte Bitcoin) a IHNED tam přesuňte své BTC. Nové (24-slovní) BTC peněženky z Cake jsou bezpečné", "outgoing": "Odchozí", "outputs": "Výstupy", + "overshot": "Překročení", "overwrite_amount": "Přepsat částku", "pairingInvalidEvent": "Neplatná událost párování", "passphrase": "Passphrase (volitelné)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Zaplaceno méně", "trade_state_unpaid": "Nezaplaceno", "trades": "Obchody", + "transaction_cost": "Transakční náklady", "transaction_details_amount": "Částka", "transaction_details_copied": "${title} zkopírováno do schránky", "transaction_details_date": "Datum", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 39b239f97..f09b8c714 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Häufig gestellte Fragen", "frozen": "Gefroren", "full_balance": "Gesamtguthaben", + "gas_exceeds_allowance": "Die durch Transaktion erforderliche Gas übertrifft die Zulage.", "generate_name": "Namen generieren", "generating_gift_card": "Geschenkkarte wird erstellt", "get_a": "Hole ein", @@ -360,6 +361,7 @@ "incoming": "Eingehend", "incorrect_seed": "Der eingegebene Text ist ungültig.", "inputs": "Eingänge", + "insufficient_funds_for_tx": "Unzureichende Mittel zur erfolgreichen Ausführung der Transaktion.", "insufficient_lamport_for_tx": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Bitte fügen Sie Ihrer Wallet mehr Sol hinzu oder reduzieren Sie die SOL-Menge, die Sie senden.", "insufficient_lamports": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Sie brauchen mindestens ${solValueNeeded} Sol. Bitte fügen Sie mehr Sol zu Ihrer Wallet hinzu oder reduzieren Sie den von Ihnen gesendeten Sol-Betrag", "insufficientFundsForRentError": "Sie haben nicht genug SOL, um die Transaktionsgebühr und die Miete für das Konto zu decken. Bitte fügen Sie mehr Sol zu Ihrer Wallet hinzu oder reduzieren Sie den von Ihnen gesendeten Sol-Betrag", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Wenn diese Wallet einen 12-Wort-Seed hat und in Cake erstellt wurde, zahlen Sie KEINE Bitcoins in diese Wallet ein. Alle auf diese Wallet übertragenen BTC können verloren gehen. Erstellen Sie eine neue 24-Wort-Wallet (tippen Sie auf das Menü oben rechts, wählen Sie Wallets, wählen Sie Neue Wallet erstellen und dann Bitcoin) und verschieben Sie Ihre BTC SOFORT dorthin. Neue (24-Wort-)BTC-Wallets von Cake sind sicher", "outgoing": "Ausgehend", "outputs": "Ausgänge", + "overshot": "Überschreiten", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Paarung ungültiges Ereignis", "passphrase": "Passphrase (optional)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "Unterbezahlt", "trade_state_unpaid": "Unbezahlt", "trades": "Börsen", + "transaction_cost": "Transaktionskosten", "transaction_details_amount": "Betrag", "transaction_details_copied": "${title} in die Zwischenablage kopiert", "transaction_details_date": "Datum", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 496ac1afc..86d807d8f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Frequently asked questions", "frozen": "Frozen", "full_balance": "Full Balance", + "gas_exceeds_allowance": "Gas required by transaction exceeds allowance.", "generate_name": "Generate Name", "generating_gift_card": "Generating Gift Card", "get_a": "Get a ", @@ -360,6 +361,7 @@ "incoming": "Incoming", "incorrect_seed": "The text entered is not valid.", "inputs": "Inputs", + "insufficient_funds_for_tx": "Insufficient funds to successfully execute transaction.", "insufficient_lamport_for_tx": "You do not have enough SOL to cover the transaction and its transaction fee. Kindly add more SOL to your wallet or reduce the SOL amount you\\'re sending.", "insufficient_lamports": "You do not have enough SOL to cover the transaction and its transaction fee. You need at least ${solValueNeeded} SOL. Kindly add more SOL to your wallet or reduce the SOL amount you\\'re sending", "insufficientFundsForRentError": "You do not have enough SOL to cover the transaction fee and rent for the account. Kindly add more SOL to your wallet or reduce the SOL amount you\\'re sending", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "If this wallet has a 12-word seed and was created in Cake, DO NOT deposit Bitcoin into this wallet. Any BTC transferred to this wallet may be lost. Create a new 24-word wallet (tap the menu at the top right, select Wallets, choose Create New Wallet, then select Bitcoin) and IMMEDIATELY move your BTC there. New (24-word) BTC wallets from Cake are secure", "outgoing": "Outgoing", "outputs": "Outputs", + "overshot": "Overshot", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Pairing Invalid Event", "passphrase": "Passphrase (Optional)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Underpaid", "trade_state_unpaid": "Unpaid", "trades": "Trades", + "transaction_cost": "Transaction Cost", "transaction_details_amount": "Amount", "transaction_details_copied": "${title} copied to Clipboard", "transaction_details_date": "Date", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index f44909fe4..4c0d16b98 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Preguntas frecuentes", "frozen": "Congelada", "full_balance": "Balance completo", + "gas_exceeds_allowance": "El gas requerido por la transacción excede la asignación.", "generate_name": "Generar nombre", "generating_gift_card": "Generando tarjeta de regalo", "get_a": "Obtener un", @@ -360,6 +361,7 @@ "incoming": "Entrante", "incorrect_seed": "El texto ingresado no es válido.", "inputs": "Entradas", + "insufficient_funds_for_tx": "Fondos insuficientes para ejecutar con éxito la transacción.", "insufficient_lamport_for_tx": "No tienes suficiente SOL para cubrir la transacción y su tarifa de transacción. Por favor, agrega más SOL a su billetera o reduce la cantidad de sol que está enviando.", "insufficient_lamports": "No tienes suficiente SOL para cubrir la transacción y su tarifa de transacción. Necesita al menos ${solValueNeeded} sol. Por favor, agrega más sol a su billetera o reduzca la cantidad de sol que está enviando", "insufficientFundsForRentError": "No tienes suficiente SOL para cubrir la tarifa de transacción y alquilar para la cuenta. Por favor, agrega más sol a su billetera o reduce la cantidad de sol que está enviando", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Si esta billetera tiene una semilla de 12 palabras y se creó en Cake, NO deposite Bitcoin en esta billetera. Cualquier BTC transferido a esta billetera se puede perder. Cree una nueva billetera de 24 palabras (toque el menú en la parte superior derecha, seleccione Monederos, elija Crear nueva billetera, luego seleccione Bitcoin) e INMEDIATAMENTE mueva su BTC allí. Las nuevas carteras BTC (24 palabras) de Cake son seguras", "outgoing": "Saliente", "outputs": "Salidas", + "overshot": "Sobrepasar", "overwrite_amount": "Sobreescribir monto", "pairingInvalidEvent": "Evento de emparejamiento no válido", "passphrase": "Passfrase (opcional)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "Poco pagado", "trade_state_unpaid": "No pagado", "trades": "Cambios", + "transaction_cost": "Costo de transacción", "transaction_details_amount": "Cantidad", "transaction_details_copied": "${title} Copiado al portapapeles", "transaction_details_date": "Fecha", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index fd22e40fc..c15366f5a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Foire aux questions", "frozen": "Gelées", "full_balance": "Solde Complet", + "gas_exceeds_allowance": "Le gaz requis par la transaction dépasse l'allocation.", "generate_name": "Générer un nom", "generating_gift_card": "Génération d'une carte-cadeau", "get_a": "Obtenir un ", @@ -360,6 +361,7 @@ "incoming": "Entrantes", "incorrect_seed": "Le texte entré est invalide.", "inputs": "Contributions", + "insufficient_funds_for_tx": "Fonds insuffisants pour exécuter avec succès la transaction.", "insufficient_lamport_for_tx": "Vous n'avez pas assez de sol pour couvrir la transaction et ses frais de transaction. Veuillez ajouter plus de Sol à votre portefeuille ou réduire la quantité de Sol que vous envoyez.", "insufficient_lamports": "Vous n'avez pas assez de sol pour couvrir la transaction et ses frais de transaction. Vous avez besoin d'au moins ${solValueNeeded} sol. Veuillez ajouter plus de Sol à votre portefeuille ou réduire la quantité de sol que vous envoyez", "insufficientFundsForRentError": "Vous n'avez pas assez de SOL pour couvrir les frais de transaction et le loyer pour le compte. Veuillez ajouter plus de Sol à votre portefeuille ou réduire la quantité de sol que vous envoyez", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Si ce portefeuille (wallet) a une phrase secrète (seed) de 12 mots et a été créé dans Cake, NE PAS y déposer de Bitcoin. Tous les BTC transférés vers ce portefeuille seront perdus. Créez un nouveau portefeuille avec phrase secrète de 24 mots (appuyez sur le menu en haut à droite, sélectionnez Portefeuilles puis Créer un Nouveau Portefeuille et enfin Bitcoin) et transférez y IMMÉDIATEMENT vos BTC. Les nouveaux portefeuilles BTC Cake (avec phrase secrète de 24 mots) sont sécurisés", "outgoing": "Sortantes", "outputs": "Les sorties", + "overshot": "Surnommer", "overwrite_amount": "Remplacer le montant", "pairingInvalidEvent": "Événement de couplage non valide", "passphrase": "Phrase de passe (facultative)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Sous payé", "trade_state_unpaid": "Non payé", "trades": "Échanges", + "transaction_cost": "Coût de la transaction", "transaction_details_amount": "Montant", "transaction_details_copied": "${title} copié vers le presse-papier", "transaction_details_date": "Date", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 4efffb579..d95f87bbf 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Tambayoyin da ake yawan yi", "frozen": "Daskararre", "full_balance": "DUKAN KUDI", + "gas_exceeds_allowance": "Gas da ake buƙata ta hanyar ma'amala ya wuce izini.", "generate_name": "Ƙirƙirar Suna", "generating_gift_card": "Samar da Katin Kyauta", "get_a": "Samu a", @@ -360,6 +361,7 @@ "incoming": "Mai shigowa", "incorrect_seed": "rubutun da aka shigar ba shi da inganci.", "inputs": "Abubuwan da ke ciki", + "insufficient_funds_for_tx": "Rashin isasshen kuɗi don aiwatar da ma'amala.", "insufficient_lamport_for_tx": "Ba ku da isasshen sool don rufe ma'amala da kuɗin ma'amala. Da unara ƙara ƙarin sool a cikin walat ɗinku ko rage adadin Sol ɗin da kuke aikawa.", "insufficient_lamports": "Ba ku da isasshen sool don rufe ma'amala da kuɗin ma'amala. Kuna buƙatar aƙalla ${solValueNeeded} Sol. Da kyau ƙara ƙarin sool zuwa walat ɗinku ko rage adadin Sol ɗin da kuke aikawa", "insufficientFundsForRentError": "Ba ku da isasshen Sol don rufe kuɗin ma'amala da haya don asusun. Da kyau ƙara ƙarin sool zuwa walat ɗinku ko rage adadin Sol ɗin da kuke aikawa", @@ -482,6 +484,7 @@ "outdated_electrum_wallet_receive_warning": "Idan wannan walat ɗin yana da nau'in kalma 12 kuma an ƙirƙira shi a cikin Cake, KAR KA saka Bitcoin cikin wannan jakar. Duk wani BTC da aka canjawa wuri zuwa wannan walat na iya ɓacewa. Ƙirƙiri sabon walat mai kalmomi 24 (matsa menu a saman dama, zaɓi Wallets, zaɓi Ƙirƙiri Sabon Wallet, sannan zaɓi Bitcoin) kuma NAN nan take matsar da BTC ɗin ku a can. Sabbin (kalmomi 24) BTC wallets daga Cake suna da tsaro", "outgoing": "Mai fita", "outputs": "Abubuwan fashewa", + "overshot": "Oveshot", "overwrite_amount": "Rubuta adadin", "pairingInvalidEvent": "Haɗa Lamarin mara inganci", "passphrase": "Passphrase (Zabi)", @@ -830,6 +833,7 @@ "trade_state_underpaid": "ba a biya gaba ɗaya ba", "trade_state_unpaid": "ba a biya ba", "trades": "Cinikai", + "transaction_cost": "Kudin kasuwanci", "transaction_details_amount": "Adadin", "transaction_details_copied": "${title} an kwafa zuwa cikin kwafin", "transaction_details_date": "Kwanan wata", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 4659b45eb..6f655fe73 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "अक्सर पूछे जाने वाले प्रश्न", "frozen": "जमा हुआ", "full_balance": "पूर्ण संतुलन", + "gas_exceeds_allowance": "लेनदेन द्वारा आवश्यक गैस भत्ता से अधिक है।", "generate_name": "नाम जनरेट करें", "generating_gift_card": "गिफ्ट कार्ड जनरेट कर रहा है", "get_a": "एक प्राप्त करें", @@ -360,6 +361,7 @@ "incoming": "आने वाली", "incorrect_seed": "दर्ज किया गया पाठ मान्य नहीं है।", "inputs": "इनपुट", + "insufficient_funds_for_tx": "लेनदेन को सफलतापूर्वक निष्पादित करने के लिए अपर्याप्त धन।", "insufficient_lamport_for_tx": "आपके पास लेनदेन और इसके लेनदेन शुल्क को कवर करने के लिए पर्याप्त सोल नहीं है। कृपया अपने बटुए में अधिक सोल जोड़ें या आपके द्वारा भेजे जा रहे सोल राशि को कम करें।", "insufficient_lamports": "आपके पास लेनदेन और इसके लेनदेन शुल्क को कवर करने के लिए पर्याप्त सोल नहीं है। आपको कम से कम ${solValueNeeded} सोल की आवश्यकता है। कृपया अपने बटुए में अधिक सोल जोड़ें या सोल राशि को कम करें जिसे आप भेज रहे हैं", "insufficientFundsForRentError": "आपके पास लेन -देन शुल्क और खाते के लिए किराए को कवर करने के लिए पर्याप्त सोल नहीं है। कृपया अपने बटुए में अधिक सोल जोड़ें या सोल राशि को कम करें जिसे आप भेज रहे हैं", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "अगर इस वॉलेट में 12 शब्दों का बीज है और इसे केक में बनाया गया है, तो इस वॉलेट में बिटकॉइन जमा न करें। इस वॉलेट में स्थानांतरित किया गया कोई भी बीटीसी खो सकता है। एक नया 24-शब्द वॉलेट बनाएं (ऊपर दाईं ओर स्थित मेनू पर टैप करें, वॉलेट चुनें, नया वॉलेट बनाएं चुनें, फिर बिटकॉइन चुनें) और तुरंत अपना बीटीसी वहां ले जाएं। केक से नए (24-शब्द) बीटीसी वॉलेट सुरक्षित हैं", "outgoing": "निवर्तमान", "outputs": "आउटपुट", + "overshot": "कम पड़ गया", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", "passphrase": "पासफ्रेज़ (वैकल्पिक)", @@ -830,6 +833,7 @@ "trade_state_underpaid": "के तहत भुगतान किया", "trade_state_unpaid": "अवैतनिक", "trades": "ट्रेडों", + "transaction_cost": "लेन -देन लागत", "transaction_details_amount": "रकम", "transaction_details_copied": "${title} क्लिपबोर्ड पर नकल", "transaction_details_date": "तारीख", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index d7f9293db..67a41ab2a 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Često postavljana pitanja", "frozen": "Smrznuto", "full_balance": "Pun iznos", + "gas_exceeds_allowance": "Plin potreban transakcijom premašuje dodatak.", "generate_name": "Generiraj ime", "generating_gift_card": "Generiranje darovne kartice", "get_a": "Nabavite ", @@ -360,6 +361,7 @@ "incoming": "Dolazno", "incorrect_seed": "Uneseni tekst nije valjan.", "inputs": "Unosi", + "insufficient_funds_for_tx": "Nedovoljna sredstva za uspješno izvršavanje transakcije.", "insufficient_lamport_for_tx": "Nemate dovoljno SOL -a da pokriva transakciju i njegovu transakcijsku naknadu. Ljubazno dodajte više sol u svoj novčanik ili smanjite količinu SOL -a koju šaljete.", "insufficient_lamports": "Nemate dovoljno SOL -a da pokriva transakciju i njegovu transakcijsku naknadu. Trebate najmanje ${solValueNeeded} sol. Ljubazno dodajte više sol u svoj novčanik ili smanjite količinu SOL -a koju šaljete", "insufficientFundsForRentError": "Nemate dovoljno SOL -a za pokrivanje naknade za transakciju i najamninu za račun. Ljubazno dodajte više sol u svoj novčanik ili smanjite količinu SOL -a koju šaljete", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Ako ovaj novčanik sadrži sjeme od 12 riječi i stvoren je u Torti, NEMOJTE polagati Bitcoin u ovaj novčanik. Bilo koji BTC prebačen u ovaj novčanik može se izgubiti. Stvorite novi novčanik od 24 riječi (taknite izbornik u gornjem desnom dijelu, odaberite Novčanici, odaberite Stvori novi novčanik, a zatim odaberite Bitcoin) i ODMAH premjestite svoj BTC tamo. Novi BTC novčanici (s 24 riječi) tvrtke Cake sigurni su", "outgoing": "Odlazno", "outputs": "Izlazi", + "overshot": "Zalijepiti", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Nevažeći događaj uparivanja", "passphrase": "Prolaznica (neobavezno)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Nedovoljno plaćen", "trade_state_unpaid": "Neplaćen", "trades": "Razmjene", + "transaction_cost": "Trošak transakcije", "transaction_details_amount": "Iznos", "transaction_details_copied": "${title} kopiran u međuspremnik", "transaction_details_date": "Datum", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index d323844da..c6e5b2d13 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Հաճախ տրվող հարցեր", "frozen": "Կասեցված", "full_balance": "Լրիվ մնացորդ", + "gas_exceeds_allowance": "Գործարքով պահանջվող գազը գերազանցում է նպաստը:", "generate_name": "Գեներացնել անուն", "generating_gift_card": "Գեներացնում է նվեր քարտ", "get_a": "Ստանալ ", @@ -360,6 +361,7 @@ "incoming": "Մուտքային", "incorrect_seed": "Տեքստը սխալ է", "inputs": "Մուտքեր", + "insufficient_funds_for_tx": "Անբավարար միջոցներ `գործարքը հաջողությամբ կատարելու համար:", "insufficient_lamport_for_tx": "Դուք չունեք բավարար SOL՝ գործարքն և գործարքի վարձը ծածկելու համար։ Խնդրում ենք ավելացնել ավելի շատ SOL ձեր դրամապանակում կամ նվազեցնել ուղարկվող SOL-ի քանակը։", "insufficient_lamports": "Դուք չունեք բավարար SOL՝ գործարքն և գործարքի վարձը ծածկելու համար։ Ձեզ անհրաժեշտ է առնվազն ${solValueNeeded} SOL։ Խնդրում ենք ավելացնել ավելի շատ SOL ձեր դրամապանակում կամ նվազեցնել ուղարկվող SOL-ի քանակը։", "insufficientFundsForRentError": "Ձեր մնացորդը բավարար չէ վարձակալության համար: Խնդրում ենք ավելացնել մնացորդը կամ նվազեցնել ուղարկվող գումարը", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Եթե այս դրամապանակը 12 բառանոց սերմ ունի և ստեղծվել է Cake-ում, Bitcoin մուծել այս դրամապանակ մի տեղափոխեք։ Որեւէ Bitcoin այս դրամապանակ տեղափոխվել կարող է կորած լինել։ Ստեղծեք նոր 24-բառանոց Bitcoin դրամապանակ (սեղմեք վերևի աջ մենյուն, ընտրեք Դրամապանակներ, ընտրեք Նոր Դրամապանակ, ապա ընտրեք Bitcoin) և տեղափոխեք ձեր ԲԻՏԿ-ն այնտեղ", "outgoing": "Ելքային", "outputs": "Ելքեր", + "overshot": "Ցանց", "overwrite_amount": "Գրեք գումարը", "pairingInvalidEvent": "Սխալ միացում", "passphrase": "Պարող արտահայտություն (Ոչ պարտադիր)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Վճարված է, բայց ոչ ամբողջությամբ", "trade_state_unpaid": "Վճարված չէ", "trades": "Գործարքներ", + "transaction_cost": "Գործարքի արժեքը", "transaction_details_amount": "Գումար", "transaction_details_copied": "${title} պատճենված է գրանցամատյան", "transaction_details_date": "Ամսաթիվ", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index bde875a49..2ffe0b955 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Pertanyaan yang sering diajukan", "frozen": "Dibekukan", "full_balance": "Saldo Penuh", + "gas_exceeds_allowance": "Gas yang dibutuhkan oleh transaksi melebihi tunjangan.", "generate_name": "Hasilkan Nama", "generating_gift_card": "Membuat Kartu Hadiah", "get_a": "Dapatkan ", @@ -360,6 +361,7 @@ "incoming": "Masuk", "incorrect_seed": "Teks yang dimasukkan tidak valid.", "inputs": "Input", + "insufficient_funds_for_tx": "Dana yang tidak mencukupi untuk berhasil menjalankan transaksi.", "insufficient_lamport_for_tx": "Anda tidak memiliki cukup SOL untuk menutupi transaksi dan biaya transaksinya. Mohon tambahkan lebih banyak sol ke dompet Anda atau kurangi jumlah sol yang Anda kirim.", "insufficient_lamports": "Anda tidak memiliki cukup SOL untuk menutupi transaksi dan biaya transaksinya. Anda membutuhkan setidaknya ${solValueNeeded} sol. Mohon tambahkan lebih banyak sol ke dompet Anda atau kurangi jumlah sol yang Anda kirim", "insufficientFundsForRentError": "Anda tidak memiliki cukup SOL untuk menutupi biaya transaksi dan menyewa untuk akun tersebut. Mohon tambahkan lebih banyak sol ke dompet Anda atau kurangi jumlah sol yang Anda kirim", @@ -482,6 +484,7 @@ "outdated_electrum_wallet_receive_warning": "Jika dompet ini memiliki biji semai 12 kata dan dibuat di Cake, JANGAN deposit Bitcoin ke dalam dompet ini. BTC apapun yang ditransfer ke dompet ini mungkin hilang. Buat dompet 24 kata baru (ketuk menu di pojok kanan atas, pilih Dompet, pilih Buat Dompet Baru, lalu pilih Bitcoin) dan SEGERA pindahkan BTC Anda ke sana. Dompet BTC (24 kata) baru dari Cake aman", "outgoing": "Keluar", "outputs": "Output", + "overshot": "Overshot", "overwrite_amount": "Timpa jumlah", "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", "passphrase": "Frasa sandi (opsional)", @@ -831,6 +834,7 @@ "trade_state_underpaid": "Kurang bayar", "trade_state_unpaid": "Belum dibayar", "trades": "Perdagangan", + "transaction_cost": "Biaya transaksi", "transaction_details_amount": "Jumlah", "transaction_details_copied": "${title} disalin ke Clipboard", "transaction_details_date": "Tanggal", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5b719d4ec..4dc5662a8 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -327,6 +327,7 @@ "frequently_asked_questions": "Domande frequenti", "frozen": "Congelato", "full_balance": "Saldo Completo", + "gas_exceeds_allowance": "Il gas richiesto dalla transazione supera l'indennità.", "generate_name": "Genera nome", "generating_gift_card": "Generazione carta regalo", "get_a": "Prendi un ", @@ -361,6 +362,7 @@ "incoming": "In arrivo", "incorrect_seed": "Il testo inserito non è valido.", "inputs": "Input", + "insufficient_funds_for_tx": "Fondi insufficienti per eseguire correttamente la transazione.", "insufficient_lamport_for_tx": "Non hai abbastanza SOL per coprire la transazione e la sua quota di transazione. Si prega di aggiungere più SOL al tuo portafoglio o ridurre l'importo SOL che stai inviando.", "insufficient_lamports": "Non hai abbastanza SOL per coprire la transazione e la sua quota di transazione. Hai bisogno di almeno ${solValueNeeded} sol. Si prega di aggiungere più SOL al tuo portafoglio o ridurre l'importo SOL che stai inviando", "insufficientFundsForRentError": "Non hai abbastanza SOL per coprire la tassa di transazione e l'affitto per il conto. Si prega di aggiungere più SOL al tuo portafoglio o ridurre l'importo SOL che stai inviando", @@ -482,6 +484,7 @@ "outdated_electrum_wallet_receive_warning": "Se questo portafoglio ha un seme di 12 parole ed è stato creato in Cake, NON depositare Bitcoin in questo portafoglio. Qualsiasi BTC trasferito su questo portafoglio potrebbe andare perso. Crea un nuovo portafoglio di 24 parole (tocca il menu in alto a destra, seleziona Portafogli, scegli Crea nuovo portafoglio, quindi seleziona Bitcoin) e sposta IMMEDIATAMENTE lì il tuo BTC. I nuovi portafogli BTC (24 parole) di Cake sono sicuri", "outgoing": "In uscita", "outputs": "Output", + "overshot": "Overs -shot", "overwrite_amount": "Sovrascrivi quantità", "pairingInvalidEvent": "Associazione evento non valido", "passphrase": "Passphrase (opzionale)", @@ -830,6 +833,7 @@ "trade_state_underpaid": "Sottopagato", "trade_state_unpaid": "Non pagato", "trades": "Scambi", + "transaction_cost": "Costo delle transazioni", "transaction_details_amount": "Ammontare", "transaction_details_copied": "${title} copiati negli Appunti", "transaction_details_date": "Data", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 631af702c..59fbb7adf 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "よくある質問", "frozen": "凍った", "full_balance": "フルバランス", + "gas_exceeds_allowance": "取引に必要なガスは、手当を超えています。", "generate_name": "名前の生成", "generated_gift_card": "ギフトカードの生成", "generating_gift_card": "ギフトカードの生成", @@ -361,6 +362,7 @@ "incoming": "着信", "incorrect_seed": "入力されたテキストは無効です。", "inputs": "入力", + "insufficient_funds_for_tx": "トランザクションを正常に実行するための資金が不十分です。", "insufficient_lamport_for_tx": "トランザクションとその取引手数料をカバーするのに十分なSOLがありません。財布にソルを追加するか、送信するソル量を減らしてください。", "insufficient_lamports": "トランザクションとその取引手数料をカバーするのに十分なSOLがありません。少なくとも${solValueNeeded} solが必要です。財布にソルを追加するか、送信するソル量を減らしてください", "insufficientFundsForRentError": "アカウントの取引料金とレンタルをカバーするのに十分なソルがありません。財布にソルを追加するか、送信するソル量を減らしてください", @@ -481,6 +483,7 @@ "outdated_electrum_wallet_receive_warning": "このウォレットに 12 ワードのシードがあり、Cake で作成された場合、このウォレットにビットコインを入金しないでください。 このウォレットに転送された BTC は失われる可能性があります。 新しい 24 ワードのウォレットを作成し (右上のメニューをタップし、[ウォレット]、[新しいウォレットの作成]、[ビットコイン] の順に選択)、すぐに BTC をそこに移動します。 Cake の新しい (24 ワード) BTC ウォレットは安全です", "outgoing": "発信", "outputs": "出力", + "overshot": "オーバーショット", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "ペアリング無効イベント", "passphrase": "パスフレーズ(オプション)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "支払不足", "trade_state_unpaid": "未払い", "trades": "取引", + "transaction_cost": "取引コスト", "transaction_details_amount": "量", "transaction_details_copied": "${title} クリップボードにコピーしました", "transaction_details_date": "日付", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 74b4d4b31..2e7793edb 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "자주 묻는 질문", "frozen": "겨울 왕국", "full_balance": "풀 밸런스", + "gas_exceeds_allowance": "거래에 필요한 가스는 수당을 초과합니다.", "generate_name": "이름 생성", "generating_gift_card": "기프트 카드 생성 중", "get_a": "가져오기", @@ -360,6 +361,7 @@ "incoming": "들어오는", "incorrect_seed": "입력하신 텍스트가 유효하지 않습니다.", "inputs": "입력", + "insufficient_funds_for_tx": "거래를 성공적으로 실행하기위한 자금이 충분하지 않습니다.", "insufficient_lamport_for_tx": "거래 및 거래 수수료를 충당하기에 충분한 SOL이 없습니다. 지갑에 더 많은 솔을 추가하거나 보내는 솔을 줄입니다.", "insufficient_lamports": "거래 및 거래 수수료를 충당하기에 충분한 SOL이 없습니다. 최소 ${solValueNeeded} sol이 필요합니다. 지갑에 더 많은 솔을 추가하거나 보내는 솔을 줄이십시오.", "insufficientFundsForRentError": "거래 수수료와 계좌 임대료를 충당하기에 충분한 SOL이 없습니다. 지갑에 더 많은 솔을 추가하거나 보내는 솔을 줄이십시오.", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "이 지갑에 12 단어 시드가 있고 Cake에서 생성 된 경우이 지갑에 비트 코인을 입금하지 마십시오. 이 지갑으로 전송 된 모든 BTC는 손실 될 수 있습니다. 새로운 24 단어 지갑을 생성하고 (오른쪽 상단의 메뉴를 탭하고 지갑을 선택한 다음 새 지갑 생성을 선택한 다음 비트 코인을 선택하십시오) 즉시 BTC를 그곳으로 이동하십시오. Cake의 새로운 (24 단어) BTC 지갑은 안전합니다", "outgoing": "나가는", "outputs": "출력", + "overshot": "오버 샷", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "잘못된 이벤트 페어링", "passphrase": "암호화 (선택 사항)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "미지급", "trade_state_unpaid": "미지급", "trades": "거래", + "transaction_cost": "거래 비용", "transaction_details_amount": "양", "transaction_details_copied": "${title} 클립 보드에 복사", "transaction_details_date": "날짜", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 88719b1ba..f86beb0f7 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "မေးလေ့ရှိသောမေးခွန်းများ", "frozen": "ဖြူဖြူ", "full_balance": "Balance အပြည့်", + "gas_exceeds_allowance": "ငွေပေးငွေယူမှလိုအပ်သောဓာတ်ငွေ့ထောက်ပံ့ကြေးကျော်လွန်။", "generate_name": "အမည်ဖန်တီးပါ။", "generating_gift_card": "လက်ဆောင်ကတ်ထုတ်ပေးခြင်း။", "get_a": "တစ်ခုရယူပါ။", @@ -360,6 +361,7 @@ "incoming": "ဝင်လာ", "incorrect_seed": "ထည့်သွင်းထားသော စာသားသည် မမှန်ကန်ပါ။", "inputs": "သွင်းငေှ", + "insufficient_funds_for_tx": "ငွေပေးငွေယူအောင်မြင်စွာလုပ်ဆောင်ရန်ရန်ပုံငွေမလုံလောက်ပါ။", "insufficient_lamport_for_tx": "သငျသညျငွေပေးငွေယူနှင့်၎င်း၏ငွေပေးငွေယူကြေးကိုဖုံးလွှမ်းရန် sol ရှိသည်မဟုတ်ကြဘူး။ ကြင်နာစွာသင်၏ပိုက်ဆံအိတ်သို့ပိုမို sol ကိုထပ်ထည့်ပါသို့မဟုတ်သင်ပို့လွှတ်ခြင်း sol ပမာဏကိုလျှော့ချပါ။", "insufficient_lamports": "သငျသညျငွေပေးငွေယူနှင့်၎င်း၏ငွေပေးငွေယူကြေးကိုဖုံးလွှမ်းရန် sol ရှိသည်မဟုတ်ကြဘူး။ သင်အနည်းဆုံး ${solValueNeeded} s ကိုလိုအပ်ပါတယ်။ ကြင်နာစွာသင်၏ပိုက်ဆံအိတ်သို့ပိုမို sol ကိုထပ်ထည့်ပါသို့မဟုတ်သင်ပို့နေသော sol ပမာဏကိုလျှော့ချပါ", "insufficientFundsForRentError": "သင်ငွေပေးချေမှုအခကြေးငွေကိုဖုံးအုပ်ရန်နှင့်အကောင့်ငှားရန်လုံလောက်သော sol ရှိသည်မဟုတ်ကြဘူး။ ကြင်နာစွာသင်၏ပိုက်ဆံအိတ်သို့ပိုမို sol ကိုပိုမိုထည့်ပါသို့မဟုတ်သင်ပို့ခြင်း sol ပမာဏကိုလျှော့ချပါ", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "ဤပိုက်ဆံအိတ်တွင် စာလုံး 12 လုံးပါပြီး ကိတ်မုန့်တွင် ဖန်တီးပါက၊ Bitcoin ကို ဤပိုက်ဆံအိတ်ထဲသို့ မထည့်ပါနှင့်။ ဤပိုက်ဆံအိတ်သို့ လွှဲပြောင်းပေးသည့် မည်သည့် BTC မဆို ဆုံးရှုံးနိုင်သည်။ 24 စကားလုံးပိုက်ဆံအိတ်အသစ်တစ်ခုဖန်တီးပါ (ညာဘက်အပေါ်ထောင့်ရှိမီနူးကိုနှိပ်ပါ၊ Wallets ကိုရွေးချယ်ပါ၊ ပိုက်ဆံအိတ်အသစ်ဖန်တီးရန်ကိုရွေးချယ်ပါ၊ ထို့နောက် Bitcoin ကိုရွေးချယ်ပါ) နှင့်သင်၏ BTC ကိုထိုနေရာသို့ချက်ချင်းရွှေ့ပါ။ Cake မှ (24 စာလုံး) BTC ပိုက်ဆံအိတ်အသစ်များသည် လုံခြုံပါသည်။", "outgoing": "အထွက်", "outputs": "ထုတ်လုပ်မှု", + "overshot": "အလွန်အကျွံအိုး", "overwrite_amount": "ပမာဏကို ထပ်ရေးပါ။", "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", "passphrase": "passphrase (optional)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "ပေးချေမှုနည်းပါးသည်။", "trade_state_unpaid": "အခကြေးငွေမယူရသေး", "trades": "ကုန်သွယ်မှုများ", + "transaction_cost": "ငွေပေးငွေယူကုန်ကျစရိတ်", "transaction_details_amount": "ပမာဏ", "transaction_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", "transaction_details_date": "ရက်စွဲ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 59d8c05ee..7433972a4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Veelgestelde vragen", "frozen": "Bevroren", "full_balance": "Volledig saldo", + "gas_exceeds_allowance": "Gas vereist door transactie overschrijdt de vergoeding.", "generate_name": "Naam genereren", "generating_gift_card": "Cadeaubon genereren", "get_a": "Krijg een ", @@ -360,6 +361,7 @@ "incoming": "inkomend", "incorrect_seed": "De ingevoerde tekst is niet geldig.", "inputs": "Invoer", + "insufficient_funds_for_tx": "Onvoldoende fondsen om de transactie met succes uit te voeren.", "insufficient_lamport_for_tx": "U hebt niet genoeg SOL om de transactie en de transactiekosten te dekken. Voeg vriendelijk meer SOL toe aan uw portemonnee of verminder de SOL -hoeveelheid die u verzendt.", "insufficient_lamports": "U hebt niet genoeg SOL om de transactie en de transactiekosten te dekken. Je hebt minstens ${solValueNeeded} sol nodig. Voeg vriendelijk meer Sol toe aan uw portemonnee of verminder de SOL -hoeveelheid die u verzendt", "insufficientFundsForRentError": "U hebt niet genoeg SOL om de transactiekosten en huur voor de rekening te dekken. Voeg vriendelijk meer SOL toe aan uw portemonnee of verminder de SOL -hoeveelheid die u verzendt", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Als deze portemonnee een seed van 12 woorden heeft en is gemaakt in Cake, stort dan GEEN Bitcoin in deze portemonnee. Elke BTC die naar deze portemonnee is overgebracht, kan verloren gaan. Maak een nieuwe portemonnee van 24 woorden (tik op het menu rechtsboven, selecteer Portefeuilles, kies Nieuwe portemonnee maken en selecteer vervolgens Bitcoin) en verplaats je BTC ONMIDDELLIJK daar. Nieuwe (24-woorden) BTC-portefeuilles van Cake zijn veilig", "outgoing": "Uitgaande", "outputs": "Uitgangen", + "overshot": "Overschrijden", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", "passphrase": "PassaspHRASE (optioneel)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Slecht betaald", "trade_state_unpaid": "Onbetaald", "trades": "Trades", + "transaction_cost": "Transactiekosten", "transaction_details_amount": "Bedrag", "transaction_details_copied": "${title} gekopieerd naar het klembord", "transaction_details_date": "Datum", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index a2793fccf..a2cd61713 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Często zadawane pytania", "frozen": "Zamrożone", "full_balance": "Pełne saldo", + "gas_exceeds_allowance": "Gaz wymagany przez transakcję przekracza dodatek.", "generate_name": "Wygeneruj nazwę", "generating_gift_card": "Generowanie karty podarunkowej", "get_a": "Zdobądź ", @@ -360,6 +361,7 @@ "incoming": "Przychodzące", "incorrect_seed": "Wprowadzony seed jest nieprawidłowy.", "inputs": "Wejścia", + "insufficient_funds_for_tx": "Niewystarczające fundusze na skuteczne wykonanie transakcji.", "insufficient_lamport_for_tx": "Nie masz wystarczającej ilości SOL, aby pokryć transakcję i opłatę za transakcję. Uprzejmie dodaj więcej sol do portfela lub zmniejsz wysyłaną kwotę SOL.", "insufficient_lamports": "Nie masz wystarczającej ilości SOL, aby pokryć transakcję i opłatę za transakcję. Potrzebujesz przynajmniej ${solValueNeeded} sol. Uprzejmie dodaj więcej sol do portfela lub zmniejsz wysyłaną kwotę SOL, którą wysyłasz", "insufficientFundsForRentError": "Nie masz wystarczającej ilości SOL, aby pokryć opłatę za transakcję i czynsz za konto. Uprzejmie dodaj więcej sol do portfela lub zmniejsz solę, którą wysyłasz", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Jeśli ten portfel ma 12-wyrazowy seed i został utworzony w Cake, NIE Wpłacaj Bitcoina do tego portfela. Wszelkie BTC przeniesione do tego portfela mogą zostać utracone. Utwórz nowy portfel z 24 słowami (dotknij menu w prawym górnym rogu, wybierz Portfele, wybierz Utwórz nowy portfel, a następnie Bitcoin) i NATYCHMIAST przenieś tam swoje BTC. Nowe (24 słowa) portfele BTC Cake Wallet są bezpieczne", "outgoing": "Wychodzące", "outputs": "Wyjścia", + "overshot": "Przesadzanie", "overwrite_amount": "Nadpisz ilość", "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", "passphrase": "PassPhraza (opcjonalnie)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Niedopłacone", "trade_state_unpaid": "Nie opłacona", "trades": "Transakcje", + "transaction_cost": "Koszt transakcji", "transaction_details_amount": "Ilość", "transaction_details_copied": "${title} skopiowane do schowka", "transaction_details_date": "Data", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 46309f90a..04d39d57b 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Perguntas frequentes", "frozen": "Congeladas", "full_balance": "Saldo total", + "gas_exceeds_allowance": "O gás exigido pela transação excede o subsídio.", "generate_name": "Gerar nome", "generating_gift_card": "Gerando Cartão Presente", "get_a": "Obter um ", @@ -360,6 +361,7 @@ "incoming": "Recebidas", "incorrect_seed": "O texto digitado não é válido.", "inputs": "Entradas", + "insufficient_funds_for_tx": "Fundos insuficientes para executar com sucesso a transação.", "insufficient_lamport_for_tx": "Você não tem Sol suficiente para cobrir a transação e sua taxa de transação. Por favor, adicione mais sol à sua carteira ou reduza a quantidade de sol que você envia.", "insufficient_lamports": "Você não tem Sol suficiente para cobrir a transação e sua taxa de transação. Você precisa de pelo menos ${solValueNeeded} sol. Por favor, adicione mais sol à sua carteira ou reduza a quantidade de sol que você está enviando", "insufficientFundsForRentError": "Você não tem Sol suficiente para cobrir a taxa de transação e o aluguel da conta. Por favor, adicione mais sol à sua carteira ou reduza a quantidade de sol que você envia", @@ -482,6 +484,7 @@ "outdated_electrum_wallet_receive_warning": "Se esta carteira tiver uma semente de 12 palavras e foi criada no Cake, NÃO deposite Bitcoin nesta carteira. Qualquer BTC transferido para esta carteira pode ser perdido. Crie uma nova carteira de 24 palavras (toque no menu no canto superior direito, selecione Carteiras, escolha Criar Nova Carteira e selecione Bitcoin) e mova IMEDIATAMENTE seu BTC para lá. As novas carteiras BTC (24 palavras) da Cake são seguras", "outgoing": "Enviadas", "outputs": "Saídas", + "overshot": "Ultrapassado", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Emparelhamento de evento inválido", "passphrase": "Senha (opcional)", @@ -830,6 +833,7 @@ "trade_state_underpaid": "Parcialmente paga", "trade_state_unpaid": "Não paga", "trades": "Trocas", + "transaction_cost": "Custo da transação", "transaction_details_amount": "Quantia", "transaction_details_copied": "${title} copiados para a área de transferência", "transaction_details_date": "Data", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 8492f6053..1bb0a9ce3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Часто задаваемые вопросы", "frozen": "Заморожено", "full_balance": "Весь баланс", + "gas_exceeds_allowance": "Газ, требуемый в результате транзакции, превышает пособие.", "generate_name": "Создать имя", "generating_gift_card": "Создание подарочной карты", "get_a": "Получить ", @@ -360,6 +361,7 @@ "incoming": "Входящие", "incorrect_seed": "Введённый текст некорректный.", "inputs": "Входы", + "insufficient_funds_for_tx": "Недостаточно средств для успешного выполнения транзакции.", "insufficient_lamport_for_tx": "У вас недостаточно Sol, чтобы покрыть транзакцию и плату за транзакцию. Пожалуйста, добавьте больше Sol в свой кошелек или уменьшите сумму Sol, которую вы отправляете.", "insufficient_lamports": "У вас недостаточно Sol, чтобы покрыть транзакцию и плату за транзакцию. Вам нужен как минимум ${solValueNeeded} sol. Пожалуйста, добавьте больше Sol в свой кошелек или уменьшите сумму Sol, которую вы отправляете", "insufficientFundsForRentError": "У вас недостаточно Sol, чтобы покрыть плату за транзакцию и аренду для счета. Пожалуйста, добавьте больше Sol в свой кошелек или уменьшите сумму Sol, которую вы отправляете", @@ -481,6 +483,7 @@ "outdated_electrum_wallet_receive_warning": "Если этот кошелек имеет мнемоническую фразу из 12 слов и был создан в Cake, НЕ переводите биткойны на этот кошелек. Любые BTC, переведенные на этот кошелек, могут быть потеряны. Создайте новый кошелек с мнемоническои фразы из 24 слов (коснитесь меню в правом верхнем углу, выберите «Кошельки», выберите «Создать новый кошелек», затем выберите «Bitcoin») и НЕМЕДЛЕННО переведите туда свои BTC. Новые (24 слова) кошельки BTC от Cake безопасны", "outgoing": "Исходящие", "outputs": "Выходы", + "overshot": "Перевернуть", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недействительное событие сопряжения", "passphrase": "Passfrase (необязательно)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "Недоплаченная", "trade_state_unpaid": "Неоплаченная", "trades": "Сделки", + "transaction_cost": "Транзакционная стоимость", "transaction_details_amount": "Сумма", "transaction_details_copied": "${title} скопировано в буфер обмена", "transaction_details_date": "Дата", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index bf45b6747..aeeaf6b5f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "คำถามที่พบบ่อย", "frozen": "ถูกดักจับ", "full_balance": "ยอดคงเหลือทั้งหมด", + "gas_exceeds_allowance": "ก๊าซที่ต้องการโดยการทำธุรกรรมเกินค่าเผื่อ", "generate_name": "สร้างชื่อ", "generating_gift_card": "กำลังสร้างบัตรของขวัญ", "get_a": "รับ ", @@ -360,6 +361,7 @@ "incoming": "ขาเข้า", "incorrect_seed": "ข้อความที่ป้อนไม่ถูกต้อง", "inputs": "อินพุต", + "insufficient_funds_for_tx": "เงินทุนไม่เพียงพอที่จะดำเนินการทำธุรกรรมได้สำเร็จ", "insufficient_lamport_for_tx": "คุณไม่มีโซลเพียงพอที่จะครอบคลุมการทำธุรกรรมและค่าธรรมเนียมการทำธุรกรรม กรุณาเพิ่มโซลให้มากขึ้นลงในกระเป๋าเงินของคุณหรือลดจำนวนโซลที่คุณส่งมา", "insufficient_lamports": "คุณไม่มีโซลเพียงพอที่จะครอบคลุมการทำธุรกรรมและค่าธรรมเนียมการทำธุรกรรม คุณต้องการอย่างน้อย ${solValueNeeded} SOL กรุณาเพิ่มโซลให้มากขึ้นลงในกระเป๋าเงินของคุณหรือลดจำนวนโซลที่คุณกำลังส่ง", "insufficientFundsForRentError": "คุณไม่มีโซลเพียงพอที่จะครอบคลุมค่าธรรมเนียมการทำธุรกรรมและค่าเช่าสำหรับบัญชี กรุณาเพิ่มโซลให้มากขึ้นลงในกระเป๋าเงินของคุณหรือลดจำนวนโซลที่คุณส่งมา", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "หากกระเป๋านี้มีซีดีที่มี 12 คำและถูกสร้างขึ้นใน Cake อย่าโอน Bitcoin เข้ากระเป๋านี้ ทุกจำนวน BTC ที่โอนเข้ากระเป๋านี้อาจสูญหาย สร้างกระเป๋าใหม่ที่มีซีดีที่มี 24 คำ (กดที่เมนูที่มุมขวาบนแล้วเลือก Wallets และเลือก Create New Wallet จากนั้นเลือก Bitcoin) และย้าย BTC ไปที่นั้นทันที กระเป๋า BTC ที่มีซีดีที่มี 24 คำของ Cake ปลอดภัย", "outgoing": "ขาออก", "outputs": "เอาต์พุต", + "overshot": "โอเวอร์คล็อต", "overwrite_amount": "เขียนทับจำนวน", "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", "passphrase": "ข้อความรหัสผ่าน (ไม่บังคับ)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "จ่ายไม่ครบ", "trade_state_unpaid": "ยังไม่ได้จ่าย", "trades": "การซื้อขาย", + "transaction_cost": "ต้นทุนการทำธุรกรรม", "transaction_details_amount": "จำนวน", "transaction_details_copied": "${title} ถูกคัดลอกไปยังคลิปบอร์ด", "transaction_details_date": "วันที่", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index cb868028c..e0ae3f471 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Mga madalas itanong", "frozen": "Frozen", "full_balance": "Buong Balanse", + "gas_exceeds_allowance": "Ang gas na kinakailangan ng transaksyon ay lumampas sa allowance.", "generate_name": "Bumuo ng pangalan", "generating_gift_card": "Bumubuo ng Gift Card", "get_a": "Kumuha ng ", @@ -360,6 +361,7 @@ "incoming": "Papasok", "incorrect_seed": "Ang text na ipinasok ay hindi wasto.", "inputs": "Mga input", + "insufficient_funds_for_tx": "Hindi sapat na pondo upang matagumpay na magsagawa ng transaksyon.", "insufficient_lamport_for_tx": "Wala kang sapat na SOL upang masakop ang transaksyon at ang bayad sa transaksyon nito. Mabuting magdagdag ng higit pa sa iyong pitaka o bawasan ang sol na halaga na iyong ipinapadala.", "insufficient_lamports": "Wala kang sapat na SOL upang masakop ang transaksyon at ang bayad sa transaksyon nito. Kailangan mo ng hindi bababa sa ${solValueNeeded} sol. Mabait na magdagdag ng higit pang sol sa iyong pitaka o bawasan ang dami ng iyong ipinapadala", "insufficientFundsForRentError": "Wala kang sapat na SOL upang masakop ang fee sa transaksyon at upa para sa account. Mabait na magdagdag ng higit pa sa iyong wallet o bawasan ang halaga ng SOL na iyong ipinapadala", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Kung ang wallet na ito ay may 12-word seed na ginawa sa Cake, huwag magdeposito ng Bitcoin sa wallet na ito. Anumang BTC na inilipat sa wallet na ito ay maaaring mawala. Lumikha ng bagong 24 na salita na wallet (i-tap ang menu sa kanang taas, piliin ang Mga Wallets, piliin ang Lumikha ng Bagong Wallet, pagkatapos ay piliin ang Bitcoin) at agad na ilipat ang iyong BTC doon. Bagong (24 na salita) BTC wallet mula sa Cake ay ligtas", "outgoing": "Palabas", "outputs": "Mga output", + "overshot": "Overshot", "overwrite_amount": "I-overwrite ang halaga", "pairingInvalidEvent": "Pairing Invalid Event", "passphrase": "Passphrase (opsyonal)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Kulang sa bayad", "trade_state_unpaid": "Hindi nabayaran", "trades": "Pangangalakal", + "transaction_cost": "Gastos sa transaksyon", "transaction_details_amount": "Halaga", "transaction_details_copied": "${title} kinopya sa clipboard", "transaction_details_date": "Petsa", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index a56478474..b38cc21af 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Sıkça sorulan sorular", "frozen": "Dondurulmuş", "full_balance": "Tüm bakiye", + "gas_exceeds_allowance": "İşlemin gerektirdiği gaz ödeneği aşar.", "generate_name": "İsim Oluştur", "generating_gift_card": "Hediye Kartı Oluşturuluyor", "get_a": "Bir ", @@ -360,6 +361,7 @@ "incoming": "Gelen", "incorrect_seed": "Girilen metin geçerli değil.", "inputs": "Girişler", + "insufficient_funds_for_tx": "İşlemi başarıyla yürütmek için yeterli fon.", "insufficient_lamport_for_tx": "İşlemi ve işlem ücretini karşılamak için yeterli SOL'unuz yok. Lütfen cüzdanınıza daha fazla SOL ekleyin veya gönderdiğiniz sol miktarını azaltın.", "insufficient_lamports": "İşlemi ve işlem ücretini karşılamak için yeterli SOL'unuz yok. En az ${solValueNeeded} Sol'a ihtiyacınız var. Lütfen cüzdanınıza daha fazla sol ekleyin veya gönderdiğiniz sol miktarını azaltın", "insufficientFundsForRentError": "İşlem ücretini karşılamak ve hesap için kiralamak için yeterli SOL'nuz yok. Lütfen cüzdanınıza daha fazla sol ekleyin veya gönderdiğiniz sol miktarını azaltın", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Bu cüzdanın 12 kelimelik bir tohumu varsa ve Cake'te oluşturulduysa, bu cüzdana Bitcoin YATIRMAYIN. Bu cüzdana aktarılan tüm BTC'ler kaybolabilir. 24 kelimelik yeni bir cüzdan oluşturun (sağ üstteki menüye dokunun, Cüzdanlar'ı seçin, Yeni Cüzdan Oluştur'u seçin, ardından Bitcoin'i seçin) ve BTC'nizi HEMEN oraya taşıyın. Cake'in yeni (24 kelimelik) BTC cüzdanları güvenlidir", "outgoing": "Giden", "outputs": "çıktılar", + "overshot": "Aşmak", "overwrite_amount": "Miktarın üzerine yaz", "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", "passphrase": "Passfrase (isteğe bağlı)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "Eksik ödendi", "trade_state_unpaid": "Ödenmedi", "trades": "Takaslar", + "transaction_cost": "İşlem maliyeti", "transaction_details_amount": "Miktar", "transaction_details_copied": "${title} panoya kopyalandı", "transaction_details_date": "Tarih", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 7e2213a0a..b0384b2c4 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "Часті запитання", "frozen": "Заморожено", "full_balance": "Весь баланс", + "gas_exceeds_allowance": "Газ, необхідний транзакціям, перевищує надбавку.", "generate_name": "Згенерувати назву", "generating_gift_card": "Створення подарункової картки", "get_a": "Отримати ", @@ -360,6 +361,7 @@ "incoming": "Вхідні", "incorrect_seed": "Введений текст невірний.", "inputs": "Вхoди", + "insufficient_funds_for_tx": "Недостатні кошти для успішного виконання транзакції.", "insufficient_lamport_for_tx": "У вас недостатньо SOL, щоб покрити транзакцію та її плату за трансакцію. Будь ласка, додайте до свого гаманця більше SOL або зменшіть суму, яку ви надсилаєте.", "insufficient_lamports": "У вас недостатньо SOL, щоб покрити транзакцію та її плату за трансакцію. Вам потрібно щонайменше ${solValueNeeded} sol. Будь ласка, додайте до свого гаманця більше SOL або зменшіть суму Sol, яку ви надсилаєте", "insufficientFundsForRentError": "У вас недостатньо SOL, щоб покрити плату за транзакцію та оренду на рахунок. Будь ласка, додайте до свого гаманця більше SOL або зменшіть суму, яку ви надсилаєте", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "Якщо цей гаманець має мнемонічну фразу з 12 слів і був створений у Cake, НЕ переводьте біткойни на цей гаманець. Будь-які BTC, переведений на цей гаманець, можуть бути втраченими. Створіть новий гаманець з мнемонічною фразою з 24 слів (торкніться меню у верхньому правому куті, виберіть Гаманці, виберіть Створити новий гаманець, потім виберіть Bitcoin) і НЕГАЙНО переведіть туди свії BTC. Нові (з мнемонічною фразою з 24 слів) гаманці BTC від Cake надійно захищені", "outgoing": "Вихідні", "outputs": "Виходи", + "overshot": "Затьмарювати", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недійсна подія сполучення", "passphrase": "Пасофрази (необов’язково)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "Недоплачена", "trade_state_unpaid": "Неоплачена", "trades": "Торгові операції", + "transaction_cost": "Вартість транзакції", "transaction_details_amount": "Сума", "transaction_details_copied": "${title} скопійовано в буфер обміну", "transaction_details_date": "Дата", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 9dd5ab282..bc9defdfd 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "اکثر پوچھے گئے سوالات", "frozen": "منجمد", "full_balance": "مکمل بیلنس", + "gas_exceeds_allowance": "لین دین کے ذریعہ درکار گیس الاؤنس سے زیادہ ہے۔", "generate_name": "نام پیدا کریں۔", "generating_gift_card": "گفٹ کارڈ تیار کرنا", "get_a": "حاصل", @@ -360,6 +361,7 @@ "incoming": "آنے والا", "incorrect_seed": "درج کردہ متن درست نہیں ہے۔", "inputs": "آدانوں", + "insufficient_funds_for_tx": "لین دین کو کامیابی کے ساتھ انجام دینے کے لئے ناکافی فنڈز۔", "insufficient_lamport_for_tx": "آپ کے پاس ٹرانزیکشن اور اس کے لین دین کی فیس کا احاطہ کرنے کے لئے کافی SOL نہیں ہے۔ برائے مہربانی اپنے بٹوے میں مزید سول شامل کریں یا آپ کو بھیجنے والی سول رقم کو کم کریں۔", "insufficient_lamports": "آپ کے پاس ٹرانزیکشن اور اس کے لین دین کی فیس کا احاطہ کرنے کے لئے کافی SOL نہیں ہے۔ آپ کو کم از کم ${solValueNeeded} sol کی ضرورت ہے۔ برائے مہربانی اپنے بٹوے میں مزید SOL شامل کریں یا آپ جس SOL رقم کو بھیج رہے ہو اسے کم کریں", "insufficientFundsForRentError": "آپ کے پاس ٹرانزیکشن فیس اور اکاؤنٹ کے لئے کرایہ لینے کے ل enough اتنا SOL نہیں ہے۔ برائے مہربانی اپنے بٹوے میں مزید سول شامل کریں یا آپ کو بھیجنے والی سول رقم کو کم کریں", @@ -482,6 +484,7 @@ "outdated_electrum_wallet_receive_warning": "اگر اس پرس میں 12 الفاظ کا بیج ہے اور اسے Cake میں بنایا گیا ہے، تو اس بٹوے میں Bitcoin جمع نہ کریں۔ اس بٹوے میں منتقل کیا گیا کوئی بھی BTC ضائع ہو سکتا ہے۔ ایک نیا 24 الفاظ والا والیٹ بنائیں (اوپر دائیں جانب مینو کو تھپتھپائیں، Wallets کو منتخب کریں، نیا والیٹ بنائیں، پھر Bitcoin کو منتخب کریں) اور فوری طور پر اپنے BTC کو وہاں منتقل کریں۔ Cake کے نئے (24-لفظوں) BTC بٹوے محفوظ ہیں۔", "outgoing": "سبکدوش ہونے والے", "outputs": "نتائج", + "overshot": "اوورشوٹ", "overwrite_amount": "رقم کو اوور رائٹ کریں۔", "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", "passphrase": "پاسفریز (اختیاری)", @@ -830,6 +833,7 @@ "trade_state_underpaid": "کم معاوضہ", "trade_state_unpaid": "بلا معاوضہ", "trades": "تجارت", + "transaction_cost": "لین دین کی لاگت", "transaction_details_amount": "رقم", "transaction_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", "transaction_details_date": "تاریخ", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index b26420fea..85a6547c5 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -325,6 +325,7 @@ "frequently_asked_questions": "Các câu hỏi thường gặp", "frozen": "Đã đóng băng", "full_balance": "Số dư đầy đủ", + "gas_exceeds_allowance": "Gas theo yêu cầu của giao dịch vượt quá trợ cấp.", "generate_name": "Tạo tên", "generating_gift_card": "Đang tạo thẻ quà tặng", "get_a": "Nhận một ", @@ -359,6 +360,7 @@ "incoming": "Đang nhận", "incorrect_seed": "Văn bản nhập không hợp lệ.", "inputs": "Đầu vào", + "insufficient_funds_for_tx": "Không đủ tiền để thực hiện thành công giao dịch.", "insufficient_lamport_for_tx": "Bạn không có đủ SOL để thanh toán giao dịch và phí giao dịch. Vui lòng thêm SOL vào ví của bạn hoặc giảm số lượng SOL bạn đang gửi.", "insufficient_lamports": "Bạn không có đủ SOL để thanh toán giao dịch và phí giao dịch. Bạn cần ít nhất ${solValueNeeded} SOL. Vui lòng thêm SOL vào ví của bạn hoặc giảm số lượng SOL bạn đang gửi", "insufficientFundsForRentError": "Bạn không có đủ SOL để thanh toán phí giao dịch và phí thuê cho tài khoản. Vui lòng thêm SOL vào ví của bạn hoặc giảm số lượng SOL bạn đang gửi", @@ -479,6 +481,7 @@ "outdated_electrum_wallet_receive_warning": "Nếu ví này có hạt giống 12 từ và được tạo trong Cake, ĐỪNG gửi Bitcoin vào ví này. Bất kỳ BTC nào chuyển vào ví này có thể bị mất. Tạo ví 24 từ mới (nhấn menu ở góc trên bên phải, chọn Ví, chọn Tạo Ví Mới, sau đó chọn Bitcoin) và NGAY LẬP TỨC chuyển BTC của bạn vào đó. Ví BTC mới (24 từ) từ Cake là an toàn", "outgoing": "Đang gửi", "outputs": "Đầu ra", + "overshot": "Quá sức", "overwrite_amount": "Ghi đè số tiền", "pairingInvalidEvent": "Sự kiện ghép nối không hợp lệ", "passphrase": "Cụm từ bảo mật (Tùy chọn)", @@ -827,6 +830,7 @@ "trade_state_underpaid": "Thanh toán chưa đủ", "trade_state_unpaid": "Chưa thanh toán", "trades": "Giao dịch", + "transaction_cost": "Chi phí giao dịch", "transaction_details_amount": "Số tiền", "transaction_details_copied": "${title} đã được sao chép vào clipboard", "transaction_details_date": "Ngày", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index eb446e984..1a548438d 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -327,6 +327,7 @@ "frequently_asked_questions": "Àwọn ìbéèrè la máa ń béèrè", "frozen": "Ó l'a tì pa", "full_balance": "Ìyókù owó kíkún", + "gas_exceeds_allowance": "Gaasi ti a beere nipasẹ idunadura ju lọ.", "generate_name": "Ṣẹda Orukọ", "generating_gift_card": "À ń dá káàdì ìrajà t'á lò nínú irú kan ìtajà", "get_a": "Gba ", @@ -361,6 +362,7 @@ "incoming": "Wọ́n tó ń bọ̀", "incorrect_seed": "Ọ̀rọ̀ tí a tẹ̀ kì í ṣe èyí.", "inputs": "Igbewọle", + "insufficient_funds_for_tx": "Awọn owo ti ko to lati ṣe idunadura ni ifijišẹ.", "insufficient_lamport_for_tx": "O ko ni sosi to lati bo idunadura ati idiyele iṣowo rẹ. Fi agbara kun Sol diẹ sii si apamọwọ rẹ tabi dinku sodo naa ti o \\ 'tun n firanṣẹ.", "insufficient_lamports": "O ko ni sosi to lati bo idunadura ati idiyele iṣowo rẹ. O nilo o kere ju ${solValueNeeded}. Fi agbara kun Sol diẹ sii si apamọwọ rẹ tabi dinku soso ti o n firanṣẹ", "insufficientFundsForRentError": "O ko ni Sol kan lati bo owo isanwo naa ki o yalo fun iroyin naa. Fi agbara kun Sol diẹ sii si apamọwọ rẹ tabi dinku soso naa ti o \\ 'tun n firanṣẹ", @@ -481,6 +483,7 @@ "outdated_electrum_wallet_receive_warning": "Ẹ KÒ FI BITCOIN SÍ ÀPAMỌ́WỌ́ YÌÍ t'á ti dá a nínú Cake Wallet àti àpamọ́wọ́ yìí ni hóró ti ọ̀rọ̀ méjìlá. A lè pàdánù BTC t'á ránṣẹ́ sí àpamọ́wọ́ yìí. Ẹ dá àpamọ́wọ́ títun tó ni hóró tó ni ọ̀rọ̀ mẹ́rinlélógún (Ẹ tẹ àkọsílẹ̀ tó wa l’ókè l'ọ́tún nígbàna, ẹ sì yan àwọn àpamọ́wọ́ nígbàna, ẹ sì yan Dá Àpamọ́wọ́ Títun nígbàna, ẹ sì yan Bitcoin) àti sún Bitcoin yín síbẹ̀ ní sinsìn yẹn. Àwọn àpamọ́wọ́ títun (hóró ni ọ̀rọ̀ mẹ́rinlélógún) láti Cake Wallet wa láìléwu.", "outgoing": "Wọ́n tó ń jáde", "outputs": "Awọn iṣan", + "overshot": "Overshot", "overwrite_amount": "Pààrọ̀ iye owó", "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", "passphrase": "Ọrọ kukuru (iyan)", @@ -829,6 +832,7 @@ "trade_state_underpaid": "Ti san iye tó kéré jù", "trade_state_unpaid": "Kò tíì san", "trades": "Àwọn pàṣípààrọ̀", + "transaction_cost": "Oniruuru idiyele", "transaction_details_amount": "Iye owó", "transaction_details_copied": "A ṣeda ${title} sí àkọsílẹ̀", "transaction_details_date": "Ìgbà", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 0d3187dc8..df1ab5b1c 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -326,6 +326,7 @@ "frequently_asked_questions": "常见问题", "frozen": "凍結的", "full_balance": "全部余额", + "gas_exceeds_allowance": "交易要求的气体超出了津贴。", "generate_name": "生成名称", "generating_gift_card": "生成礼品卡", "get_a": "得到一个", @@ -360,6 +361,7 @@ "incoming": "收到", "incorrect_seed": "输入的文字无效。", "inputs": "输入", + "insufficient_funds_for_tx": "资金不足无法成功执行交易。", "insufficient_lamport_for_tx": "您没有足够的溶胶来支付交易及其交易费用。请在您的钱包中添加更多溶胶或减少您发送的溶胶量。", "insufficient_lamports": "您没有足够的溶胶来支付交易及其交易费用。您至少需要${solValueNeeded} sol。请在您的钱包中添加更多溶胶或减少您发送的溶胶量", "insufficientFundsForRentError": "您没有足够的溶胶来支付该帐户的交易费和租金。请在钱包中添加更多溶胶或减少您发送的溶胶量", @@ -480,6 +482,7 @@ "outdated_electrum_wallet_receive_warning": "如果这个钱包有一个 12 字的种子并且是在 Cake 中创建的,不要将比特币存入这个钱包。 任何转移到此钱包的 BTC 都可能丢失。 创建一个新的 24 字钱包(点击右上角的菜单,选择钱包,选择创建新钱包,然后选择比特币)并立即将您的 BTC 移到那里。 Cake 的新(24 字)BTC 钱包是安全的", "outgoing": "发送", "outputs": "输出", + "overshot": "超越", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "配对无效事件", "passphrase": "密码(可选)", @@ -828,6 +831,7 @@ "trade_state_underpaid": "支付不足", "trade_state_unpaid": "未付", "trades": "交易", + "transaction_cost": "交易成本", "transaction_details_amount": "金额", "transaction_details_copied": "${title} 复制到剪切板", "transaction_details_date": "日期", diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index d67ab7605..e17a509d7 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -81,6 +81,7 @@ class SecretKey { SecretKey('etherScanApiKey', () => ''), SecretKey('polygonScanApiKey', () => ''), SecretKey('moralisApiKey', () => ''), + SecretKey('nowNodesApiKey ', () => ''), ]; static final solanaSecrets = [ From 82bad3a951f25f6be16d63c0a1a402445efd41b8 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Wed, 11 Dec 2024 19:30:56 +0200 Subject: [PATCH 07/26] fix regex for xrp and wow --- lib/core/address_validator.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index c122a872b..387b91dcc 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -80,7 +80,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.shib: pattern = '0x[0-9a-zA-Z]+'; case CryptoCurrency.xrp: - pattern = '[0-9a-zA-Z]{34}|X[0-9a-zA-Z]{46}'; + pattern = '[0-9a-zA-Z]{34}|[0-9a-zA-Z]{33}|X[0-9a-zA-Z]{46}'; case CryptoCurrency.xhv: pattern = 'hvx|hvi|hvs[0-9a-zA-Z]+'; case CryptoCurrency.xag: @@ -282,10 +282,14 @@ class AddressValidator extends TextValidator { switch (type) { case CryptoCurrency.xmr: - case CryptoCurrency.wow: pattern = '(4[0-9a-zA-Z]{94})' '|(8[0-9a-zA-Z]{94})' '|([0-9a-zA-Z]{106})'; + case CryptoCurrency.wow: + pattern = '(W[0-9a-zA-Z]{94})' + '|(W[0-9a-zA-Z]{94})' + '|(W[0-9a-zA-Z]{96})' + '|([0-9a-zA-Z]{106})'; case CryptoCurrency.btc: pattern = '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}'; From 6e8cc9c39e938e318950b64ce42b3bcb3cfd3726 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:51:09 +0100 Subject: [PATCH 08/26] CW-854 Monero Wallet Group Fix (#1865) * Fix: Tentative fix to wrong wallet groupings, specifically monero or non bip39 wallet types * fix: Modify logic to filter out single wallets and multi group wallets --------- Co-authored-by: Omar Hatem --- .../wallet_list/wallet_list_view_model.dart | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index c903b535f..407dce55a 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/entities/wallet_group.dart'; import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:cake_wallet/entities/wallet_manager.dart'; +import 'package:cake_wallet/reactions/bip39_wallet_utils.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -90,20 +91,59 @@ abstract class WalletListViewModelBase with Store { multiWalletGroups.clear(); singleWalletsList.clear(); - wallets.addAll( - _walletInfoSource.values - .map((info) => convertWalletInfoToWalletListItem(info)), - ); + for (var info in _walletInfoSource.values) { + wallets.add(convertWalletInfoToWalletListItem(info)); + } //========== Split into shared seed groups and single wallets list _walletManager.updateWalletGroups(); - for (var group in _walletManager.walletGroups) { + final walletGroupsFromManager = _walletManager.walletGroups; + + for (var group in walletGroupsFromManager) { if (group.wallets.length == 1) { - singleWalletsList - .add(convertWalletInfoToWalletListItem(group.wallets.first)); - } else { + singleWalletsList.add(convertWalletInfoToWalletListItem(group.wallets.first)); + continue; + } + + // Identify wallets that should be moved to singleWalletsList using the filters: the type/derivation + final excludedWallets = []; + + for (var wallet in group.wallets) { + // Check for non-BIP39 wallet types + final isNonBIP39 = !isBIP39Wallet(wallet.type); + + // Check for nano derivation type + final isNanoDerivation = wallet.type == WalletType.nano && + wallet.derivationInfo?.derivationType == DerivationType.nano; + + // Check for electrum derivation type + final isElectrumDerivation = + (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) && + wallet.derivationInfo?.derivationType == DerivationType.electrum; + + if (isNonBIP39 || isNanoDerivation || isElectrumDerivation) { + excludedWallets.add(wallet); + } + } + + // Add excluded wallets to singleWalletsList + for (var excludedWallet in excludedWallets) { + singleWalletsList.add(convertWalletInfoToWalletListItem(excludedWallet)); + } + + // Remove excluded wallets from the group's wallets to avoid duplication + group.wallets.removeWhere((wallet) { + return excludedWallets.any((excluded) => excluded.address == wallet.address); + }); + + // Check if the group has more than one wallet after the excluded wallets are removed. + if (group.wallets.length > 1) { + //Add the entire group to the multi wallet group list since its still a multi wallet multiWalletGroups.add(group); + } else if (group.wallets.length == 1) { + // Add the group to the wallet left to the single wallets list + singleWalletsList.add(convertWalletInfoToWalletListItem(group.wallets.first)); } } } From 699f591113a2e0abffd584e89a45202eb70358e0 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 11 Dec 2024 20:26:13 +0100 Subject: [PATCH 09/26] fix: Tentative fix for transaction history items overlap across wallet types (#1864) --- cw_bitcoin/lib/electrum_transaction_history.dart | 5 ++++- cw_evm/lib/evm_chain_transaction_history.dart | 6 +++++- cw_nano/lib/nano_transaction_history.dart | 5 ++++- cw_solana/lib/solana_transaction_history.dart | 5 ++++- cw_tron/lib/tron_transaction_history.dart | 5 ++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index 658f83f8a..d096d0e7b 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -31,7 +31,10 @@ abstract class ElectrumTransactionHistoryBase String _password; int _height; - Future init() async => await _load(); + Future init() async { + clear(); + await _load(); + } @override void addOne(ElectrumTransactionInfo transaction) => transactions[transaction.id] = transaction; diff --git a/cw_evm/lib/evm_chain_transaction_history.dart b/cw_evm/lib/evm_chain_transaction_history.dart index c4d91783f..4a05746da 100644 --- a/cw_evm/lib/evm_chain_transaction_history.dart +++ b/cw_evm/lib/evm_chain_transaction_history.dart @@ -34,7 +34,10 @@ abstract class EVMChainTransactionHistoryBase //! Common methods across all child classes - Future init() async => await _load(); + Future init() async { + clear(); + await _load(); + } @override Future save() async { @@ -81,6 +84,7 @@ abstract class EVMChainTransactionHistoryBase _update(tx); } } + print('doneee'); } catch (e) { log(e.toString()); } diff --git a/cw_nano/lib/nano_transaction_history.dart b/cw_nano/lib/nano_transaction_history.dart index 7b4c5bc12..2b551ffa6 100644 --- a/cw_nano/lib/nano_transaction_history.dart +++ b/cw_nano/lib/nano_transaction_history.dart @@ -28,7 +28,10 @@ abstract class NanoTransactionHistoryBase extends TransactionHistoryBase init() async => await _load(); + Future init() async { + clear(); + await _load(); + } @override Future save() async { diff --git a/cw_solana/lib/solana_transaction_history.dart b/cw_solana/lib/solana_transaction_history.dart index 761753f06..62b9db8f7 100644 --- a/cw_solana/lib/solana_transaction_history.dart +++ b/cw_solana/lib/solana_transaction_history.dart @@ -26,7 +26,10 @@ abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase init() async => await _load(); + Future init() async { + clear(); + await _load(); + } @override Future save() async { diff --git a/cw_tron/lib/tron_transaction_history.dart b/cw_tron/lib/tron_transaction_history.dart index 9d226c09c..c940c7708 100644 --- a/cw_tron/lib/tron_transaction_history.dart +++ b/cw_tron/lib/tron_transaction_history.dart @@ -25,7 +25,10 @@ abstract class TronTransactionHistoryBase extends TransactionHistoryBase init() async => await _load(); + Future init() async { + clear(); + await _load(); + } @override Future save() async { From 329a1fd6de7637f8afec6e7ab7859730aaac36f7 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 11 Dec 2024 21:19:52 +0100 Subject: [PATCH 10/26] CW-703: Better Seed UI/UX (#1868) * feat: Switch UI for seeds display * feat: Add localization for disclaimer text * fix: Modify color for warning on seeds screen * Fix: Adjust UI styling for seed page * chore: Revert podfile.lock * Fix column colors * Fix more colors --------- Co-authored-by: tuxpizza --- lib/src/screens/seed/wallet_seed_page.dart | 266 +++++++++++++-------- lib/view_model/wallet_seed_view_model.dart | 4 + 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_hy.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_vi.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 30 files changed, 196 insertions(+), 102 deletions(-) diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index 10160839c..05a44281a 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -1,5 +1,5 @@ -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; @@ -15,7 +15,8 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; -import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; + +import '../../../themes/extensions/menu_theme.dart'; class WalletSeedPage extends BasePage { WalletSeedPage(this.walletSeedViewModel, {required this.isNewWalletCreated}); @@ -92,118 +93,179 @@ class WalletSeedPage extends BasePage { @override Widget body(BuildContext context) { - final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; - return WillPopScope( - onWillPop: () async => false, - child: Container( - padding: EdgeInsets.all(24), - alignment: Alignment.center, - child: ConstrainedBox( - constraints: - BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ConstrainedBox( - constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), - child: AspectRatio(aspectRatio: 1, child: image), - ), - Observer(builder: (_) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - key: ValueKey('wallet_seed_page_wallet_name_text_key'), - walletSeedViewModel.name, - style: TextStyle( + onWillPop: () async => false, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8), + alignment: Alignment.center, + child: ConstrainedBox( + constraints: + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Observer( + builder: (_) { + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: currentTheme.type == ThemeType.dark + ? Color.fromRGBO(126, 116, 59, 1) + : Color.fromRGBO(189, 169, 90, 1), + borderRadius: BorderRadius.all(Radius.circular(12)), + border: Border.all( + color: currentTheme.type == ThemeType.dark + ? Color.fromRGBO(171, 171, 41, 1) + : Color.fromRGBO(125, 122, 15, 1), + width: 2.0, + )), + child: Row( + children: [ + Icon( + Icons.warning_amber_rounded, + size: 64, + color: Colors.white.withOpacity(0.75), + ), + SizedBox(width: 8), + Expanded( + child: Text( + S.current.cake_seeds_save_disclaimer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w800, + color: currentTheme.type == ThemeType.dark + ? Colors.white.withOpacity(0.75) + : Colors.white.withOpacity(0.85), + ), + ), + ), + ], + ), + ), + SizedBox(height: 32), + Text( + key: ValueKey('wallet_seed_page_wallet_name_text_key'), + walletSeedViewModel.name, + style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.titleColor), - ), - Padding( - padding: EdgeInsets.only(top: 20, left: 16, right: 16), - child: Text( - key: ValueKey('wallet_seed_page_wallet_seed_text_key'), - walletSeedViewModel.seed, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: - Theme.of(context).extension()!.secondaryTextColor), + color: Theme.of(context).extension()!.titleColor, + ), ), - ) - ], - ); - }), - Column( - children: [ - isNewWalletCreated - ? Padding( - padding: EdgeInsets.only(bottom: 43, left: 43, right: 43), - child: Text( - key: ValueKey( - 'wallet_seed_page_wallet_seed_reminder_text_key', - ), - S.of(context).seed_reminder, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .extension()! - .detailsTitlesColor, - ), + SizedBox(height: 24), + Expanded( + child: GridView.builder( + padding: const EdgeInsets.symmetric(horizontal: 4), + itemCount: walletSeedViewModel.seedSplit.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: walletSeedViewModel.columnCount, + childAspectRatio: 3.6, + mainAxisSpacing: 8.0, + crossAxisSpacing: 8.0, ), - ) - : Offstage(), - Row( - mainAxisSize: MainAxisSize.max, - children: [ - Flexible( - child: Container( - padding: EdgeInsets.only(right: 8.0), - child: PrimaryButton( - key: ValueKey('wallet_seed_page_save_seeds_button_key'), + itemBuilder: (context, index) { + final item = walletSeedViewModel.seedSplit[index]; + final numberCount = index + 1; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 4), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Theme.of(context).cardColor, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 20, + child: Text( + numberCount.toString(), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + color: Theme.of(context).extension()!.buttonTextColor.withOpacity(0.5) + ), + ), + ), + const SizedBox(width: 8), + Text( + '${item[0].toUpperCase()}${item.substring(1)}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + color: Theme.of(context).extension()!.buttonTextColor + ), + ), + ], + ), + ); + }, + ), + ), + ], + ), + ); + }, + ), + Column( + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: PrimaryButton( + key: ValueKey('wallet_seed_page_save_seeds_button_key'), + onPressed: () { + ShareUtil.share( + text: walletSeedViewModel.seed, + context: context, + ); + }, + text: S.of(context).save, + color: Theme.of(context).cardColor, + textColor: currentTheme.type == ThemeType.dark + ? Theme.of(context).extension()!.textColor + : Theme.of(context).extension()!.buttonTextColor, + ), + ), + ), + Flexible( + child: Container( + padding: EdgeInsets.only(left: 8.0), + child: Builder( + builder: (context) => PrimaryButton( + key: ValueKey('wallet_seed_page_copy_seeds_button_key'), onPressed: () { - ShareUtil.share( - text: walletSeedViewModel.seed, - context: context, + ClipboardUtil.setSensitiveDataToClipboard( + ClipboardData(text: walletSeedViewModel.seed), ); + showBar(context, S.of(context).copied_to_clipboard); }, - text: S.of(context).save, - color: Colors.green, + text: S.of(context).copy, + color: Theme.of(context).primaryColor, textColor: Colors.white, ), ), ), - Flexible( - child: Container( - padding: EdgeInsets.only(left: 8.0), - child: Builder( - builder: (context) => PrimaryButton( - key: ValueKey('wallet_seed_page_copy_seeds_button_key'), - onPressed: () { - ClipboardUtil.setSensitiveDataToClipboard( - ClipboardData(text: walletSeedViewModel.seed), - ); - showBar(context, S.of(context).copied_to_clipboard); - }, - text: S.of(context).copy, - color: Theme.of(context).extension()!.indicatorsColor, - textColor: Colors.white, - ), - ), - ), - ) - ], - ) - ], - ) - ], - ), + ) + ], + ), + SizedBox(height: 24), + ], + ) + ], ), - )); + ), + ), + ); } } diff --git a/lib/view_model/wallet_seed_view_model.dart b/lib/view_model/wallet_seed_view_model.dart index 8923a99da..c13dba716 100644 --- a/lib/view_model/wallet_seed_view_model.dart +++ b/lib/view_model/wallet_seed_view_model.dart @@ -15,4 +15,8 @@ abstract class WalletSeedViewModelBase with Store { @observable String seed; + + List get seedSplit => seed.split(' '); + + int get columnCount => seedSplit.length <= 16 ? 2 : 3; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 1b1f37e1e..b8e476e4c 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "شراء بطاقات مسبقة الدفع وبطاقات الهدايا في جميع أنحاء العالم", "cake_pay_web_cards_subtitle": "اشتري بطاقات مدفوعة مسبقا وبطاقات هدايا في جميع أنحاء العالم", "cake_pay_web_cards_title": "بطاقات Cake Pay Web", + "cake_seeds_save_disclaimer": "يرجى حفظ هذه الكلمات في مكان آمن! إذا فقدت الوصول إلى محفظتك ، فإن دعم محفظة الكيك لا يمكن أن يساعدك", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "آسف ، بطاقة الهدايا هذه غير متوفرة على iOS. يمكنك شرائه على Android أو من خلال موقعنا بدلاً من ذلك.", "cakepay_prepaid_card": "بطاقة ائتمان CakePay مسبقة الدفع", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 36ecd4b5d..91a718f91 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Купете предплатени карти и карти за подаръци в световен мащаб", "cake_pay_web_cards_subtitle": "Купете световно признати предплатени и гифт карти", "cake_pay_web_cards_title": "Cake Pay Онлайн Карти", + "cake_seeds_save_disclaimer": "Моля, запазете тези думи на сигурно място! Ако загубите достъп до портфейла си, поддръжката на портфейла за торти не може да ви помогне", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "За съжаление тази карта за подарък не се предлага в iOS. Можете да го закупите на Android или чрез нашия уебсайт вместо това.", "cakepay_prepaid_card": "CakePay предплатена дебитна карта", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index af91ea643..d2ca2def5 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Kupte si celosvětové předplacené karty a dárkové karty", "cake_pay_web_cards_subtitle": "Kupte si celosvětové předplacené a dárkové karty", "cake_pay_web_cards_title": "Cake Pay webové karty", + "cake_seeds_save_disclaimer": "Uložte tato slova na bezpečném místě! Pokud ztratíte přístup k vaší peněžence, podpora peněženky dortu vám nemůže pomoci", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Je nám líto, tato dárková karta není k dispozici na iOS. Místo toho si jej můžete zakoupit na Androidu nebo prostřednictvím našeho webu.", "cakepay_prepaid_card": "CakePay předplacená debetní karta", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f09b8c714..f5e2a3879 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Kaufen Sie weltweite Prepaid-Karten und Geschenkkarten", "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten", "cake_pay_web_cards_title": "Cake Pay-Webkarten", + "cake_seeds_save_disclaimer": "Bitte speichern Sie diese Wörter an einem sicheren Ort! Wenn Sie den Zugang zu Ihrer Brieftasche verlieren, kann Ihnen die Stütze der Kuchenbrieftasche nicht helfen", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Entschuldigung, diese Geschenkkarte ist auf iOS nicht erhältlich. Sie können es stattdessen auf Android oder über unsere Website kaufen.", "cakepay_prepaid_card": "CakePay-Prepaid-Debitkarte", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 86d807d8f..0168f7951 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Buy worldwide prepaid cards and gift cards", "cake_pay_web_cards_subtitle": "Buy worldwide prepaid cards and gift cards", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "Please save these words in a secure place! If you lose access to your wallet, Cake Wallet support CANNOT help you", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Sorry, this gift card is not available on iOS. You can purchase it on Android or through our website instead.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4c0d16b98..12ea9bbf3 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Compra tarjetas prepagadas y tarjetas de regalo en todo el mundo", "cake_pay_web_cards_subtitle": "Compra tarjetas de prepago y tarjetas de regalo en todo el mundo", "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", + "cake_seeds_save_disclaimer": "¡Guarde estas palabras en un lugar seguro! Si pierde acceso a su billetera, el soporte de la billetera de pastel no puede ayudarlo", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Lo siento, esta tarjeta de regalo no está disponible en iOS. Puede comprarlo en Android o a través de nuestro sitio web.", "cakepay_prepaid_card": "Tarjeta de Débito Prepago CakePay", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index c15366f5a..a8b1fc48b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Achetez des cartes et des cartes-cadeaux prépayées mondiales", "cake_pay_web_cards_subtitle": "Achetez des cartes prépayées et des cartes-cadeaux dans le monde entier", "cake_pay_web_cards_title": "Cartes Web Cake Pay", + "cake_seeds_save_disclaimer": "Veuillez enregistrer ces mots dans un endroit sécurisé! Si vous perdez accès à votre portefeuille, le support de portefeuille à gâteau ne peut pas vous aider", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Désolé, cette carte-cadeau n'est pas disponible sur iOS. Vous pouvez l'acheter sur Android ou via notre site Web à la place.", "cakepay_prepaid_card": "Carte de débit prépayée Cake Pay", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index d95f87bbf..24330f348 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Sayi katunan shirye-shiryen duniya da katunan kyauta", "cake_pay_web_cards_subtitle": "Sayi katunan da aka riga aka biya na duniya da katunan kyauta", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "Da fatan za a ceci waɗannan kalmomin a cikin amintaccen wuri! Idan ka rasa damar zuwa Wallet, Tallafin Wall Wallet ba zai iya taimaka maka ba", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Yi haƙuri, wannan katin kyautar ba a samuwa akan iOS. Kuna iya sayan shi a kan Android ko ta yanar gizo a maimakon.", "cakepay_prepaid_card": "Katin zare kudi na CakePay", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 6f655fe73..5d226dfb6 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "दुनिया भर में प्रीपेड कार्ड और उपहार कार्ड खरीदें", "cake_pay_web_cards_subtitle": "दुनिया भर में प्रीपेड कार्ड और गिफ्ट कार्ड खरीदें", "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", + "cake_seeds_save_disclaimer": "कृपया इन शब्दों को सुरक्षित स्थान पर सहेजें! यदि आप अपने बटुए तक पहुंच खो देते हैं, तो केक वॉलेट समर्थन आपकी मदद नहीं कर सकता है", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "क्षमा करें, यह उपहार कार्ड iOS पर उपलब्ध नहीं है। आप इसे Android पर या हमारी वेबसाइट के बजाय खरीद सकते हैं।", "cakepay_prepaid_card": "केकपे प्रीपेड डेबिट कार्ड", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 67a41ab2a..ed60e6ee6 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Kupite svjetske unaprijed plaćene kartice i poklon kartice", "cake_pay_web_cards_subtitle": "Kupujte prepaid kartice i poklon kartice diljem svijeta", "cake_pay_web_cards_title": "Cake Pay Web kartice", + "cake_seeds_save_disclaimer": "Molimo spremite ove riječi na sigurno mjesto! Ako izgubite pristup vašem novčaniku, podrška za novčanik za kolače ne može vam pomoći", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Oprostite, ova poklon kartica nije dostupna na iOS -u. Umjesto toga, možete ga kupiti na Androidu ili putem naše web stranice.", "cakepay_prepaid_card": "CakePay unaprijed plaćena debitna kartica", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index c6e5b2d13..41b18f59e 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Գնեք համաշխարհային նախավճարային քարտեր և նվեր քարտեր", "cake_pay_web_cards_subtitle": "Գնեք համաշխարհային նախավճարային քարտեր և նվեր քարտեր", "cake_pay_web_cards_title": "Cake Pay Վեբ Քարտեր", + "cake_seeds_save_disclaimer": "Խնդրում ենք պահպանել այս բառերը անվտանգ տեղում: Եթե ​​ձեր դրամապանակը կորցնեք մուտքը, տորթի դրամապանակի աջակցությունը չի կարող օգնել ձեզ", "cake_wallet": "Cake Գաղտնապահոց", "cakepay_ios_not_available": "Ներեցեք, այս նվեր քարտը հասանելի չէ iOS- ում: Փոխարենը կարող եք այն գնել Android- ում կամ մեր կայքում:", "cakepay_prepaid_card": "CakePay Նախավճարային Դեբետային Քարտ", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 2ffe0b955..ef64b7044 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Beli kartu prabayar di seluruh dunia dan kartu hadiah", "cake_pay_web_cards_subtitle": "Beli kartu prabayar dan kartu hadiah secara global", "cake_pay_web_cards_title": "Kartu Web Cake Pay", + "cake_seeds_save_disclaimer": "Harap simpan kata -kata ini di tempat yang aman! Jika Anda kehilangan akses ke dompet Anda, dukungan dompet kue tidak dapat membantu Anda", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Maaf, kartu hadiah ini tidak tersedia di iOS. Anda dapat membelinya di Android atau melalui situs web kami sebagai gantinya.", "cakepay_prepaid_card": "Kartu Debit Prabayar CakePay", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 4dc5662a8..6a508822a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Acquista carte prepagate in tutto il mondo e carte regalo", "cake_pay_web_cards_subtitle": "Acquista carte prepagate e carte regalo in tutto il mondo", "cake_pay_web_cards_title": "Carte Web Cake Pay", + "cake_seeds_save_disclaimer": "Si prega di salvare queste parole in un posto sicuro! Se perdi l'accesso al tuo portafoglio, il supporto per il portafoglio della torta non può aiutarti", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Mi dispiace, questa carta regalo non è disponibile su iOS. Puoi acquistarlo su Android o tramite il nostro sito Web.", "cakepay_prepaid_card": "Carta di debito prepagata CakePay", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 59fbb7adf..177171a50 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "世界中のプリペイドカードとギフトカードを購入します", "cake_pay_web_cards_subtitle": "世界中のプリペイド カードとギフト カードを購入する", "cake_pay_web_cards_title": "Cake Pay ウェブカード", + "cake_seeds_save_disclaimer": "これらの言葉を安全な場所に保存してください!財布へのアクセスを失った場合、ケーキウォレットのサポートはあなたを助けることができません", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "申し訳ありませんが、このギフトカードはiOSでは利用できません。代わりにAndroidまたは当社のWebサイトから購入できます。", "cakepay_prepaid_card": "CakePayプリペイドデビットカード", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2e7793edb..fd66d0010 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "전세계 선불 카드와 기프트 카드를 구입하십시오", "cake_pay_web_cards_subtitle": "전 세계 선불 카드 및 기프트 카드 구매", "cake_pay_web_cards_title": "케이크페이 웹카드", + "cake_seeds_save_disclaimer": "이 단어를 안전한 장소에 저장하십시오! 지갑에 대한 접근이 손실되면 케이크 지갑 지지대가 도움이되지 않습니다.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "죄송합니다.이 기프트 카드는 iOS에서 사용할 수 없습니다. Android 또는 웹 사이트를 통해 구매할 수 있습니다.", "cakepay_prepaid_card": "CakePay 선불 직불 카드", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index f86beb0f7..ae007e487 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Worldwide ကြိုတင်ငွေဖြည့်ကဒ်များနှင့်လက်ဆောင်ကဒ်များကို 0 ယ်ပါ", "cake_pay_web_cards_subtitle": "ကမ္ဘာတစ်ဝှမ်း ကြိုတင်ငွေပေးကတ်များနှင့် လက်ဆောင်ကတ်များကို ဝယ်ယူပါ။", "cake_pay_web_cards_title": "Cake Pay ဝဘ်ကတ်များ", + "cake_seeds_save_disclaimer": "ကျေးဇူးပြုပြီးဒီစကားလုံးတွေကိုလုံခြုံတဲ့နေရာမှာသိမ်းထားပါ။ သင်၏ပိုက်ဆံအိတ်ကိုသင်လက်လှမ်းမမီပါကကိတ်မုန့်ပိုက်ဆံအိတ်အထောက်အပံ့သည်သင့်ကိုမကူညီနိုင်ပါ", "cake_wallet": "Cake ပိုက်ဆံအိတ်", "cakepay_ios_not_available": "တောင်းပန်ပါတယ်, ဒီလက်ဆောင်ကဒ်ကို iOS မှာမရနိုင်ပါ။ ၎င်းကို Android တွင်သို့မဟုတ်ကျွန်ုပ်တို့၏ဝက်ဘ်ဆိုက်တွင် 0 ယ်နိုင်သည်။", "cakepay_prepaid_card": "CakePay ကြိုတင်ငွေဖြည့်ဒက်ဘစ်ကတ်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 7433972a4..6343f4dd0 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Koop wereldwijde prepaid -kaarten en cadeaubonnen", "cake_pay_web_cards_subtitle": "Koop wereldwijd prepaidkaarten en cadeaubonnen", "cake_pay_web_cards_title": "Cake Pay-webkaarten", + "cake_seeds_save_disclaimer": "Bewaar deze woorden op een veilige plek! Als u de toegang tot uw portemonnee verliest, kan ondersteuning voor cake -portemonnee u niet helpen", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Sorry, deze cadeaubon is niet beschikbaar op iOS. U kunt het in plaats daarvan kopen op Android of via onze website.", "cakepay_prepaid_card": "CakePay Prepaid Debetkaart", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index a2cd61713..6afe3b932 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Kup na całym świecie karty przedpłacone i karty podarunkowe", "cake_pay_web_cards_subtitle": "Kupuj na całym świecie karty przedpłacone i karty podarunkowe", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "Zapisz te słowa w bezpiecznym miejscu! Jeśli stracisz dostęp do portfela, wsparcie portfela ciasta nie może ci pomóc", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Przepraszam, ta karta podarunkowa nie jest dostępna na iOS. Zamiast tego możesz go kupić na Android lub za pośrednictwem naszej strony internetowej.", "cakepay_prepaid_card": "Przedpłacona karta debetowa CakePay", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 04d39d57b..85fafc590 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Compre cartões pré -pagos em todo o mundo e cartões -presente", "cake_pay_web_cards_subtitle": "Compre cartões pré-pagos e cartões-presente em todo o mundo", "cake_pay_web_cards_title": "Cartões Cake Pay Web", + "cake_seeds_save_disclaimer": "Por favor, salve estas palavras em um local seguro! Se você perder o acesso à sua carteira, o suporte da carteira de bolo não poderá ajudá -lo", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Desculpe, este cartão -presente não está disponível no iOS. Você pode comprá -lo no Android ou através do nosso site.", "cakepay_prepaid_card": "Cartão de débito pré-pago CakePay", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 1bb0a9ce3..07d8f39ce 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Купить карты с предоплатой и подарочными картами по всему миру", "cake_pay_web_cards_subtitle": "Покупайте карты предоплаты и подарочные карты по всему миру", "cake_pay_web_cards_title": "Веб-карты Cake Pay", + "cake_seeds_save_disclaimer": "Пожалуйста, сохраните эти слова в безопасном месте! Если вы теряете доступ к своему кошельку, поддержка кошелька для торта не может вам помочь", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Извините, эта подарочная карта недоступна на iOS. Вместо этого вы можете приобрести его на Android или через наш веб -сайт.", "cakepay_prepaid_card": "Предоплаченная дебетовая карта CakePay", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index aeeaf6b5f..f938576dd 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "ซื้อบัตรเติมเงินและบัตรของขวัญทั่วโลก", "cake_pay_web_cards_subtitle": "ซื้อบัตรพร้อมเงินระดับโลกและบัตรของขวัญ", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "โปรดบันทึกคำเหล่านี้ในสถานที่ที่ปลอดภัย! หากคุณสูญเสียการเข้าถึงกระเป๋าเงินของคุณการสนับสนุนกระเป๋าเงินเค้กไม่สามารถช่วยคุณได้", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "ขออภัยบัตรของขวัญนี้ไม่มีใน iOS คุณสามารถซื้อได้บน Android หรือผ่านเว็บไซต์ของเราแทน", "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e0ae3f471..2234d02b1 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", "cake_pay_web_cards_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_seeds_save_disclaimer": "Mangyaring i -save ang mga salitang ito sa isang ligtas na lugar! Kung nawalan ka ng pag -access sa iyong pitaka, hindi makakatulong sa iyo ang suporta ng wallet ng cake", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Paumanhin, ang gift card na ito ay hindi magagamit sa iOS. Maaari mo itong bilhin sa Android o sa pamamagitan ng aming website sa halip.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b38cc21af..83f423b59 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Dünya çapında ön ödemeli kartlar ve hediye kartları satın alın", "cake_pay_web_cards_subtitle": "Dünya çapında ön ödemeli kartlar ve hediye kartları satın alın", "cake_pay_web_cards_title": "Cake Pay Web Kartları", + "cake_seeds_save_disclaimer": "Lütfen bu kelimeleri güvenli bir yerde kaydedin! Cüzdanınıza erişimi kaybederseniz, kek cüzdan desteği size yardımcı olamaz", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Üzgünüm, bu hediye kartı iOS'ta mevcut değil. Bunun yerine Android'de veya web sitemizden satın alabilirsiniz.", "cakepay_prepaid_card": "CakePay Ön Ödemeli Kart", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b0384b2c4..b70f58c88 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Купіть у всьому світі передплачені картки та подарункові картки", "cake_pay_web_cards_subtitle": "Купуйте передоплачені та подарункові картки по всьому світу", "cake_pay_web_cards_title": "Веб-картки Cake Pay", + "cake_seeds_save_disclaimer": "Збережіть ці слова в безпечному місці! Якщо ви втрачаєте доступ до свого гаманця, підтримка гаманця тортів не може вам допомогти", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Вибачте, ця подарункова карта недоступна на iOS. Ви можете придбати його на Android або через наш веб -сайт.", "cakepay_prepaid_card": "Передплачена дебетова картка CakePay", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index bc9defdfd..78443c803 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈ خریدیں", "cake_pay_web_cards_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈز خریدیں۔", "cake_pay_web_cards_title": "Cake پے ویب کارڈز", + "cake_seeds_save_disclaimer": "براہ کرم ان الفاظ کو ایک محفوظ جگہ پر محفوظ کریں! اگر آپ اپنے بٹوے تک رسائی کھو دیتے ہیں تو ، کیک پرس کی مدد آپ کی مدد نہیں کرسکتی ہے", "cake_wallet": "Cake والیٹ", "cakepay_ios_not_available": "معذرت ، یہ گفٹ کارڈ iOS پر دستیاب نہیں ہے۔ اس کے بجائے آپ اسے اینڈروئیڈ پر یا ہماری ویب سائٹ کے ذریعے خرید سکتے ہیں۔", "cakepay_prepaid_card": "Cake پے پری پیڈ ڈیبٹ کارڈ", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 85a6547c5..7491263b4 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Mua thẻ trả trước toàn cầu và thẻ quà tặng", "cake_pay_web_cards_subtitle": "Mua thẻ trả trước toàn cầu và thẻ quà tặng", "cake_pay_web_cards_title": "Thẻ Cake Pay Web", + "cake_seeds_save_disclaimer": "Vui lòng lưu những từ này ở một nơi an toàn! Nếu bạn mất quyền truy cập vào ví của mình, hỗ trợ ví tiền không thể giúp bạn", "cake_wallet": "Ví Cake", "cakepay_ios_not_available": "Xin lỗi, thẻ quà tặng này không có sẵn trên iOS. Thay vào đó, bạn có thể mua nó trên Android hoặc thông qua trang web của chúng tôi.", "cakepay_prepaid_card": "Thẻ Ghi Nợ Trả Trước CakePay", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 1a548438d..f51c83e1c 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "Ra awọn kaadi ti a san ni agbaye ati awọn kaadi ẹbun", "cake_pay_web_cards_subtitle": "Ra àwọn káàdì ìrajà t'á lò nínú ìtajà kan àti àwọn káàdì náà t'á lè lò níbikíbi", "cake_pay_web_cards_title": "Àwọn káàdì wẹ́ẹ̀bù ti Cake Pay", + "cake_seeds_save_disclaimer": "Jọwọ fi awọn ọrọ wọnyi pamọ ni aaye aabo! Ti o ba padanu wiwọle si apamọwọ rẹ, atilẹyin apamọwọ oyinbo ti a ko le ran ọ lọwọ", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Ma binu, kaadi ẹbun yii ko wa lori iOS. O le ra lori Android tabi nipasẹ oju opo wẹẹbu wa dipo.", "cakepay_prepaid_card": "Káàdì ìrajà ti CakePay", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index df1ab5b1c..7e36289ef 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -101,6 +101,7 @@ "cake_pay_subtitle": "购买全球预付费卡和礼品卡", "cake_pay_web_cards_subtitle": "购买全球预付卡和礼品卡", "cake_pay_web_cards_title": "蛋糕支付网络卡", + "cake_seeds_save_disclaimer": "请在安全的地方保存这些单词!如果您无法使用钱包,蛋糕钱包的支撑就无法帮助您", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "抱歉,这张礼品卡在iOS上不可用。您可以在Android或通过我们的网站上购买它。", "cakepay_prepaid_card": "CakePay 预付借记卡", From e2a1d865afe2380cc9e814270ea98bfdf5456519 Mon Sep 17 00:00:00 2001 From: cyan Date: Wed, 11 Dec 2024 15:31:01 -0500 Subject: [PATCH 11/26] CW-673: Save Haven seeds to show it to the user after Haven removal (#1518) * haven: backup seeds * haven backup fixes * ci fix * reorder build script * disable haven * properly call cw_haven code * [skip ci] update PR * Update evm_chain_transaction_history.dart remove print --------- Co-authored-by: Omar Hatem --- cw_core/lib/hive_type_ids.dart | 3 +- cw_evm/lib/evm_chain_transaction_history.dart | 1 - lib/entities/default_settings_migration.dart | 32 +++++++++++++------ lib/entities/haven_seed_store.dart | 19 +++++++++++ lib/haven/cw_haven.dart | 17 ++++++++++ lib/main.dart | 18 +++++++++-- tool/configure.dart | 11 ++++++- 7 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 lib/entities/haven_seed_store.dart diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index 6432c484b..0899ac665 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -18,4 +18,5 @@ const SPL_TOKEN_TYPE_ID = 16; const DERIVATION_INFO_TYPE_ID = 17; const TRON_TOKEN_TYPE_ID = 18; const HARDWARE_WALLET_TYPE_TYPE_ID = 19; -const MWEB_UTXO_TYPE_ID = 20; \ No newline at end of file +const MWEB_UTXO_TYPE_ID = 20; +const HAVEN_SEED_STORE_TYPE_ID = 21; \ No newline at end of file diff --git a/cw_evm/lib/evm_chain_transaction_history.dart b/cw_evm/lib/evm_chain_transaction_history.dart index 4a05746da..7c46ebecc 100644 --- a/cw_evm/lib/evm_chain_transaction_history.dart +++ b/cw_evm/lib/evm_chain_transaction_history.dart @@ -84,7 +84,6 @@ abstract class EVMChainTransactionHistoryBase _update(tx); } } - print('doneee'); } catch (e) { log(e.toString()); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index d91ad6442..92cb752cd 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,9 +1,13 @@ import 'dart:convert'; import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/root_dir.dart'; @@ -52,7 +56,8 @@ Future defaultSettingsMigration( required Box powNodes, required Box walletInfoSource, required Box tradeSource, - required Box contactSource}) async { + required Box contactSource, + required Box havenSeedStore}) async { if (Platform.isIOS) { await ios_migrate_v1(walletInfoSource, tradeSource, contactSource); } @@ -290,20 +295,22 @@ Future defaultSettingsMigration( ); break; case 45: - await updateWalletTypeNodesWithNewNode( + await _backupHavenSeeds(havenSeedStore); + + updateWalletTypeNodesWithNewNode( newNodeUri: 'matic.nownodes.io', sharedPreferences: sharedPreferences, nodes: nodes, type: WalletType.polygon, useSSL: true, ); - await updateWalletTypeNodesWithNewNode( - newNodeUri: 'eth.nownodes.io', - sharedPreferences: sharedPreferences, - nodes: nodes, - type: WalletType.ethereum, - useSSL: true, - ); + updateWalletTypeNodesWithNewNode( + newNodeUri: 'eth.nownodes.io', + sharedPreferences: sharedPreferences, + nodes: nodes, + type: WalletType.ethereum, + useSSL: true, + ); default: break; } @@ -318,6 +325,13 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future _backupHavenSeeds(Box havenSeedStore) async { + final future = haven?.backupHavenSeeds(havenSeedStore); + if (future != null) { + await future; + } + return; +} /// generic function for changing any wallet default node /// instead of making a new function for each change Future _changeDefaultNode({ diff --git a/lib/entities/haven_seed_store.dart b/lib/entities/haven_seed_store.dart new file mode 100644 index 000000000..f899799d8 --- /dev/null +++ b/lib/entities/haven_seed_store.dart @@ -0,0 +1,19 @@ +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; + +part 'haven_seed_store.g.dart'; + +@HiveType(typeId: HavenSeedStore.typeId) +class HavenSeedStore extends HiveObject { + HavenSeedStore({required this.id, this.seed}); + + static const typeId = HAVEN_SEED_STORE_TYPE_ID; + static const boxName = 'HavenSeedStore'; + static const boxKey = 'havenSeedStoreKey'; + + @HiveField(0, defaultValue: '') + String id; + + @HiveField(2) + String? seed; +} diff --git a/lib/haven/cw_haven.dart b/lib/haven/cw_haven.dart index 57c4e49c3..c54e47eb4 100644 --- a/lib/haven/cw_haven.dart +++ b/lib/haven/cw_haven.dart @@ -307,6 +307,23 @@ class CWHaven extends Haven { return havenTransactionInfo.accountIndex; } + @override + Future backupHavenSeeds(Box havenSeedStore) async { + final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); + final wallets = walletInfoSource.values + .where((element) => element.type == WalletType.haven); + for (var w in wallets) { + final walletService = HavenWalletService(walletInfoSource); + final flutterSecureStorage = secureStorageShared; + final keyService = KeyService(flutterSecureStorage); + final password = await keyService.getWalletPassword(walletName: w.name); + final wallet = await walletService.openWallet(w.name, password); + await havenSeedStore.add(HavenSeedStore(id: wallet.id, seed: wallet.seed)); + wallet.close(); + } + await havenSeedStore.flush(); + } + @override WalletService createHavenWalletService(Box walletInfoSource) { return HavenWalletService(walletInfoSource); diff --git a/lib/main.dart b/lib/main.dart index 00d76800d..510705105 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/default_settings_migration.dart'; import 'package:cake_wallet/entities/get_encryption_key.dart'; import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; @@ -164,6 +165,10 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } + if (!CakeHive.isAdapterRegistered(HavenSeedStore.typeId)) { + CakeHive.registerAdapter(HavenSeedStoreAdapter()); + } + if (!CakeHive.isAdapterRegistered(MwebUtxo.typeId)) { CakeHive.registerAdapter(MwebUtxoAdapter()); } @@ -188,6 +193,12 @@ Future initializeAppConfigs() async { final anonpayInvoiceInfo = await CakeHive.openBox(AnonpayInvoiceInfo.boxName); final unspentCoinsInfoSource = await CakeHive.openBox(UnspentCoinsInfo.boxName); + final havenSeedStoreBoxKey = + await getEncryptionKey(secureStorage: secureStorage, forKey: HavenSeedStore.boxKey); + final havenSeedStore = await CakeHive.openBox( + HavenSeedStore.boxName, + encryptionKey: havenSeedStoreBoxKey); + await initialSetup( sharedPreferences: await SharedPreferences.getInstance(), nodes: nodes, @@ -203,6 +214,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, + havenSeedStore: havenSeedStore, initialMigrationVersion: 45, ); } @@ -222,7 +234,8 @@ Future initialSetup( required SecureStorage secureStorage, required Box anonpayInvoiceInfo, required Box unspentCoinsInfoSource, - int initialMigrationVersion = 15}) async { + required Box havenSeedStore, + int initialMigrationVersion = 15, }) async { LanguageService.loadLocaleList(); await defaultSettingsMigration( secureStorage: secureStorage, @@ -232,7 +245,8 @@ Future initialSetup( contactSource: contactSource, tradeSource: tradesSource, nodes: nodes, - powNodes: powNodes); + powNodes: powNodes, + havenSeedStore: havenSeedStore); await setup( walletInfoSource: walletInfoSource, nodeSource: nodes, diff --git a/tool/configure.dart b/tool/configure.dart index d9d5c6667..6abd73d9e 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -656,7 +656,14 @@ import 'package:cw_core/output_info.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; -import 'package:cw_core/crypto_currency.dart';"""; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/core/key_service.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:cake_wallet/entities/haven_seed_store.dart'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; +"""; const havenCWHeaders = """ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_amount_format.dart'; @@ -679,6 +686,7 @@ import 'package:cw_haven/mnemonics/french.dart'; import 'package:cw_haven/mnemonics/italian.dart'; import 'package:cw_haven/haven_transaction_creation_credentials.dart'; import 'package:cw_haven/api/balance_list.dart'; +import 'package:cw_haven/haven_wallet_service.dart'; """; const havenCwPart = "part 'cw_haven.dart';"; const havenContent = """ @@ -779,6 +787,7 @@ abstract class Haven { void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); WalletService createHavenWalletService(Box walletInfoSource); + Future backupHavenSeeds(Box havenSeedStore); CryptoCurrency assetOfTransaction(TransactionInfo tx); List getAssetRate(); } From 1320b3ea3c927176b756d93d6f6ff5207c9c94cc Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 11 Dec 2024 22:39:59 +0200 Subject: [PATCH 12/26] Update address_validator.dart (#1805) --- lib/core/address_validator.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 387b91dcc..dbb6f9541 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -106,9 +106,8 @@ class AddressValidator extends TextValidator { case CryptoCurrency.wow: pattern = '[0-9a-zA-Z]+'; case CryptoCurrency.bch: - pattern = '^(bitcoincash:)?(q|p)[0-9a-zA-Z]{41,42}'; - case CryptoCurrency.bnb: - pattern = '[0-9a-zA-Z]+'; + pattern = '(?:bitcoincash:)?(q|p)[0-9a-zA-Z]{41}' + '|[13][a-km-zA-HJ-NP-Z1-9]{25,34}'; case CryptoCurrency.hbar: pattern = '[0-9a-zA-Z.]+'; case CryptoCurrency.zaddr: @@ -203,7 +202,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.avaxc: return [42]; case CryptoCurrency.bch: - return [42, 43, 44, 54, 55]; + return [42, 54, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]; case CryptoCurrency.bnb: return [42]; case CryptoCurrency.nano: From fd6801cafb6d3c61b4738e06ca7985a64d48ab35 Mon Sep 17 00:00:00 2001 From: cyan Date: Wed, 11 Dec 2024 16:03:34 -0500 Subject: [PATCH 13/26] CW-834 Empty error when spending in wownero (#1870) * CW-834 Empty error when spending in wownero * monero -> wownero --- cw_wownero/lib/api/transaction_history.dart | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cw_wownero/lib/api/transaction_history.dart b/cw_wownero/lib/api/transaction_history.dart index ce93df7d1..3cebdd811 100644 --- a/cw_wownero/lib/api/transaction_history.dart +++ b/cw_wownero/lib/api/transaction_history.dart @@ -181,13 +181,23 @@ void commitTransaction({required wownero.PendingTransaction transactionPointer}) final txCommit = wownero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false); - final String? error = (() { + String? error = (() { final status = wownero.PendingTransaction_status(transactionPointer.cast()); if (status == 0) { return null; } - return wownero.Wallet_errorString(wptr!); + return wownero.PendingTransaction_errorString(transactionPointer.cast()); })(); + if (error == null) { + error = (() { + final status = wownero.Wallet_status(wptr!); + if (status == 0) { + return null; + } + return wownero.Wallet_errorString(wptr!); + })(); + + } if (error != null) { throw CreationTransactionException(message: error); From 5abd524af35b4df06c6250f9a83a28819f118822 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Thu, 12 Dec 2024 02:49:17 -0500 Subject: [PATCH 14/26] Update seed page strings and colors (#1871) --- lib/src/screens/seed/wallet_seed_page.dart | 6 +++--- res/values/strings_ar.arb | 2 +- res/values/strings_bg.arb | 2 +- res/values/strings_cs.arb | 2 +- res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- res/values/strings_es.arb | 2 +- res/values/strings_fr.arb | 2 +- res/values/strings_ha.arb | 2 +- res/values/strings_hi.arb | 2 +- res/values/strings_hr.arb | 2 +- res/values/strings_hy.arb | 2 +- res/values/strings_id.arb | 2 +- res/values/strings_it.arb | 2 +- res/values/strings_ja.arb | 2 +- res/values/strings_ko.arb | 2 +- res/values/strings_my.arb | 2 +- res/values/strings_nl.arb | 2 +- res/values/strings_pl.arb | 2 +- res/values/strings_pt.arb | 2 +- res/values/strings_ru.arb | 2 +- res/values/strings_th.arb | 2 +- res/values/strings_tl.arb | 2 +- res/values/strings_tr.arb | 2 +- res/values/strings_uk.arb | 2 +- res/values/strings_ur.arb | 2 +- res/values/strings_vi.arb | 2 +- res/values/strings_yo.arb | 2 +- res/values/strings_zh.arb | 2 +- 29 files changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index 05a44281a..fe532e7fb 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -114,12 +114,12 @@ class WalletSeedPage extends BasePage { padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: currentTheme.type == ThemeType.dark - ? Color.fromRGBO(126, 116, 59, 1) - : Color.fromRGBO(189, 169, 90, 1), + ? Color.fromRGBO(132, 110, 64, 1) + : Color.fromRGBO(194, 165, 94, 1), borderRadius: BorderRadius.all(Radius.circular(12)), border: Border.all( color: currentTheme.type == ThemeType.dark - ? Color.fromRGBO(171, 171, 41, 1) + ? Color.fromRGBO(177, 147, 41, 1) : Color.fromRGBO(125, 122, 15, 1), width: 2.0, )), diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index b8e476e4c..bd7fa47d7 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "شراء بطاقات مسبقة الدفع وبطاقات الهدايا في جميع أنحاء العالم", "cake_pay_web_cards_subtitle": "اشتري بطاقات مدفوعة مسبقا وبطاقات هدايا في جميع أنحاء العالم", "cake_pay_web_cards_title": "بطاقات Cake Pay Web", - "cake_seeds_save_disclaimer": "يرجى حفظ هذه الكلمات في مكان آمن! إذا فقدت الوصول إلى محفظتك ، فإن دعم محفظة الكيك لا يمكن أن يساعدك", + "cake_seeds_save_disclaimer": "يرجى حفظ هذه الكلمات في مكان آمن! ستحتاج إلى هذه الكلمات لاستعادة محفظتك على جهاز جديد.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "آسف ، بطاقة الهدايا هذه غير متوفرة على iOS. يمكنك شرائه على Android أو من خلال موقعنا بدلاً من ذلك.", "cakepay_prepaid_card": "بطاقة ائتمان CakePay مسبقة الدفع", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 91a718f91..bff37e95c 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Купете предплатени карти и карти за подаръци в световен мащаб", "cake_pay_web_cards_subtitle": "Купете световно признати предплатени и гифт карти", "cake_pay_web_cards_title": "Cake Pay Онлайн Карти", - "cake_seeds_save_disclaimer": "Моля, запазете тези думи на сигурно място! Ако загубите достъп до портфейла си, поддръжката на портфейла за торти не може да ви помогне", + "cake_seeds_save_disclaimer": "Моля, запазете тези думи на сигурно място! Ще ви трябват тези думи, за да възстановите портфейла си на ново устройство.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "За съжаление тази карта за подарък не се предлага в iOS. Можете да го закупите на Android или чрез нашия уебсайт вместо това.", "cakepay_prepaid_card": "CakePay предплатена дебитна карта", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index d2ca2def5..d8025678f 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Kupte si celosvětové předplacené karty a dárkové karty", "cake_pay_web_cards_subtitle": "Kupte si celosvětové předplacené a dárkové karty", "cake_pay_web_cards_title": "Cake Pay webové karty", - "cake_seeds_save_disclaimer": "Uložte tato slova na bezpečném místě! Pokud ztratíte přístup k vaší peněžence, podpora peněženky dortu vám nemůže pomoci", + "cake_seeds_save_disclaimer": "Uložte tato slova na bezpečném místě! Tato slova budete potřebovat k obnovení peněženky na novém zařízení.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Je nám líto, tato dárková karta není k dispozici na iOS. Místo toho si jej můžete zakoupit na Androidu nebo prostřednictvím našeho webu.", "cakepay_prepaid_card": "CakePay předplacená debetní karta", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f5e2a3879..b3aad50b0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Kaufen Sie weltweite Prepaid-Karten und Geschenkkarten", "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten", "cake_pay_web_cards_title": "Cake Pay-Webkarten", - "cake_seeds_save_disclaimer": "Bitte speichern Sie diese Wörter an einem sicheren Ort! Wenn Sie den Zugang zu Ihrer Brieftasche verlieren, kann Ihnen die Stütze der Kuchenbrieftasche nicht helfen", + "cake_seeds_save_disclaimer": "Bitte speichern Sie diese Wörter an einem sicheren Ort! Sie benötigen diese Wörter, um Ihre Brieftasche auf einem neuen Gerät wiederherzustellen.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Entschuldigung, diese Geschenkkarte ist auf iOS nicht erhältlich. Sie können es stattdessen auf Android oder über unsere Website kaufen.", "cakepay_prepaid_card": "CakePay-Prepaid-Debitkarte", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 0168f7951..bd483adb1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Buy worldwide prepaid cards and gift cards", "cake_pay_web_cards_subtitle": "Buy worldwide prepaid cards and gift cards", "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_seeds_save_disclaimer": "Please save these words in a secure place! If you lose access to your wallet, Cake Wallet support CANNOT help you", + "cake_seeds_save_disclaimer": "Please save these words in a secure place! You will need these words to restore your wallet on a new device.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Sorry, this gift card is not available on iOS. You can purchase it on Android or through our website instead.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 12ea9bbf3..45b1d279b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Compra tarjetas prepagadas y tarjetas de regalo en todo el mundo", "cake_pay_web_cards_subtitle": "Compra tarjetas de prepago y tarjetas de regalo en todo el mundo", "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", - "cake_seeds_save_disclaimer": "¡Guarde estas palabras en un lugar seguro! Si pierde acceso a su billetera, el soporte de la billetera de pastel no puede ayudarlo", + "cake_seeds_save_disclaimer": "¡Guarde estas palabras en un lugar seguro! Necesitará estas palabras para restaurar su billetera en un nuevo dispositivo.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Lo siento, esta tarjeta de regalo no está disponible en iOS. Puede comprarlo en Android o a través de nuestro sitio web.", "cakepay_prepaid_card": "Tarjeta de Débito Prepago CakePay", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index a8b1fc48b..a359e3630 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Achetez des cartes et des cartes-cadeaux prépayées mondiales", "cake_pay_web_cards_subtitle": "Achetez des cartes prépayées et des cartes-cadeaux dans le monde entier", "cake_pay_web_cards_title": "Cartes Web Cake Pay", - "cake_seeds_save_disclaimer": "Veuillez enregistrer ces mots dans un endroit sécurisé! Si vous perdez accès à votre portefeuille, le support de portefeuille à gâteau ne peut pas vous aider", + "cake_seeds_save_disclaimer": "Veuillez enregistrer ces mots dans un endroit sécurisé! Vous aurez besoin de ces mots pour restaurer votre portefeuille sur un nouvel appareil.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Désolé, cette carte-cadeau n'est pas disponible sur iOS. Vous pouvez l'acheter sur Android ou via notre site Web à la place.", "cakepay_prepaid_card": "Carte de débit prépayée Cake Pay", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 24330f348..48ede7b7c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Sayi katunan shirye-shiryen duniya da katunan kyauta", "cake_pay_web_cards_subtitle": "Sayi katunan da aka riga aka biya na duniya da katunan kyauta", "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_seeds_save_disclaimer": "Da fatan za a ceci waɗannan kalmomin a cikin amintaccen wuri! Idan ka rasa damar zuwa Wallet, Tallafin Wall Wallet ba zai iya taimaka maka ba", + "cake_seeds_save_disclaimer": "Da fatan za a ceci waɗannan kalmomin a cikin amintaccen wuri! Kuna buƙatar waɗannan kalmomin don dawo da walat ɗinku a kan sabon na'ura.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Yi haƙuri, wannan katin kyautar ba a samuwa akan iOS. Kuna iya sayan shi a kan Android ko ta yanar gizo a maimakon.", "cakepay_prepaid_card": "Katin zare kudi na CakePay", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5d226dfb6..c2feea939 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "दुनिया भर में प्रीपेड कार्ड और उपहार कार्ड खरीदें", "cake_pay_web_cards_subtitle": "दुनिया भर में प्रीपेड कार्ड और गिफ्ट कार्ड खरीदें", "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", - "cake_seeds_save_disclaimer": "कृपया इन शब्दों को सुरक्षित स्थान पर सहेजें! यदि आप अपने बटुए तक पहुंच खो देते हैं, तो केक वॉलेट समर्थन आपकी मदद नहीं कर सकता है", + "cake_seeds_save_disclaimer": "कृपया इन शब्दों को सुरक्षित स्थान पर सहेजें! एक नए डिवाइस पर अपने बटुए को पुनर्स्थापित करने के लिए आपको इन शब्दों की आवश्यकता होगी।", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "क्षमा करें, यह उपहार कार्ड iOS पर उपलब्ध नहीं है। आप इसे Android पर या हमारी वेबसाइट के बजाय खरीद सकते हैं।", "cakepay_prepaid_card": "केकपे प्रीपेड डेबिट कार्ड", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index ed60e6ee6..c82e2a5f8 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Kupite svjetske unaprijed plaćene kartice i poklon kartice", "cake_pay_web_cards_subtitle": "Kupujte prepaid kartice i poklon kartice diljem svijeta", "cake_pay_web_cards_title": "Cake Pay Web kartice", - "cake_seeds_save_disclaimer": "Molimo spremite ove riječi na sigurno mjesto! Ako izgubite pristup vašem novčaniku, podrška za novčanik za kolače ne može vam pomoći", + "cake_seeds_save_disclaimer": "Molimo spremite ove riječi na sigurno mjesto! Trebat će vam ove riječi da biste vratili novčanik na novi uređaj.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Oprostite, ova poklon kartica nije dostupna na iOS -u. Umjesto toga, možete ga kupiti na Androidu ili putem naše web stranice.", "cakepay_prepaid_card": "CakePay unaprijed plaćena debitna kartica", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 41b18f59e..d83bc2a3a 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Գնեք համաշխարհային նախավճարային քարտեր և նվեր քարտեր", "cake_pay_web_cards_subtitle": "Գնեք համաշխարհային նախավճարային քարտեր և նվեր քարտեր", "cake_pay_web_cards_title": "Cake Pay Վեբ Քարտեր", - "cake_seeds_save_disclaimer": "Խնդրում ենք պահպանել այս բառերը անվտանգ տեղում: Եթե ​​ձեր դրամապանակը կորցնեք մուտքը, տորթի դրամապանակի աջակցությունը չի կարող օգնել ձեզ", + "cake_seeds_save_disclaimer": "Խնդրում ենք պահպանել այս բառերը անվտանգ տեղում: Ձեզ հարկավոր կլինի այս բառերը `ձեր դրամապանակը նոր սարքում վերականգնելու համար:", "cake_wallet": "Cake Գաղտնապահոց", "cakepay_ios_not_available": "Ներեցեք, այս նվեր քարտը հասանելի չէ iOS- ում: Փոխարենը կարող եք այն գնել Android- ում կամ մեր կայքում:", "cakepay_prepaid_card": "CakePay Նախավճարային Դեբետային Քարտ", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ef64b7044..ca140e63e 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Beli kartu prabayar di seluruh dunia dan kartu hadiah", "cake_pay_web_cards_subtitle": "Beli kartu prabayar dan kartu hadiah secara global", "cake_pay_web_cards_title": "Kartu Web Cake Pay", - "cake_seeds_save_disclaimer": "Harap simpan kata -kata ini di tempat yang aman! Jika Anda kehilangan akses ke dompet Anda, dukungan dompet kue tidak dapat membantu Anda", + "cake_seeds_save_disclaimer": "Harap simpan kata -kata ini di tempat yang aman! Anda akan membutuhkan kata -kata ini untuk mengembalikan dompet Anda pada perangkat baru.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Maaf, kartu hadiah ini tidak tersedia di iOS. Anda dapat membelinya di Android atau melalui situs web kami sebagai gantinya.", "cakepay_prepaid_card": "Kartu Debit Prabayar CakePay", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 6a508822a..f5dbc1c5a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Acquista carte prepagate in tutto il mondo e carte regalo", "cake_pay_web_cards_subtitle": "Acquista carte prepagate e carte regalo in tutto il mondo", "cake_pay_web_cards_title": "Carte Web Cake Pay", - "cake_seeds_save_disclaimer": "Si prega di salvare queste parole in un posto sicuro! Se perdi l'accesso al tuo portafoglio, il supporto per il portafoglio della torta non può aiutarti", + "cake_seeds_save_disclaimer": "Si prega di salvare queste parole in un posto sicuro! Avrai bisogno di queste parole per ripristinare il portafoglio su un nuovo dispositivo.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Mi dispiace, questa carta regalo non è disponibile su iOS. Puoi acquistarlo su Android o tramite il nostro sito Web.", "cakepay_prepaid_card": "Carta di debito prepagata CakePay", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 177171a50..182133e68 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "世界中のプリペイドカードとギフトカードを購入します", "cake_pay_web_cards_subtitle": "世界中のプリペイド カードとギフト カードを購入する", "cake_pay_web_cards_title": "Cake Pay ウェブカード", - "cake_seeds_save_disclaimer": "これらの言葉を安全な場所に保存してください!財布へのアクセスを失った場合、ケーキウォレットのサポートはあなたを助けることができません", + "cake_seeds_save_disclaimer": "これらの言葉を安全な場所に保存してください!新しいデバイスで財布を復元するには、これらの単語が必要です。", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "申し訳ありませんが、このギフトカードはiOSでは利用できません。代わりにAndroidまたは当社のWebサイトから購入できます。", "cakepay_prepaid_card": "CakePayプリペイドデビットカード", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index fd66d0010..747c316d6 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "전세계 선불 카드와 기프트 카드를 구입하십시오", "cake_pay_web_cards_subtitle": "전 세계 선불 카드 및 기프트 카드 구매", "cake_pay_web_cards_title": "케이크페이 웹카드", - "cake_seeds_save_disclaimer": "이 단어를 안전한 장소에 저장하십시오! 지갑에 대한 접근이 손실되면 케이크 지갑 지지대가 도움이되지 않습니다.", + "cake_seeds_save_disclaimer": "이 단어를 안전한 장소에 저장하십시오! 새 장치에서 지갑을 복원하려면이 단어가 필요합니다.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "죄송합니다.이 기프트 카드는 iOS에서 사용할 수 없습니다. Android 또는 웹 사이트를 통해 구매할 수 있습니다.", "cakepay_prepaid_card": "CakePay 선불 직불 카드", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index ae007e487..8fe87b34c 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Worldwide ကြိုတင်ငွေဖြည့်ကဒ်များနှင့်လက်ဆောင်ကဒ်များကို 0 ယ်ပါ", "cake_pay_web_cards_subtitle": "ကမ္ဘာတစ်ဝှမ်း ကြိုတင်ငွေပေးကတ်များနှင့် လက်ဆောင်ကတ်များကို ဝယ်ယူပါ။", "cake_pay_web_cards_title": "Cake Pay ဝဘ်ကတ်များ", - "cake_seeds_save_disclaimer": "ကျေးဇူးပြုပြီးဒီစကားလုံးတွေကိုလုံခြုံတဲ့နေရာမှာသိမ်းထားပါ။ သင်၏ပိုက်ဆံအိတ်ကိုသင်လက်လှမ်းမမီပါကကိတ်မုန့်ပိုက်ဆံအိတ်အထောက်အပံ့သည်သင့်ကိုမကူညီနိုင်ပါ", + "cake_seeds_save_disclaimer": "ကျေးဇူးပြုပြီးဒီစကားလုံးတွေကိုလုံခြုံတဲ့နေရာမှာသိမ်းထားပါ။ သင်၏ပိုက်ဆံအိတ်ကိုကိရိယာအသစ်တစ်ခုတွင်သင်၏ပိုက်ဆံအိတ်ကိုပြန်လည်ရယူရန်ဤစကားလုံးများကိုသင်လိုအပ်လိမ့်မည်။", "cake_wallet": "Cake ပိုက်ဆံအိတ်", "cakepay_ios_not_available": "တောင်းပန်ပါတယ်, ဒီလက်ဆောင်ကဒ်ကို iOS မှာမရနိုင်ပါ။ ၎င်းကို Android တွင်သို့မဟုတ်ကျွန်ုပ်တို့၏ဝက်ဘ်ဆိုက်တွင် 0 ယ်နိုင်သည်။", "cakepay_prepaid_card": "CakePay ကြိုတင်ငွေဖြည့်ဒက်ဘစ်ကတ်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6343f4dd0..ca7052b0e 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Koop wereldwijde prepaid -kaarten en cadeaubonnen", "cake_pay_web_cards_subtitle": "Koop wereldwijd prepaidkaarten en cadeaubonnen", "cake_pay_web_cards_title": "Cake Pay-webkaarten", - "cake_seeds_save_disclaimer": "Bewaar deze woorden op een veilige plek! Als u de toegang tot uw portemonnee verliest, kan ondersteuning voor cake -portemonnee u niet helpen", + "cake_seeds_save_disclaimer": "Bewaar deze woorden op een veilige plek! U hebt deze woorden nodig om uw portemonnee op een nieuw apparaat te herstellen.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Sorry, deze cadeaubon is niet beschikbaar op iOS. U kunt het in plaats daarvan kopen op Android of via onze website.", "cakepay_prepaid_card": "CakePay Prepaid Debetkaart", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 6afe3b932..fad2bb026 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Kup na całym świecie karty przedpłacone i karty podarunkowe", "cake_pay_web_cards_subtitle": "Kupuj na całym świecie karty przedpłacone i karty podarunkowe", "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_seeds_save_disclaimer": "Zapisz te słowa w bezpiecznym miejscu! Jeśli stracisz dostęp do portfela, wsparcie portfela ciasta nie może ci pomóc", + "cake_seeds_save_disclaimer": "Zapisz te słowa w bezpiecznym miejscu! Będziesz potrzebować tych słów, aby przywrócić portfel na nowym urządzeniu.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Przepraszam, ta karta podarunkowa nie jest dostępna na iOS. Zamiast tego możesz go kupić na Android lub za pośrednictwem naszej strony internetowej.", "cakepay_prepaid_card": "Przedpłacona karta debetowa CakePay", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 85fafc590..c59afec65 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Compre cartões pré -pagos em todo o mundo e cartões -presente", "cake_pay_web_cards_subtitle": "Compre cartões pré-pagos e cartões-presente em todo o mundo", "cake_pay_web_cards_title": "Cartões Cake Pay Web", - "cake_seeds_save_disclaimer": "Por favor, salve estas palavras em um local seguro! Se você perder o acesso à sua carteira, o suporte da carteira de bolo não poderá ajudá -lo", + "cake_seeds_save_disclaimer": "Por favor, salve estas palavras em um local seguro! Você precisará dessas palavras para restaurar sua carteira em um novo dispositivo.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Desculpe, este cartão -presente não está disponível no iOS. Você pode comprá -lo no Android ou através do nosso site.", "cakepay_prepaid_card": "Cartão de débito pré-pago CakePay", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 07d8f39ce..94b1c7010 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Купить карты с предоплатой и подарочными картами по всему миру", "cake_pay_web_cards_subtitle": "Покупайте карты предоплаты и подарочные карты по всему миру", "cake_pay_web_cards_title": "Веб-карты Cake Pay", - "cake_seeds_save_disclaimer": "Пожалуйста, сохраните эти слова в безопасном месте! Если вы теряете доступ к своему кошельку, поддержка кошелька для торта не может вам помочь", + "cake_seeds_save_disclaimer": "Пожалуйста, сохраните эти слова в безопасном месте! Вам понадобятся эти слова, чтобы восстановить свой кошелек на новом устройстве.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Извините, эта подарочная карта недоступна на iOS. Вместо этого вы можете приобрести его на Android или через наш веб -сайт.", "cakepay_prepaid_card": "Предоплаченная дебетовая карта CakePay", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f938576dd..f35187cd4 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "ซื้อบัตรเติมเงินและบัตรของขวัญทั่วโลก", "cake_pay_web_cards_subtitle": "ซื้อบัตรพร้อมเงินระดับโลกและบัตรของขวัญ", "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_seeds_save_disclaimer": "โปรดบันทึกคำเหล่านี้ในสถานที่ที่ปลอดภัย! หากคุณสูญเสียการเข้าถึงกระเป๋าเงินของคุณการสนับสนุนกระเป๋าเงินเค้กไม่สามารถช่วยคุณได้", + "cake_seeds_save_disclaimer": "โปรดบันทึกคำเหล่านี้ในสถานที่ที่ปลอดภัย! คุณจะต้องใช้คำเหล่านี้เพื่อกู้คืนกระเป๋าเงินของคุณในอุปกรณ์ใหม่", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "ขออภัยบัตรของขวัญนี้ไม่มีใน iOS คุณสามารถซื้อได้บน Android หรือผ่านเว็บไซต์ของเราแทน", "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 2234d02b1..290fcf4bf 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", "cake_pay_web_cards_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_seeds_save_disclaimer": "Mangyaring i -save ang mga salitang ito sa isang ligtas na lugar! Kung nawalan ka ng pag -access sa iyong pitaka, hindi makakatulong sa iyo ang suporta ng wallet ng cake", + "cake_seeds_save_disclaimer": "Mangyaring i -save ang mga salitang ito sa isang ligtas na lugar! Kakailanganin mo ang mga salitang ito upang maibalik ang iyong pitaka sa isang bagong aparato.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Paumanhin, ang gift card na ito ay hindi magagamit sa iOS. Maaari mo itong bilhin sa Android o sa pamamagitan ng aming website sa halip.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 83f423b59..912cd52e4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Dünya çapında ön ödemeli kartlar ve hediye kartları satın alın", "cake_pay_web_cards_subtitle": "Dünya çapında ön ödemeli kartlar ve hediye kartları satın alın", "cake_pay_web_cards_title": "Cake Pay Web Kartları", - "cake_seeds_save_disclaimer": "Lütfen bu kelimeleri güvenli bir yerde kaydedin! Cüzdanınıza erişimi kaybederseniz, kek cüzdan desteği size yardımcı olamaz", + "cake_seeds_save_disclaimer": "Lütfen bu kelimeleri güvenli bir yerde kaydedin! Cüzdanınızı yeni bir cihazda geri yüklemek için bu kelimelere ihtiyacınız olacak.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Üzgünüm, bu hediye kartı iOS'ta mevcut değil. Bunun yerine Android'de veya web sitemizden satın alabilirsiniz.", "cakepay_prepaid_card": "CakePay Ön Ödemeli Kart", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b70f58c88..fd03f437e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Купіть у всьому світі передплачені картки та подарункові картки", "cake_pay_web_cards_subtitle": "Купуйте передоплачені та подарункові картки по всьому світу", "cake_pay_web_cards_title": "Веб-картки Cake Pay", - "cake_seeds_save_disclaimer": "Збережіть ці слова в безпечному місці! Якщо ви втрачаєте доступ до свого гаманця, підтримка гаманця тортів не може вам допомогти", + "cake_seeds_save_disclaimer": "Збережіть ці слова в безпечному місці! Вам знадобляться ці слова, щоб відновити гаманець на новому пристрої.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Вибачте, ця подарункова карта недоступна на iOS. Ви можете придбати його на Android або через наш веб -сайт.", "cakepay_prepaid_card": "Передплачена дебетова картка CakePay", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 78443c803..03140020a 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈ خریدیں", "cake_pay_web_cards_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈز خریدیں۔", "cake_pay_web_cards_title": "Cake پے ویب کارڈز", - "cake_seeds_save_disclaimer": "براہ کرم ان الفاظ کو ایک محفوظ جگہ پر محفوظ کریں! اگر آپ اپنے بٹوے تک رسائی کھو دیتے ہیں تو ، کیک پرس کی مدد آپ کی مدد نہیں کرسکتی ہے", + "cake_seeds_save_disclaimer": "براہ کرم ان الفاظ کو ایک محفوظ جگہ پر محفوظ کریں! اپنے بٹوے کو کسی نئے آلے پر بحال کرنے کے ل You آپ کو ان الفاظ کی ضرورت ہوگی۔", "cake_wallet": "Cake والیٹ", "cakepay_ios_not_available": "معذرت ، یہ گفٹ کارڈ iOS پر دستیاب نہیں ہے۔ اس کے بجائے آپ اسے اینڈروئیڈ پر یا ہماری ویب سائٹ کے ذریعے خرید سکتے ہیں۔", "cakepay_prepaid_card": "Cake پے پری پیڈ ڈیبٹ کارڈ", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 7491263b4..e40edf458 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Mua thẻ trả trước toàn cầu và thẻ quà tặng", "cake_pay_web_cards_subtitle": "Mua thẻ trả trước toàn cầu và thẻ quà tặng", "cake_pay_web_cards_title": "Thẻ Cake Pay Web", - "cake_seeds_save_disclaimer": "Vui lòng lưu những từ này ở một nơi an toàn! Nếu bạn mất quyền truy cập vào ví của mình, hỗ trợ ví tiền không thể giúp bạn", + "cake_seeds_save_disclaimer": "Vui lòng lưu những từ này ở một nơi an toàn! Bạn sẽ cần những từ này để khôi phục ví của bạn trên một thiết bị mới.", "cake_wallet": "Ví Cake", "cakepay_ios_not_available": "Xin lỗi, thẻ quà tặng này không có sẵn trên iOS. Thay vào đó, bạn có thể mua nó trên Android hoặc thông qua trang web của chúng tôi.", "cakepay_prepaid_card": "Thẻ Ghi Nợ Trả Trước CakePay", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index f51c83e1c..8b3cdc358 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "Ra awọn kaadi ti a san ni agbaye ati awọn kaadi ẹbun", "cake_pay_web_cards_subtitle": "Ra àwọn káàdì ìrajà t'á lò nínú ìtajà kan àti àwọn káàdì náà t'á lè lò níbikíbi", "cake_pay_web_cards_title": "Àwọn káàdì wẹ́ẹ̀bù ti Cake Pay", - "cake_seeds_save_disclaimer": "Jọwọ fi awọn ọrọ wọnyi pamọ ni aaye aabo! Ti o ba padanu wiwọle si apamọwọ rẹ, atilẹyin apamọwọ oyinbo ti a ko le ran ọ lọwọ", + "cake_seeds_save_disclaimer": "Jọwọ fi awọn ọrọ wọnyi pamọ ni aaye aabo! Iwọ yoo nilo awọn ọrọ wọnyi lati mu pada apamọwọ rẹ sori ẹrọ tuntun.", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "Ma binu, kaadi ẹbun yii ko wa lori iOS. O le ra lori Android tabi nipasẹ oju opo wẹẹbu wa dipo.", "cakepay_prepaid_card": "Káàdì ìrajà ti CakePay", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 7e36289ef..63e92a67d 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -101,7 +101,7 @@ "cake_pay_subtitle": "购买全球预付费卡和礼品卡", "cake_pay_web_cards_subtitle": "购买全球预付卡和礼品卡", "cake_pay_web_cards_title": "蛋糕支付网络卡", - "cake_seeds_save_disclaimer": "请在安全的地方保存这些单词!如果您无法使用钱包,蛋糕钱包的支撑就无法帮助您", + "cake_seeds_save_disclaimer": "请在安全的地方保存这些单词!您将需要这些单词来恢复新设备上的钱包。", "cake_wallet": "Cake Wallet", "cakepay_ios_not_available": "抱歉,这张礼品卡在iOS上不可用。您可以在Android或通过我们的网站上购买它。", "cakepay_prepaid_card": "CakePay 预付借记卡", From ad34caa5be322dcfe81aebc2eefb405322cc347b Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Thu, 12 Dec 2024 03:24:45 -0500 Subject: [PATCH 15/26] UI Enhancements (#1824) * Fix button color * Unify search icon * Update select button colors * Modify tap to hide for balance card * Modify tap to hide constants * Modify hidden balance behaviour * Add tap to hide to second value * Make tap to hide persistent * Change to switchBalanceValue function * Fix MWEB card spacing [skip ci] * Swap buttons on wallets screen [skip ci] --- .../cake_pay/cards/cake_pay_cards_page.dart | 19 ++-- .../screens/dashboard/pages/balance_page.dart | 91 ++++++++++--------- .../screens/new_wallet/new_wallet_page.dart | 2 +- .../new_wallet/widgets/select_button.dart | 2 +- .../screens/receive/widgets/header_tile.dart | 2 +- .../screens/wallet_list/wallet_list_page.dart | 40 ++++---- lib/src/widgets/search_bar_widget.dart | 4 +- .../dashboard/balance_view_model.dart | 11 ++- 8 files changed, 91 insertions(+), 80 deletions(-) diff --git a/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart index f2958ee31..450fa5281 100644 --- a/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart +++ b/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart @@ -116,7 +116,7 @@ class CakePayCardsPage extends BasePage { }, child: Container( width: 32, - padding: EdgeInsets.all(8), + padding: EdgeInsets.only(top: 7, bottom: 7), decoration: BoxDecoration( color: Theme.of(context).extension()!.syncedBackgroundColor, border: Border.all( @@ -125,7 +125,7 @@ class CakePayCardsPage extends BasePage { borderRadius: BorderRadius.circular(10), ), child: Image.asset( - 'assets/images/filter.png', + 'assets/images/filter_icon.png', color: Theme.of(context).extension()!.iconColor, ))), ); @@ -141,14 +141,14 @@ class CakePayCardsPage extends BasePage { } }, child: Container( - padding: EdgeInsets.symmetric(horizontal: 6), + padding: EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( color: Theme.of(context).extension()!.syncedBackgroundColor, border: Border.all(color: Colors.transparent), borderRadius: BorderRadius.circular(10), ), child: Container( - margin: EdgeInsets.symmetric(vertical: 2), + margin: EdgeInsets.symmetric(vertical: 4), child: Row( children: [ Image.asset( @@ -363,13 +363,10 @@ class _SearchWidget extends StatelessWidget { @override Widget build(BuildContext context) { final searchIcon = ExcludeSemantics( - child: Padding( - padding: EdgeInsets.all(8), - child: Image.asset( - 'assets/images/mini_search_icon.png', + child: Icon( Icons.search, color: Theme.of(context).extension()!.iconColor, + //size: 24 ), - ), ); return TextField( @@ -379,8 +376,8 @@ class _SearchWidget extends StatelessWidget { decoration: InputDecoration( filled: true, contentPadding: EdgeInsets.only( - top: 10, - left: 10, + top: 8, + left: 8, ), fillColor: Theme.of(context).extension()!.syncedBackgroundColor, hintText: S.of(context).search, diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index b16a7b090..46c01254a 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -118,12 +118,7 @@ class CryptoBalanceWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( - onLongPress: () => dashboardViewModel.balanceViewModel.isReversing = - !dashboardViewModel.balanceViewModel.isReversing, - onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing = - !dashboardViewModel.balanceViewModel.isReversing, - child: SingleChildScrollView( + return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -459,7 +454,6 @@ class CryptoBalanceWidget extends StatelessWidget { }), ], ), - ), ); } @@ -597,44 +591,47 @@ class BalanceRowWidget extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance - ? () => _showBalanceDescription( - context, S.of(context).available_balance_description) - : null, - child: Column( + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Semantics( - hint: 'Double tap to see more information', - container: true, - child: Text('${availableBalanceLabel}', - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1)), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: hasAdditionalBalance + ? () => _showBalanceDescription( + context, S.of(context).available_balance_description) + : null, + child: Row( + children: [ + Semantics( + hint: 'Double tap to see more information', + container: true, + child: Text('${availableBalanceLabel}', + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1)), + ), + if (hasAdditionalBalance) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ), + ], ), - if (hasAdditionalBalance) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Icon(Icons.help_outline, - size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), - ), - ], ), SizedBox(height: 6), AutoSizeText(availableBalance, @@ -667,9 +664,10 @@ class BalanceRowWidget extends StatelessWidget { fontWeight: FontWeight.w500, color: Theme.of(context).extension()!.textColor, height: 1)), + ], ), - ), + SizedBox( width: min(MediaQuery.of(context).size.width * 0.2, 100), child: Center( @@ -712,6 +710,7 @@ class BalanceRowWidget extends StatelessWidget { ), ], ), + ), if (frozenBalance.isNotEmpty) GestureDetector( behavior: HitTestBehavior.opaque, @@ -778,7 +777,9 @@ class BalanceRowWidget extends StatelessWidget { ), ), if (hasAdditionalBalance) - Column( + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 24), @@ -821,12 +822,13 @@ class BalanceRowWidget extends StatelessWidget { ), ], ), + ), ], ), ), ), if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[ - SizedBox(height: 16), + SizedBox(height: 10), Container( margin: const EdgeInsets.only(left: 16, right: 16), decoration: BoxDecoration( @@ -881,7 +883,9 @@ class BalanceRowWidget extends StatelessWidget { ], ), if (hasSecondAvailableBalance) - Row( + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -953,6 +957,7 @@ class BalanceRowWidget extends StatelessWidget { ), ], ), + ), ], ), ), diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 387904df0..e63a01f61 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -347,7 +347,7 @@ class _WalletNameFormState extends State { key: ValueKey('new_wallet_page_confirm_button_key'), onPressed: _confirmForm, text: S.of(context).seed_language_next, - color: Colors.green, + color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: _walletNewVM.state is IsExecutingState, isDisabled: _walletNewVM.name.isEmpty, diff --git a/lib/src/screens/new_wallet/widgets/select_button.dart b/lib/src/screens/new_wallet/widgets/select_button.dart index 87015b89e..6cca53cf5 100644 --- a/lib/src/screens/new_wallet/widgets/select_button.dart +++ b/lib/src/screens/new_wallet/widgets/select_button.dart @@ -40,7 +40,7 @@ class SelectButton extends StatelessWidget { @override Widget build(BuildContext context) { - final backgroundColor = color ?? (isSelected ? Colors.green : Theme.of(context).cardColor); + final backgroundColor = color ?? (isSelected ? Theme.of(context).primaryColor : Theme.of(context).cardColor); final effectiveTextColor = textColor ?? (isSelected ? Theme.of(context).extension()!.restoreWalletButtonTextColor diff --git a/lib/src/screens/receive/widgets/header_tile.dart b/lib/src/screens/receive/widgets/header_tile.dart index dc48db89d..68148bbee 100644 --- a/lib/src/screens/receive/widgets/header_tile.dart +++ b/lib/src/screens/receive/widgets/header_tile.dart @@ -31,7 +31,7 @@ class _HeaderTileState extends State { @override Widget build(BuildContext context) { - final searchIcon = Image.asset("assets/images/search_icon.png", + final searchIcon = Icon( Icons.search, color: Theme.of(context).extension()!.iconsColor); return Container( diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index f7e6515de..63f28d285 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -334,6 +334,26 @@ class WalletListBodyState extends State { padding: const EdgeInsets.all(24), child: Column( children: [ + PrimaryImageButton( + key: ValueKey('wallet_list_page_restore_wallet_button_key'), + onPressed: () { + if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { + widget.authService.authenticateAction( + context, + route: Routes.restoreOptions, + arguments: false, + conditionToDetermineIfToUse2FA: widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, + ); + } else { + Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false); + } + }, + image: restoreWalletImage, + text: S.of(context).wallet_list_restore_wallet, + color: Theme.of(context).cardColor, + textColor: Theme.of(context).extension()!.buttonTextColor, + ), + SizedBox(height: 10.0), PrimaryImageButton( key: ValueKey('wallet_list_page_create_new_wallet_button_key'), onPressed: () { @@ -373,26 +393,6 @@ class WalletListBodyState extends State { color: Theme.of(context).primaryColor, textColor: Colors.white, ), - SizedBox(height: 10.0), - PrimaryImageButton( - key: ValueKey('wallet_list_page_restore_wallet_button_key'), - onPressed: () { - if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { - widget.authService.authenticateAction( - context, - route: Routes.restoreOptions, - arguments: false, - conditionToDetermineIfToUse2FA: widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, - ); - } else { - Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false); - } - }, - image: restoreWalletImage, - text: S.of(context).wallet_list_restore_wallet, - color: Theme.of(context).cardColor, - textColor: Theme.of(context).extension()!.buttonTextColor, - ) ], ), ), diff --git a/lib/src/widgets/search_bar_widget.dart b/lib/src/widgets/search_bar_widget.dart index 6c7c14db2..e67c793cc 100644 --- a/lib/src/widgets/search_bar_widget.dart +++ b/lib/src/widgets/search_bar_widget.dart @@ -22,8 +22,8 @@ class SearchBarWidget extends StatelessWidget { decoration: InputDecoration( hintText: hintText ?? S.of(context).search, hintStyle: TextStyle(color: Theme.of(context).extension()!.searchHintColor), - prefixIcon: Image.asset("assets/images/search_icon.png", - color: Theme.of(context).extension()!.searchIconColor), + prefixIcon: Icon( Icons.search, + color: Theme.of(context).primaryColor), filled: true, fillColor: Theme.of(context).extension()!.searchBackgroundFillColor, alignLabelWithHint: false, diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 20dca292c..075cf6b75 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -287,7 +287,7 @@ abstract class BalanceViewModelBase with Store { BalanceRecord( availableBalance: '---', additionalBalance: '---', - frozenBalance: '---', + frozenBalance: '', secondAvailableBalance: '---', secondAdditionalBalance: '---', fiatAdditionalBalance: isFiatDisabled ? '' : '---', @@ -488,6 +488,15 @@ abstract class BalanceViewModelBase with Store { isShowCard = cardDisplayStatus; } + @action + void switchBalanceValue() { + if (settingsStore.balanceDisplayMode == BalanceDisplayMode.displayableBalance) { + settingsStore.balanceDisplayMode = BalanceDisplayMode.hiddenBalance; + } else { + settingsStore.balanceDisplayMode = BalanceDisplayMode.displayableBalance; + } + } + String _getFiatBalance({required double price, String? cryptoAmount}) { if (cryptoAmount == null || cryptoAmount.isEmpty || double.tryParse(cryptoAmount) == null) { return '0.00'; From df6ea551aacafe92ce8b387fd7e52ba184d01676 Mon Sep 17 00:00:00 2001 From: cyan Date: Thu, 12 Dec 2024 16:32:05 -0500 Subject: [PATCH 16/26] CW-848-amount-0-fee-error-fix-in-monero (#1866) * update monero_c hash * update monero_c hash * update monero_c hash * update monero_c hash * update monero_c hash --- cw_monero/lib/api/wallet.dart | 1 - cw_monero/pubspec.lock | 8 ++++---- cw_monero/pubspec.yaml | 2 +- cw_wownero/pubspec.lock | 8 ++++---- cw_wownero/pubspec.yaml | 2 +- scripts/prepare_moneroc.sh | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index f57beb5fc..78153a654 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -121,7 +121,6 @@ Future setupNodeSync( daemonUsername: login ?? '', daemonPassword: password ?? ''); }); - // monero.Wallet_init3(wptr!, argv0: '', defaultLogBaseName: 'moneroc', console: true, logPath: ''); final status = monero.Wallet_status(wptr!); diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index d8a3a4ff8..9aa076a56 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -503,8 +503,8 @@ packages: dependency: "direct main" description: path: "impls/monero.dart" - ref: c41c4dad9aa5003a914cfb2c528c76386f952665 - resolved-ref: c41c4dad9aa5003a914cfb2c528c76386f952665 + ref: af5277f96073917185864d3596e82b67bee54e78 + resolved-ref: af5277f96073917185864d3596e82b67bee54e78 url: "https://github.com/mrcyjanek/monero_c" source: git version: "0.0.0" @@ -829,10 +829,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" watcher: dependency: "direct overridden" description: diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index 36b002988..61caf93da 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: monero: git: url: https://github.com/mrcyjanek/monero_c - ref: c41c4dad9aa5003a914cfb2c528c76386f952665 + ref: af5277f96073917185864d3596e82b67bee54e78 # ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash path: impls/monero.dart mutex: ^3.1.0 diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock index 70f1f1e1d..532bb236b 100644 --- a/cw_wownero/pubspec.lock +++ b/cw_wownero/pubspec.lock @@ -463,8 +463,8 @@ packages: dependency: "direct main" description: path: "impls/monero.dart" - ref: c41c4dad9aa5003a914cfb2c528c76386f952665 - resolved-ref: c41c4dad9aa5003a914cfb2c528c76386f952665 + ref: af5277f96073917185864d3596e82b67bee54e78 + resolved-ref: af5277f96073917185864d3596e82b67bee54e78 url: "https://github.com/mrcyjanek/monero_c" source: git version: "0.0.0" @@ -757,10 +757,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" watcher: dependency: "direct overridden" description: diff --git a/cw_wownero/pubspec.yaml b/cw_wownero/pubspec.yaml index fc5782645..a92f530f6 100644 --- a/cw_wownero/pubspec.yaml +++ b/cw_wownero/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: monero: git: url: https://github.com/mrcyjanek/monero_c - ref: c41c4dad9aa5003a914cfb2c528c76386f952665 + ref: af5277f96073917185864d3596e82b67bee54e78 # ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash path: impls/monero.dart mutex: ^3.1.0 diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh index 41b12570c..c345408dd 100755 --- a/scripts/prepare_moneroc.sh +++ b/scripts/prepare_moneroc.sh @@ -8,7 +8,7 @@ if [[ ! -d "monero_c" ]]; then git clone https://github.com/mrcyjanek/monero_c --branch master cd monero_c - git checkout c41c4dad9aa5003a914cfb2c528c76386f952665 + git checkout af5277f96073917185864d3596e82b67bee54e78 git reset --hard git submodule update --init --force --recursive ./apply_patches.sh monero From 489a409beace6fac7368645f2dc02d5923a05b23 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 13 Dec 2024 01:24:37 +0200 Subject: [PATCH 17/26] Cw 807 add extra fields for xrp and xlm exchanges (#1869) * show extra id for xrp/xlm Stealth * extra id for xrp/xlm LetsExchange * extra id xrp/xml for Sideshift and Trocador * fix Exolix min amount issue * fix extra id ui --- .../provider/exolix_exchange_provider.dart | 49 +++++++++++++++---- .../letsexchange_exchange_provider.dart | 4 ++ .../provider/sideshift_exchange_provider.dart | 6 ++- .../stealth_ex_exchange_provider.dart | 4 ++ .../provider/trocador_exchange_provider.dart | 5 +- lib/exchange/trade.dart | 2 + .../trade_details_list_card.dart | 16 +++++- .../trade_details/trade_details_page.dart | 1 + lib/src/widgets/standard_list_card.dart | 12 +++++ .../exchange/exchange_trade_view_model.dart | 29 ++++++----- lib/view_model/trade_details_view_model.dart | 1 + 11 files changed, 102 insertions(+), 27 deletions(-) diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart index 49aa56195..ee5a46bbc 100644 --- a/lib/exchange/provider/exolix_exchange_provider.dart +++ b/lib/exchange/provider/exolix_exchange_provider.dart @@ -60,15 +60,17 @@ class ExolixExchangeProvider extends ExchangeProvider { Future checkIsAvailable() async => true; @override - Future fetchLimits( - {required CryptoCurrency from, - required CryptoCurrency to, - required bool isFixedRateMode}) async { + Future fetchLimits({ + required CryptoCurrency from, + required CryptoCurrency to, + required bool isFixedRateMode, + }) async { final params = { 'rateType': _getRateType(isFixedRateMode), 'amount': '1', 'apiToken': apiKey, }; + if (isFixedRateMode) { params['coinFrom'] = _normalizeCurrency(to); params['coinTo'] = _normalizeCurrency(from); @@ -80,14 +82,30 @@ class ExolixExchangeProvider extends ExchangeProvider { params['networkFrom'] = _networkFor(from); params['networkTo'] = _networkFor(to); } - final uri = Uri.https(apiBaseUrl, ratePath, params); - final response = await get(uri); - if (response.statusCode != 200) - throw Exception('Unexpected http status: ${response.statusCode}'); + // Maximum of 2 attempts to fetch limits + for (int i = 0; i < 2; i++) { + final uri = Uri.https(apiBaseUrl, ratePath, params); + final response = await get(uri); - final responseJSON = json.decode(response.body) as Map; - return Limits(min: responseJSON['minAmount'] as double?); + if (response.statusCode == 200) { + final responseJSON = json.decode(response.body) as Map; + final minAmount = responseJSON['minAmount']; + final maxAmount = responseJSON['maxAmount']; + return Limits(min: _toDouble(minAmount), max: _toDouble(maxAmount)); + } else if (response.statusCode == 422) { + final errorResponse = json.decode(response.body) as Map; + if (errorResponse.containsKey('minAmount')) { + params['amount'] = errorResponse['minAmount'].toString(); + continue; + } + throw Exception('Error 422: ${errorResponse['message'] ?? 'Unknown error'}'); + } else { + throw Exception('Unexpected HTTP status: ${response.statusCode}'); + } + } + + throw Exception('Failed to fetch limits after retrying.'); } @override @@ -279,4 +297,15 @@ class ExolixExchangeProvider extends ExchangeProvider { String _normalizeAddress(String address) => address.startsWith('bitcoincash:') ? address.replaceFirst('bitcoincash:', '') : address; + + static double? _toDouble(dynamic value) { + if (value is int) { + return value.toDouble(); + } else if (value is double) { + return value; + } else if (value is String) { + return double.tryParse(value); + } + return null; + } } diff --git a/lib/exchange/provider/letsexchange_exchange_provider.dart b/lib/exchange/provider/letsexchange_exchange_provider.dart index 0a2f81317..95520d5f0 100644 --- a/lib/exchange/provider/letsexchange_exchange_provider.dart +++ b/lib/exchange/provider/letsexchange_exchange_provider.dart @@ -168,6 +168,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { final status = responseJSON['status'] as String; final createdAtString = responseJSON['created_at'] as String; final expiredAtTimestamp = responseJSON['expired_at'] as int; + final extraId = responseJSON['deposit_extra_id'] as String?; final createdAt = DateTime.parse(createdAtString); final expiredAt = DateTime.fromMillisecondsSinceEpoch(expiredAtTimestamp * 1000); @@ -199,6 +200,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { state: TradeState.deserialize(raw: status), createdAt: createdAt, expiredAt: expiredAt, + extraId: extraId, ); } catch (e) { log(e.toString()); @@ -231,6 +233,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { final status = responseJSON['status'] as String; final createdAtString = responseJSON['created_at'] as String; final expiredAtTimestamp = responseJSON['expired_at'] as int; + final extraId = responseJSON['deposit_extra_id'] as String?; final createdAt = DateTime.parse(createdAtString); final expiredAt = DateTime.fromMillisecondsSinceEpoch(expiredAtTimestamp * 1000); @@ -249,6 +252,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider { createdAt: createdAt, expiredAt: expiredAt, isRefund: status == 'refund', + extraId: extraId, ); } diff --git a/lib/exchange/provider/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart index f53d778ec..7373d5f2d 100644 --- a/lib/exchange/provider/sideshift_exchange_provider.dart +++ b/lib/exchange/provider/sideshift_exchange_provider.dart @@ -203,6 +203,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { final inputAddress = responseJSON['depositAddress'] as String; final settleAddress = responseJSON['settleAddress'] as String; final depositAmount = responseJSON['depositAmount'] as String?; + final depositMemo = responseJSON['depositMemo'] as String?; return Trade( id: id, @@ -217,6 +218,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { payoutAddress: settleAddress, createdAt: DateTime.now(), isSendAll: isSendAll, + extraId: depositMemo ); } @@ -251,6 +253,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { final isVariable = (responseJSON['type'] as String) == 'variable'; final expiredAtRaw = responseJSON['expiresAt'] as String; final expiredAt = isVariable ? null : DateTime.tryParse(expiredAtRaw)?.toLocal(); + final depositMemo = responseJSON['depositMemo'] as String?; return Trade( id: id, @@ -261,7 +264,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { amount: expectedSendAmount ?? '', state: TradeState.deserialize(raw: status ?? 'created'), expiredAt: expiredAt, - payoutAddress: settleAddress); + payoutAddress: settleAddress, + extraId: depositMemo); } Future _createQuote(TradeRequest request) async { diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart index 123f759ef..53c40ee62 100644 --- a/lib/exchange/provider/stealth_ex_exchange_provider.dart +++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart @@ -154,6 +154,7 @@ class StealthExExchangeProvider extends ExchangeProvider { final receiveAmount = toDouble(withdrawal['amount']); final status = responseJSON['status'] as String; final createdAtString = responseJSON['created_at'] as String; + final extraId = deposit['extra_id'] as String?; final createdAt = DateTime.parse(createdAtString); final expiredAt = validUntil != null @@ -188,6 +189,7 @@ class StealthExExchangeProvider extends ExchangeProvider { state: TradeState.deserialize(raw: status), createdAt: createdAt, expiredAt: expiredAt, + extraId: extraId, ); } catch (e) { log(e.toString()); @@ -220,6 +222,7 @@ class StealthExExchangeProvider extends ExchangeProvider { final status = responseJSON['status'] as String; final createdAtString = responseJSON['created_at'] as String; final createdAt = DateTime.parse(createdAtString); + final extraId = deposit['extra_id'] as String?; return Trade( id: respId, @@ -234,6 +237,7 @@ class StealthExExchangeProvider extends ExchangeProvider { state: TradeState.deserialize(raw: status), createdAt: createdAt, isRefund: status == 'refunded', + extraId: extraId, ); } diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index b01ce9eae..151ded371 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -171,7 +171,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { if (!isFixedRateMode) 'amount_from': request.fromAmount, if (isFixedRateMode) 'amount_to': request.toAmount, 'address': request.toAddress, - 'refund': request.refundAddress + 'refund': request.refundAddress, + 'refund_memo' : '0', }; if (isFixedRateMode) { @@ -262,6 +263,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { final password = responseJSON['password'] as String; final providerId = responseJSON['id_provider'] as String; final providerName = responseJSON['provider'] as String; + final addressProviderMemo = responseJSON['address_provider_memo'] as String?; return Trade( id: id, @@ -277,6 +279,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { password: password, providerId: providerId, providerName: providerName, + extraId: addressProviderMemo, ); }); } diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index a0c08aac7..c5738cfd9 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -143,6 +143,7 @@ class Trade extends HiveObject { isRefund: map['isRefund'] as bool?, isSendAll: map['isSendAll'] as bool?, router: map['router'] as String?, + extraId: map['extra_id'] as String?, ); } @@ -162,6 +163,7 @@ class Trade extends HiveObject { 'isRefund': isRefund, 'isSendAll': isSendAll, 'router': router, + 'extra_id': extraId, }; } diff --git a/lib/src/screens/trade_details/trade_details_list_card.dart b/lib/src/screens/trade_details/trade_details_list_card.dart index 9c543a964..64f727b91 100644 --- a/lib/src/screens/trade_details/trade_details_list_card.dart +++ b/lib/src/screens/trade_details/trade_details_list_card.dart @@ -8,7 +8,8 @@ class TradeDetailsListCardItem extends StandartListItem { {required this.id, required this.createdAt, required this.pair, - required this.onTap}) + required this.onTap, + this.extraId}) : super(title: '', value: ''); factory TradeDetailsListCardItem.tradeDetails( @@ -16,9 +17,19 @@ class TradeDetailsListCardItem extends StandartListItem { required String createdAt, required CryptoCurrency from, required CryptoCurrency to, - required void Function(BuildContext) onTap}) { + required void Function(BuildContext) onTap, + String? extraId}) { + + + final extraIdTitle = from == CryptoCurrency.xrp + ? S.current.destination_tag + : from == CryptoCurrency.xlm + ? S.current.memo + : S.current.extra_id; + return TradeDetailsListCardItem( id: '${S.current.trade_details_id} ${formatAsText(id)}', + extraId: extraId != null ? '$extraIdTitle $extraId' : null, createdAt: formatAsText(createdAt), pair: '${formatAsText(from)} → ${formatAsText(to)}', onTap: onTap); @@ -27,6 +38,7 @@ class TradeDetailsListCardItem extends StandartListItem { final String id; final String createdAt; final String pair; + final String? extraId; final void Function(BuildContext) onTap; static String formatAsText(T value) => value?.toString() ?? ''; diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 1028c3939..40d14fa14 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -69,6 +69,7 @@ class TradeDetailsPageBodyState extends State { if (item is TradeDetailsListCardItem) return TradeDetailsStandardListCard( id: item.id, + extraId: item.extraId, create: item.createdAt, pair: item.pair, currentTheme: tradeDetailsViewModel.settingsStore.currentTheme.type, diff --git a/lib/src/widgets/standard_list_card.dart b/lib/src/widgets/standard_list_card.dart index 4b16e1ad4..c86df0b9d 100644 --- a/lib/src/widgets/standard_list_card.dart +++ b/lib/src/widgets/standard_list_card.dart @@ -6,12 +6,14 @@ import 'package:cake_wallet/themes/theme_base.dart'; class TradeDetailsStandardListCard extends StatelessWidget { TradeDetailsStandardListCard( {required this.id, + this.extraId, required this.create, required this.pair, required this.onTap, required this.currentTheme}); final String id; + final String? extraId; final String create; final String pair; final ThemeType currentTheme; @@ -57,6 +59,16 @@ class TradeDetailsStandardListCard extends StatelessWidget { SizedBox( height: 8, ), + if (extraId != null && extraId!.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text(extraId!, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: textColor)), + ), Text(create, style: TextStyle( fontSize: 12, diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index ac0456440..0c8053842 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -146,7 +146,7 @@ abstract class ExchangeTradeViewModelBase with Store { void _updateItems() { final tagFrom = - tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : ''; + tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : ''; final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : ''; items.clear(); @@ -159,16 +159,6 @@ abstract class ExchangeTradeViewModelBase with Store { ), ); - if (trade.extraId != null) { - final title = trade.from == CryptoCurrency.xrp - ? S.current.destination_tag - : trade.from == CryptoCurrency.xlm - ? S.current.memo - : S.current.extra_id; - - items.add(ExchangeTradeItem(title: title, data: '${trade.extraId}', isCopied: false)); - } - items.addAll([ ExchangeTradeItem( title: S.current.amount, @@ -176,7 +166,7 @@ abstract class ExchangeTradeViewModelBase with Store { isCopied: true, ), ExchangeTradeItem( - title: S.current.estimated_receive_amount +':', + title: S.current.estimated_receive_amount + ':', data: '${tradesStore.trade?.receiveAmount} ${trade.to}', isCopied: true, ), @@ -185,12 +175,25 @@ abstract class ExchangeTradeViewModelBase with Store { data: trade.inputAddress ?? '', isCopied: true, ), + ]); + + if (trade.extraId != null) { + final title = trade.from == CryptoCurrency.xrp + ? S.current.destination_tag + : trade.from == CryptoCurrency.xlm + ? S.current.memo + : S.current.extra_id; + + items.add(ExchangeTradeItem(title: title, data: '${trade.extraId}', isCopied: true)); + } + + items.add( ExchangeTradeItem( title: S.current.arrive_in_this_address('${tradesStore.trade!.to}', tagTo) + ':', data: trade.payoutAddress ?? '', isCopied: true, ), - ]); + ); } static bool _checkIfCanSend(TradesStore tradesStore, WalletBase wallet) { diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index 59813090d..db7b979d9 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -153,6 +153,7 @@ abstract class TradeDetailsViewModelBase with Store { items.add(TradeDetailsListCardItem.tradeDetails( id: trade.id, + extraId: trade.extraId, createdAt: trade.createdAt != null ? dateFormat.format(trade.createdAt!) : '', from: trade.from, to: trade.to, From e21cf7113d613c77287d59f5068fb9f80e2d7cf4 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:44:39 +0100 Subject: [PATCH 18/26] CW-703: Better Seed UI/UX - Fix for Japanese PolySeeds (#1875) * feat: Switch UI for seeds display * feat: Add localization for disclaimer text * fix: Modify color for warning on seeds screen * Fix: Adjust UI styling for seed page * chore: Revert podfile.lock * Fix column colors * Fix more colors * Fix more colors and update strings * fix: Error extracting seed words in Japanese because of spacing type used --------- Co-authored-by: tuxpizza --- lib/src/screens/seed/wallet_seed_page.dart | 30 ++++++++++++---------- lib/view_model/wallet_seed_view_model.dart | 5 +++- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index fe532e7fb..b1ab7471b 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/clipboard_util.dart'; @@ -139,8 +138,8 @@ class WalletSeedPage extends BasePage { fontSize: 12, fontWeight: FontWeight.w800, color: currentTheme.type == ThemeType.dark - ? Colors.white.withOpacity(0.75) - : Colors.white.withOpacity(0.85), + ? Colors.white.withOpacity(0.75) + : Colors.white.withOpacity(0.85), ), ), ), @@ -188,19 +187,24 @@ class WalletSeedPage extends BasePage { numberCount.toString(), textAlign: TextAlign.right, style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w700, - color: Theme.of(context).extension()!.buttonTextColor.withOpacity(0.5) - ), + fontSize: 14, + fontWeight: FontWeight.w700, + color: Theme.of(context) + .extension()! + .buttonTextColor + .withOpacity(0.5)), ), ), const SizedBox(width: 8), - Text( - '${item[0].toUpperCase()}${item.substring(1)}', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w700, - color: Theme.of(context).extension()!.buttonTextColor + Expanded( + child: Text( + '${item[0].toUpperCase()}${item.substring(1)}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + color: Theme.of(context) + .extension()! + .buttonTextColor), ), ), ], diff --git a/lib/view_model/wallet_seed_view_model.dart b/lib/view_model/wallet_seed_view_model.dart index c13dba716..be348fd09 100644 --- a/lib/view_model/wallet_seed_view_model.dart +++ b/lib/view_model/wallet_seed_view_model.dart @@ -16,7 +16,10 @@ abstract class WalletSeedViewModelBase with Store { @observable String seed; - List get seedSplit => seed.split(' '); + /// The Regex split the words based on any whitespace character. + /// + /// Either standard ASCII space (U+0020) or the full-width space character (U+3000) used by the Japanese. + List get seedSplit => seed.split(RegExp(r'\s+')); int get columnCount => seedSplit.length <= 16 ? 2 : 3; } From 3ad04227a48f7d1d52970e2d20eb0be651fa8c34 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:45:41 +0100 Subject: [PATCH 19/26] test: Attempting automation for testing (#1734) * feat: Integration tests setup and tests for Disclaimer, Welcome and Setup Pin Code pages * feat: Integration test flow from start to restoring a wallet successfully done * test: Dashboard view test and linking to flow * feat: Testing the Exchange flow section, selecting sending and receiving currencies * test: Successfully create an exchange section * feat: Implement flow up to sending section * test: Complete Exchange flow * fix dependency issue * test: Final cleanups * feat: Add CI to run automated integration tests withan android emulator * feat: Adjust Automated integration test CI to run on ubuntu 20.04-a * fix: Move integration test CI into PR test build CI * ci: Add automated test ci which is a streamlined replica of pr test build ci * ci: Re-add step to access branch name * ci: Add KVM * ci: Add filepath to trigger the test run from * ci: Add required key * ci: Add required key * ci: Add missing secret key * ci: Add missing secret key * ci: Add nano secrets to workflow * ci: Switch step to free space on runner * ci: Remove timeout from workflow * ci: Confirm impact that removing copy_monero_deps would have on entire workflow time * ci: Update CI and temporarily remove cache related to emulator * ci: Remove dynamic java version * ci: Temporarily switch CI * ci: Switch to 11.x jdk * ci: Temporarily switch CI * ci: Revert ubuntu version * ci: Add more api levels * ci: Add more target options * ci: Settled on stable emulator matrix options * ci: Add more target options * ci: Modify flow * ci: Streamline api levels to 28 and 29 * ci: One more trial * ci: Switch to flutter drive * ci: Reduce options * ci: Remove haven from test * ci: Check for solana in list * ci: Adjust amounts and currencies for exchange flow * ci: Set write response on failure to true * ci: Split ci to funds and non funds related tests * test: Test for Send flow scenario and minor restructuring for test folders and files * chore: cleanup * ci: Pause CI for now * ci: Pause CI for now * ci: Pause CI for now * test: Restore wallets integration automated tests * Fix: Add keys back to currency amount textfield widget * fix: Switch variable name * fix: remove automation for now * tests: Automated tests for Create wallets flow * tests: Further optimize common flows * tests: Add missing await for call * tests: Confirm Seeds Display Properly WIP * tests: Confirm Seeds Display Correctly Automated Tests * fix: Add missing pubspec params for bitcoin and bitcoin_cash * feat: Automated Tests for Transaction History Flow * fix: Add missing pubspec parameter * feat: Automated Integration Tests for Transaction History flow * test: Updating send page robot and also syncing branch with main * test: Modifying tests to flow with wallet grouping implementation * fix: Issue with transaction history test * fix: Modifications to the PR and add automated confirmation for checking that all wallet types are restored or created correctly * test: Attempting automation for testing * test: Attempting automation for testing * test: Print out working directory * test: See if I can cut down time by removing the build step * test: More logs * test: Pubspec was not generated, checking if this fixes it * test: Pubspec was not generated, checking if this fixes it * test: Pubspec was not generated, checking if this fixes it * test: Pubspec was not generated, checking if this fixes it * test: Pubspec was not generated, checking if this fixes it * test: Pubspec was not generated, checking if this fixes it * test: Another trial * test: Another trial * test: Another trial * test: Another trial * test: Another trial * test: Another trial * fix: Adjust config file * test: Add commands to generate files and set codebase up as new * test: try another route * test: try another route - 2 * test: try another route * test: try another route - 2 * test: Uncomment KVM and optimizations-a * test: Try with sudo permissions-a * test: Try again * test: Pause build and rename steps, see how faster it resolves * test: Try using working directory * test: Check details of current working directory * test: Switch test run command from flutter drive to flutter test * test: Adding secrets to CI workflow * fix: add working directory to emulator and reactivate build step * test: Add verbosity * test: Check tat emulator is present and ready to connect * test: Try a direct test to see if it'll trigger properly * test: Try the flutter drive command * test: Try uninstalling before running * test: Create an aggregator test file as the entry point for all tests * test: Try without awaiting each test * test: Another trial at getting combined tests running * test: Use a test runner script that'll be responsible for running all available integration tests * test: Add command to make integration test runner file an executable * test: Fix failing exchange flow test * test: fix failing exchange flow test * test: Fix issue with send flow test * test: Fix issue with confirm seeds flow test * test: Modify create and restore flows to reflect modified onboarding flow * chore: Remove package declaration in AndroidManifestBase file to fix issue of it being deprecated * test: Bump up flutter version * fix: Add meld keys * chore: Remove package name declarations from AndroidManifests * better write close function definition comment integration tests workflow for now --------- Co-authored-by: OmarHatem --- .../workflows/automated_integration_test.yml | 298 ++++++++++++++++++ .github/workflows/pr_test_build_android.yml | 2 +- cw_bitcoin/lib/electrum_wallet.dart | 2 +- cw_bitcoin/lib/litecoin_wallet.dart | 2 +- cw_core/lib/wallet_base.dart | 2 +- cw_evm/lib/evm_chain_wallet.dart | 2 +- cw_haven/lib/haven_wallet.dart | 2 +- cw_monero/lib/monero_wallet.dart | 2 +- cw_nano/lib/nano_wallet.dart | 2 +- cw_solana/lib/solana_wallet.dart | 2 +- cw_tron/lib/tron_wallet.dart | 2 +- cw_wownero/lib/wownero_wallet.dart | 2 +- .../components/common_test_constants.dart | 6 +- .../components/common_test_flows.dart | 13 +- .../robots/create_pin_welcome_page_robot.dart | 53 ++++ .../robots/exchange_page_robot.dart | 14 +- integration_test/robots/send_page_robot.dart | 11 +- .../robots/wallet_keys_robot.dart | 18 +- .../test_suites/confirm_seeds_flow_test.dart | 2 +- integration_test_runner.sh | 45 +++ .../screens/wallet_keys/wallet_keys_page.dart | 1 + lib/src/widgets/search_bar_widget.dart | 1 + 22 files changed, 446 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/automated_integration_test.yml create mode 100644 integration_test/robots/create_pin_welcome_page_robot.dart create mode 100755 integration_test_runner.sh diff --git a/.github/workflows/automated_integration_test.yml b/.github/workflows/automated_integration_test.yml new file mode 100644 index 000000000..588bc1821 --- /dev/null +++ b/.github/workflows/automated_integration_test.yml @@ -0,0 +1,298 @@ +#name: Automated Integration Tests +# +#on: +# pull_request: +# branches: [main, CW-659-Transaction-History-Automated-Tests] +# workflow_dispatch: +# inputs: +# branch: +# description: "Branch name to build" +# required: true +# default: "main" +# +#jobs: +# Automated_integration_test: +# runs-on: ubuntu-20.04 +# strategy: +# fail-fast: false +# matrix: +# api-level: [29] +# # arch: [x86, x86_64] +# env: +# STORE_PASS: test@cake_wallet +# KEY_PASS: test@cake_wallet +# PR_NUMBER: ${{ github.event.number }} +# +# steps: +# - name: is pr +# if: github.event_name == 'pull_request' +# run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV +# +# - name: is not pr +# if: github.event_name != 'pull_request' +# run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENV +# +# - name: Free Disk Space (Ubuntu) +# uses: insightsengineering/disk-space-reclaimer@v1 +# with: +# tools-cache: true +# android: false +# dotnet: true +# haskell: true +# large-packages: true +# swap-storage: true +# docker-images: true +# +# - uses: actions/checkout@v2 +# - uses: actions/setup-java@v2 +# with: +# distribution: "temurin" +# java-version: "17" +# - name: Configure placeholder git details +# run: | +# git config --global user.email "CI@cakewallet.com" +# git config --global user.name "Cake Github Actions" +# - name: Flutter action +# uses: subosito/flutter-action@v1 +# with: +# flutter-version: "3.24.0" +# channel: stable +# +# - name: Install package dependencies +# run: | +# sudo apt update +# sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang +# +# - name: Execute Build and Setup Commands +# run: | +# sudo mkdir -p /opt/android +# sudo chown $USER /opt/android +# cd /opt/android +# -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +# cargo install cargo-ndk +# git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} +# cd cake_wallet/scripts/android/ +# ./install_ndk.sh +# source ./app_env.sh cakewallet +# chmod +x pubspec_gen.sh +# ./app_config.sh +# +# - name: Cache Externals +# id: cache-externals +# uses: actions/cache@v3 +# with: +# path: | +# /opt/android/cake_wallet/cw_haven/android/.cxx +# /opt/android/cake_wallet/scripts/monero_c/release +# key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }} +# +# - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} +# name: Generate Externals +# run: | +# cd /opt/android/cake_wallet/scripts/android/ +# source ./app_env.sh cakewallet +# ./build_monero_all.sh +# +# - name: Install Flutter dependencies +# run: | +# cd /opt/android/cake_wallet +# flutter pub get +# +# +# - name: Install go and gomobile +# run: | +# # install go > 1.23: +# wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz +# sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz +# export PATH=$PATH:/usr/local/go/bin +# export PATH=$PATH:~/go/bin +# go install golang.org/x/mobile/cmd/gomobile@latest +# gomobile init +# +# - name: Build mwebd +# run: | +# # paths are reset after each step, so we need to set them again: +# export PATH=$PATH:/usr/local/go/bin +# export PATH=$PATH:~/go/bin +# cd /opt/android/cake_wallet/scripts/android/ +# ./build_mwebd.sh --dont-install +# +# - name: Generate KeyStore +# run: | +# cd /opt/android/cake_wallet/android/app +# keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS +# +# - name: Generate key properties +# run: | +# cd /opt/android/cake_wallet +# flutter packages pub run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS +# +# - name: Generate localization +# run: | +# cd /opt/android/cake_wallet +# flutter packages pub run tool/generate_localization.dart +# +# - name: Build generated code +# run: | +# cd /opt/android/cake_wallet +# ./model_generator.sh +# +# - name: Add secrets +# run: | +# cd /opt/android/cake_wallet +# touch lib/.secrets.g.dart +# touch cw_evm/lib/.secrets.g.dart +# touch cw_solana/lib/.secrets.g.dart +# touch cw_core/lib/.secrets.g.dart +# touch cw_nano/lib/.secrets.g.dart +# touch cw_tron/lib/.secrets.g.dart +# echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart +# echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart +# echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart +# echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart +# echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart +# echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart +# echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart +# echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart +# echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart +# echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart +# echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart +# echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart +# echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart +# echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart +# echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart +# 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 }}';" >> lib/.secrets.g.dart +# echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_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 +# echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart +# echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart +# echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart +# echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart +# echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart +# echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const quantexExchangeMarkup = '${{ secrets.QUANTEX_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart +# echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart +# echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart +# echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart +# echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart +# echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart +# echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dart +# echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart +# echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart +# echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart +# echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const litecoinTestWalletSeeds = '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const bitcoinCashTestWalletSeeds = '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const nanoTestWalletSeeds = '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart +# echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const bitcoinTestWalletReceiveAddress = '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const ethereumTestWalletReceiveAddress = '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const litecoinTestWalletReceiveAddress = '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const polygonTestWalletReceiveAddress = '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const solanaTestWalletReceiveAddress = '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const tronTestWalletReceiveAddress = '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart +# echo "const moneroTestWalletBlockHeight = '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart +# +# - name: Rename app +# run: | +# echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties +# +# - name: Build +# run: | +# cd /opt/android/cake_wallet +# flutter build apk --release --split-per-abi +# +# # - name: Rename apk file +# # run: | +# # cd /opt/android/cake_wallet/build/app/outputs/flutter-apk +# # mkdir test-apk +# # cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk +# # cp app-x86_64-release.apk test-apk/${{env.BRANCH_NAME}}_x86.apk +# +# # - name: Upload Artifact +# # uses: kittaakos/upload-artifact-as-is@v0 +# # with: +# # path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/ +# +# # - name: Send Test APK +# # continue-on-error: true +# # uses: adrey/slack-file-upload-action@1.0.5 +# # with: +# # token: ${{ secrets.SLACK_APP_TOKEN }} +# # path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk +# # channel: ${{ secrets.SLACK_APK_CHANNEL }} +# # title: "${{ env.BRANCH_NAME }}.apk" +# # filename: ${{ env.BRANCH_NAME }}.apk +# # initial_comment: ${{ github.event.head_commit.message }} +# +# - name: 🦾 Enable KVM +# run: | +# echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules +# sudo udevadm control --reload-rules +# sudo udevadm trigger --name-match=kvm +# +# - name: 🦾 Cache gradle +# uses: gradle/actions/setup-gradle@v3 +# +# - name: 🦾 Cache AVD +# uses: actions/cache@v4 +# id: avd-cache +# with: +# path: | +# ~/.android/avd/* +# ~/.android/adb* +# key: avd-${{ matrix.api-level }} +# +# - name: 🦾 Create AVD and generate snapshot for caching +# if: steps.avd-cache.outputs.cache-hit != 'true' +# uses: reactivecircus/android-emulator-runner@v2 +# with: +# api-level: ${{ matrix.api-level }} +# force-avd-creation: false +# # arch: ${{ matrix.arch }} +# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none +# working-directory: /opt/android/cake_wallet +# disable-animations: false +# script: echo "Generated AVD snapshot for caching." +# +# - name: 🚀 Integration tests on Android Emulator +# uses: reactivecircus/android-emulator-runner@v2 +# with: +# api-level: ${{ matrix.api-level }} +# force-avd-creation: false +# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none +# disable-animations: true +# working-directory: /opt/android/cake_wallet +# script: | +# chmod a+rx integration_test_runner.sh +# ./integration_test_runner.sh \ No newline at end of file diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index ab198dfb2..d98c0b77b 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -207,7 +207,7 @@ jobs: echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart - echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar + echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dart echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index d4f0e4adc..a5bb9c655 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -1346,7 +1346,7 @@ abstract class ElectrumWalletBase } @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { try { await _receiveStream?.cancel(); await electrumClient.close(); diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index e55516e9a..f7cc20bcd 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1191,7 +1191,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { } @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _utxoStream?.cancel(); _feeRatesTimer?.cancel(); _syncTimer?.cancel(); diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 112a20852..16c794a25 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -83,7 +83,7 @@ abstract class WalletBase rescan({required int height}); - Future close({required bool shouldCleanup}); + Future close({bool shouldCleanup = false}); Future changePassword(String password); diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index eb93bd94f..dca16539c 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -270,7 +270,7 @@ abstract class EVMChainWalletBase } @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _client.stop(); _transactionsUpdateTimer?.cancel(); _updateFeesTimer?.cancel(); diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 734a6da9c..6c372d344 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -108,7 +108,7 @@ abstract class HavenWalletBase Future? updateBalance() => null; @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _listener?.stop(); _onAccountChangeReaction?.reaction.dispose(); _autoSaveTimer?.cancel(); diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 83d9504ad..21d5b6d4b 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -175,7 +175,7 @@ abstract class MoneroWalletBase extends WalletBase? updateBalance() => null; @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _listener?.stop(); _onAccountChangeReaction?.reaction.dispose(); _onTxHistoryChangeReaction?.reaction.dispose(); diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index f1d66a4a8..b48335857 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -150,7 +150,7 @@ abstract class NanoWalletBase Future changePassword(String password) => throw UnimplementedError("changePassword"); @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _client.stop(); _receiveTimer?.cancel(); } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 3a2d281e3..c884d8e82 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -180,7 +180,7 @@ abstract class SolanaWalletBase Future changePassword(String password) => throw UnimplementedError("changePassword"); @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _client.stop(); _transactionsUpdateTimer?.cancel(); } diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart index 3cd8bfc99..cfa80f0d3 100644 --- a/cw_tron/lib/tron_wallet.dart +++ b/cw_tron/lib/tron_wallet.dart @@ -217,7 +217,7 @@ abstract class TronWalletBase Future changePassword(String password) => throw UnimplementedError("changePassword"); @override - Future close({required bool shouldCleanup}) async => _transactionsUpdateTimer?.cancel(); + Future close({bool shouldCleanup = false}) async => _transactionsUpdateTimer?.cancel(); @action @override diff --git a/cw_wownero/lib/wownero_wallet.dart b/cw_wownero/lib/wownero_wallet.dart index db0fe7bd8..c4c79af11 100644 --- a/cw_wownero/lib/wownero_wallet.dart +++ b/cw_wownero/lib/wownero_wallet.dart @@ -162,7 +162,7 @@ abstract class WowneroWalletBase Future? updateBalance() => null; @override - Future close({required bool shouldCleanup}) async { + Future close({bool shouldCleanup = false}) async { _listener?.stop(); _onAccountChangeReaction?.reaction.dispose(); _onTxHistoryChangeReaction?.reaction.dispose(); diff --git a/integration_test/components/common_test_constants.dart b/integration_test/components/common_test_constants.dart index 302d52189..6ace69b45 100644 --- a/integration_test/components/common_test_constants.dart +++ b/integration_test/components/common_test_constants.dart @@ -4,10 +4,10 @@ import 'package:cw_core/wallet_type.dart'; class CommonTestConstants { static final pin = [0, 8, 0, 1]; static final String sendTestAmount = '0.00008'; - static final String exchangeTestAmount = '8'; + static final String exchangeTestAmount = '0.01'; static final WalletType testWalletType = WalletType.solana; static final String testWalletName = 'Integrated Testing Wallet'; - static final CryptoCurrency testReceiveCurrency = CryptoCurrency.sol; - static final CryptoCurrency testDepositCurrency = CryptoCurrency.usdtSol; + static final CryptoCurrency testReceiveCurrency = CryptoCurrency.usdtSol; + static final CryptoCurrency testDepositCurrency = CryptoCurrency.sol; static final String testWalletAddress = '5v9gTW1yWPffhnbNKuvtL2frevAf4HpBMw8oYnfqUjhm'; } diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart index 82f714da0..8350b5859 100644 --- a/integration_test/components/common_test_flows.dart +++ b/integration_test/components/common_test_flows.dart @@ -7,6 +7,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:cake_wallet/main.dart' as app; +import '../robots/create_pin_welcome_page_robot.dart'; import '../robots/dashboard_page_robot.dart'; import '../robots/disclaimer_page_robot.dart'; import '../robots/new_wallet_page_robot.dart'; @@ -37,6 +38,7 @@ class CommonTestFlows { _walletListPageRobot = WalletListPageRobot(_tester), _newWalletTypePageRobot = NewWalletTypePageRobot(_tester), _restoreOptionsPageRobot = RestoreOptionsPageRobot(_tester), + _createPinWelcomePageRobot = CreatePinWelcomePageRobot(_tester), _restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(_tester), _walletGroupDescriptionPageRobot = WalletGroupDescriptionPageRobot(_tester); @@ -53,6 +55,7 @@ class CommonTestFlows { final WalletListPageRobot _walletListPageRobot; final NewWalletTypePageRobot _newWalletTypePageRobot; final RestoreOptionsPageRobot _restoreOptionsPageRobot; + final CreatePinWelcomePageRobot _createPinWelcomePageRobot; final RestoreFromSeedOrKeysPageRobot _restoreFromSeedOrKeysPageRobot; final WalletGroupDescriptionPageRobot _walletGroupDescriptionPageRobot; @@ -190,10 +193,12 @@ class CommonTestFlows { WalletType walletTypeToCreate, List pin, ) async { - await _welcomePageRobot.navigateToCreateNewWalletPage(); + await _createPinWelcomePageRobot.tapSetAPinButton(); await setupPinCodeForWallet(pin); + await _welcomePageRobot.navigateToCreateNewWalletPage(); + await _selectWalletTypeForWallet(walletTypeToCreate); } @@ -201,12 +206,14 @@ class CommonTestFlows { WalletType walletTypeToRestore, List pin, ) async { + await _createPinWelcomePageRobot.tapSetAPinButton(); + + await setupPinCodeForWallet(pin); + await _welcomePageRobot.navigateToRestoreWalletPage(); await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); - await setupPinCodeForWallet(pin); - await _selectWalletTypeForWallet(walletTypeToRestore); } diff --git a/integration_test/robots/create_pin_welcome_page_robot.dart b/integration_test/robots/create_pin_welcome_page_robot.dart new file mode 100644 index 000000000..ca136cb38 --- /dev/null +++ b/integration_test/robots/create_pin_welcome_page_robot.dart @@ -0,0 +1,53 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/welcome/create_pin_welcome_page.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../components/common_test_cases.dart'; + +class CreatePinWelcomePageRobot { + CreatePinWelcomePageRobot(this.tester) : commonTestCases = CommonTestCases(tester); + + final WidgetTester tester; + late CommonTestCases commonTestCases; + + Future isCreatePinWelcomePage() async { + await commonTestCases.isSpecificPage(); + } + + void hasTitle() { + String title; + if (isMoneroOnly) { + title = S.current.monero_com; + } + + if (isHaven) { + title = S.current.haven_app; + } + + title = S.current.cake_wallet; + + commonTestCases.hasText(title); + } + + void hasDescription() { + String description; + if (isMoneroOnly) { + description = S.current.monero_com_wallet_text; + } + + if (isHaven) { + description = S.current.haven_app_wallet_text; + } + + description = S.current.new_first_wallet_text; + + commonTestCases.hasText(description); + } + + Future tapSetAPinButton() async { + await commonTestCases.tapItemByKey('create_pin_welcome_page_create_a_pin_button_key'); + + await commonTestCases.defaultSleepTime(); + } +} diff --git a/integration_test/robots/exchange_page_robot.dart b/integration_test/robots/exchange_page_robot.dart index e01b2df9c..a3378e293 100644 --- a/integration_test/robots/exchange_page_robot.dart +++ b/integration_test/robots/exchange_page_robot.dart @@ -123,10 +123,8 @@ class ExchangePageRobot { return; } - await commonTestCases.dragUntilVisible( - 'picker_items_index_${depositCurrency.name}_button_key', - 'picker_scrollbar_key', - ); + await commonTestCases.enterText(depositCurrency.name, 'search_bar_widget_key'); + await commonTestCases.defaultSleepTime(); await commonTestCases.tapItemByKey('picker_items_index_${depositCurrency.name}_button_key'); @@ -149,10 +147,8 @@ class ExchangePageRobot { return; } - await commonTestCases.dragUntilVisible( - 'picker_items_index_${receiveCurrency.name}_button_key', - 'picker_scrollbar_key', - ); + await commonTestCases.enterText(receiveCurrency.name, 'search_bar_widget_key'); + await commonTestCases.defaultSleepTime(); await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.name}_button_key'); @@ -318,7 +314,7 @@ class ExchangePageRobot { Future handleErrors(String initialAmount) async { await tester.pumpAndSettle(); - + await _handleMinLimitError(initialAmount); await _handleMaxLimitError(initialAmount); diff --git a/integration_test/robots/send_page_robot.dart b/integration_test/robots/send_page_robot.dart index 20cef948d..f8e1a49ad 100644 --- a/integration_test/robots/send_page_robot.dart +++ b/integration_test/robots/send_page_robot.dart @@ -84,13 +84,11 @@ class SendPageRobot { return; } - await commonTestCases.dragUntilVisible( - 'picker_items_index_${receiveCurrency.name}_button_key', - 'picker_scrollbar_key', - ); + await commonTestCases.enterText(receiveCurrency.title, 'search_bar_widget_key'); + await commonTestCases.defaultSleepTime(); - await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.name}_button_key'); + await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.fullName}_button_key'); } Future enterReceiveAddress(String receiveAddress) async { @@ -210,6 +208,7 @@ class SendPageRobot { _handleAuthPage(); } } + await tester.pump(); } Future handleSendResult() async { @@ -366,4 +365,4 @@ class SendPageRobot { Future _onIgnoreButtonOnSentDialogPressed() async { await commonTestCases.tapItemByKey('send_page_sent_dialog_ignore_button_key'); } -} \ No newline at end of file +} diff --git a/integration_test/robots/wallet_keys_robot.dart b/integration_test/robots/wallet_keys_robot.dart index f6aeb3a66..189929737 100644 --- a/integration_test/robots/wallet_keys_robot.dart +++ b/integration_test/robots/wallet_keys_robot.dart @@ -42,11 +42,11 @@ class WalletKeysAndSeedPageRobot { bool hasPrivateKey = appStore.wallet!.privateKey != null; if (walletType == WalletType.monero) { - final moneroWallet = appStore.wallet as MoneroWallet; + final moneroWallet = appStore.wallet as MoneroWalletBase; final lang = PolyseedLang.getByPhrase(moneroWallet.seed); final legacySeed = moneroWallet.seedLegacy(lang.nameEnglish); - _confirmMoneroWalletCredentials( + await _confirmMoneroWalletCredentials( appStore, walletName, moneroWallet.seed, @@ -59,7 +59,7 @@ class WalletKeysAndSeedPageRobot { final lang = PolyseedLang.getByPhrase(wowneroWallet.seed); final legacySeed = wowneroWallet.seedLegacy(lang.nameEnglish); - _confirmMoneroWalletCredentials( + await _confirmMoneroWalletCredentials( appStore, walletName, wowneroWallet.seed, @@ -105,12 +105,12 @@ class WalletKeysAndSeedPageRobot { await commonTestCases.defaultSleepTime(seconds: 5); } - void _confirmMoneroWalletCredentials( + Future _confirmMoneroWalletCredentials( AppStore appStore, String walletName, String seed, String legacySeed, - ) { + ) async { final keys = appStore.wallet!.keys as MoneroWalletKeys; final hasPublicSpendKey = commonTestCases.isKeyPresent( @@ -145,10 +145,18 @@ class WalletKeysAndSeedPageRobot { tester.printToConsole('$walletName wallet has private view key properly displayed'); } if (hasSeeds) { + await commonTestCases.dragUntilVisible( + '${walletName}_wallet_seed_item_key', + 'wallet_keys_page_credentials_list_view_key', + ); commonTestCases.hasText(seed); tester.printToConsole('$walletName wallet has seeds properly displayed'); } if (hasSeedLegacy) { + await commonTestCases.dragUntilVisible( + '${walletName}_wallet_seed_legacy_item_key', + 'wallet_keys_page_credentials_list_view_key', + ); commonTestCases.hasText(legacySeed); tester.printToConsole('$walletName wallet has legacy seeds properly displayed'); } diff --git a/integration_test/test_suites/confirm_seeds_flow_test.dart b/integration_test/test_suites/confirm_seeds_flow_test.dart index bf6fd5a5f..2d11a2cc4 100644 --- a/integration_test/test_suites/confirm_seeds_flow_test.dart +++ b/integration_test/test_suites/confirm_seeds_flow_test.dart @@ -101,7 +101,7 @@ Future _confirmSeedsFlowForWalletType( walletKeysAndSeedPageRobot.hasTitle(); walletKeysAndSeedPageRobot.hasShareWarning(); - walletKeysAndSeedPageRobot.confirmWalletCredentials(walletType); + await walletKeysAndSeedPageRobot.confirmWalletCredentials(walletType); await walletKeysAndSeedPageRobot.backToDashboard(); } diff --git a/integration_test_runner.sh b/integration_test_runner.sh new file mode 100755 index 000000000..34c9227c0 --- /dev/null +++ b/integration_test_runner.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +declare -a targets +declare -a passed_tests +declare -a failed_tests + +# Collect all Dart test files in the integration_test directory +while IFS= read -r -d $'\0' file; do + targets+=("$file") +done < <(find integration_test/test_suites -name "*.dart" -type f -print0) + +# Run each test and collect results +for target in "${targets[@]}" +do + echo "Running test: $target" + if flutter drive \ + --driver=test_driver/integration_test.dart \ + --target="$target"; then + echo "✅ Test passed: $target" + passed_tests+=("$target") + else + echo "❌ Test failed: $target" + failed_tests+=("$target") + fi +done + +# Provide a summary of test results +echo -e "\n===== Test Summary =====" +if [ ${#passed_tests[@]} -gt 0 ]; then + echo "✅ Passed Tests:" + for test in "${passed_tests[@]}"; do + echo " - $test" + done +fi + +if [ ${#failed_tests[@]} -gt 0 ]; then + echo -e "\n❌ Failed Tests:" + for test in "${failed_tests[@]}"; do + echo " - $test" + done + # Exit with a non-zero status to indicate failure + exit 1 +else + echo -e "\n🎉 All tests passed successfully!" +fi diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index fac760516..ac00bb161 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -84,6 +84,7 @@ class WalletKeysPage extends BasePage { child: Observer( builder: (_) { return ListView.separated( + key: ValueKey('wallet_keys_page_credentials_list_view_key'), separatorBuilder: (context, index) => Container( height: 1, padding: EdgeInsets.only(left: 24), diff --git a/lib/src/widgets/search_bar_widget.dart b/lib/src/widgets/search_bar_widget.dart index e67c793cc..34ebe8560 100644 --- a/lib/src/widgets/search_bar_widget.dart +++ b/lib/src/widgets/search_bar_widget.dart @@ -17,6 +17,7 @@ class SearchBarWidget extends StatelessWidget { @override Widget build(BuildContext context) { return TextFormField( + key: ValueKey('search_bar_widget_key'), controller: searchController, style: TextStyle(color: Theme.of(context).extension()!.searchHintColor), decoration: InputDecoration( From 9a60b0146f08a0f112b0406bafbbbb58b069e111 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 14 Dec 2024 01:27:46 +0200 Subject: [PATCH 20/26] add transaction success info page (#1878) --- lib/di.dart | 4 + lib/router.dart | 5 + lib/routes.dart | 1 + lib/src/screens/send/send_page.dart | 148 +++++++----------- .../send/transaction_success_info_page.dart | 32 ++++ 5 files changed, 100 insertions(+), 90 deletions(-) create mode 100644 lib/src/screens/send/transaction_success_info_page.dart diff --git a/lib/di.dart b/lib/di.dart index 6531c411f..693df0ed3 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -39,6 +39,7 @@ import 'package:cake_wallet/entities/wallet_manager.dart'; import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart'; import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart'; import 'package:cake_wallet/src/screens/receive/address_list_page.dart'; +import 'package:cake_wallet/src/screens/send/transaction_success_info_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart'; import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart'; @@ -1175,6 +1176,9 @@ Future setup({ getIt.registerFactoryParam( (seedPhraseLength, _) => PreSeedPage(seedPhraseLength)); + getIt.registerFactoryParam( + (content, _) => TransactionSuccessPage(content: content)); + getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( tradeForDetails: trade, diff --git a/lib/router.dart b/lib/router.dart index a64369b32..faba5fd52 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -69,6 +69,7 @@ import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/send/send_page.dart'; import 'package:cake_wallet/src/screens/send/send_template_page.dart'; +import 'package:cake_wallet/src/screens/send/transaction_success_info_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; @@ -585,6 +586,10 @@ Route createRoute(RouteSettings settings) { return MaterialPageRoute( builder: (_) => getIt.get(param1: settings.arguments as int)); + case Routes.transactionSuccessPage: + return MaterialPageRoute( + builder: (_) => getIt.get(param1: settings.arguments as String)); + case Routes.backup: return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index bea118ae0..c8eb63c26 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -53,6 +53,7 @@ class Routes { static const restoreWalletType = '/restore_wallet_type'; static const restoreWallet = '/restore_wallet'; static const preSeedPage = '/pre_seed_page'; + static const transactionSuccessPage = '/transaction_success_info_page'; static const backup = '/backup'; static const editBackupPassword = '/edit_backup_passowrd'; static const restoreFromBackup = '/restore_from_backup'; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 4b1227751..ddf2d7c89 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -500,95 +500,6 @@ class SendPage extends BasePage { actionRightButton: () async { Navigator.of(_dialogContext).pop(); sendViewModel.commitTransaction(context); - await showPopUp( - context: context, - builder: (BuildContext _dialogContext) { - return Observer(builder: (_) { - final state = sendViewModel.state; - - if (state is FailureState) { - Navigator.of(_dialogContext).pop(); - } - - if (state is TransactionCommitted) { - newContactAddress = - newContactAddress ?? sendViewModel.newContactAddress(); - - if (sendViewModel.coinTypeToSpendFrom != UnspentCoinType.any) { - newContactAddress = null; - } - - final successMessage = S.of(_dialogContext).send_success( - sendViewModel.selectedCryptoCurrency.toString()); - - final waitMessage = sendViewModel.walletType == WalletType.solana - ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' - : ''; - - final newContactMessage = newContactAddress != null && sendViewModel.showAddressBookPopup - ? '\n${S.of(_dialogContext).add_contact_to_address_book}' - : ''; - - String alertContent = - "$successMessage$waitMessage$newContactMessage"; - - if (newContactMessage.isNotEmpty) { - return AlertWithTwoActions( - alertDialogKey: ValueKey('send_page_sent_dialog_key'), - alertTitle: '', - alertContent: alertContent, - rightButtonText: S.of(_dialogContext).add_contact, - leftButtonText: S.of(_dialogContext).ignor, - alertLeftActionButtonKey: - ValueKey('send_page_sent_dialog_ignore_button_key'), - alertRightActionButtonKey: ValueKey( - 'send_page_sent_dialog_add_contact_button_key'), - actionRightButton: () { - Navigator.of(_dialogContext).pop(); - RequestReviewHandler.requestReview(); - Navigator.of(context).pushNamed( - Routes.addressBookAddContact, - arguments: newContactAddress); - newContactAddress = null; - }, - actionLeftButton: () { - Navigator.of(_dialogContext).pop(); - RequestReviewHandler.requestReview(); - newContactAddress = null; - }); - } else { - if (initialPaymentRequest?.callbackMessage?.isNotEmpty ?? - false) { - alertContent = initialPaymentRequest!.callbackMessage!; - } - return AlertWithOneAction( - alertTitle: '', - alertContent: alertContent, - buttonText: S.of(_dialogContext).ok, - buttonAction: () { - Navigator.of(_dialogContext).pop(); - RequestReviewHandler.requestReview(); - }); - } - } - - return Offstage(); - }); - }); - if (state is TransactionCommitted) { - if (initialPaymentRequest?.callbackUrl?.isNotEmpty ?? false) { - // wait a second so it's not as jarring: - await Future.delayed(Duration(seconds: 1)); - try { - launchUrl( - Uri.parse(initialPaymentRequest!.callbackUrl!), - mode: LaunchMode.externalApplication, - ); - } catch (e) { - printV(e); - } - } - } }, actionLeftButton: () => Navigator.of(_dialogContext).pop()); }); @@ -597,7 +508,64 @@ class SendPage extends BasePage { } if (state is TransactionCommitted) { - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) async { + + final successMessage = S.of(context).send_success( + sendViewModel.selectedCryptoCurrency.toString()); + + final waitMessage = sendViewModel.walletType == WalletType.solana + ? '. ${S.of(context).waitFewSecondForTxUpdate}' + : ''; + + String alertContent = "$successMessage$waitMessage"; + + await Navigator.of(context).pushNamed( + Routes.transactionSuccessPage, + arguments: alertContent + ); + + newContactAddress = newContactAddress ?? sendViewModel.newContactAddress(); + if (sendViewModel.coinTypeToSpendFrom != UnspentCoinType.any) newContactAddress = null; + + if (newContactAddress != null && sendViewModel.showAddressBookPopup) { + await showPopUp( + context: context, + builder: (BuildContext _dialogContext) => AlertWithTwoActions( + alertDialogKey: ValueKey('send_page_sent_dialog_key'), + alertTitle: '', + alertContent: S.of(_dialogContext).add_contact_to_address_book, + rightButtonText: S.of(_dialogContext).add_contact, + leftButtonText: S.of(_dialogContext).ignor, + alertLeftActionButtonKey: ValueKey('send_page_sent_dialog_ignore_button_key'), + alertRightActionButtonKey: + ValueKey('send_page_sent_dialog_add_contact_button_key'), + actionRightButton: () { + Navigator.of(_dialogContext).pop(); + RequestReviewHandler.requestReview(); + Navigator.of(context) + .pushNamed(Routes.addressBookAddContact, arguments: newContactAddress); + newContactAddress = null; + }, + actionLeftButton: () { + Navigator.of(_dialogContext).pop(); + RequestReviewHandler.requestReview(); + newContactAddress = null; + })); + } + + if (initialPaymentRequest?.callbackUrl?.isNotEmpty ?? false) { + // wait a second so it's not as jarring: + await Future.delayed(Duration(seconds: 1)); + try { + launchUrl( + Uri.parse(initialPaymentRequest!.callbackUrl!), + mode: LaunchMode.externalApplication, + ); + } catch (e) { + printV(e); + } + } + sendViewModel.clearOutputs(); }); } diff --git a/lib/src/screens/send/transaction_success_info_page.dart b/lib/src/screens/send/transaction_success_info_page.dart new file mode 100644 index 000000000..628cc0393 --- /dev/null +++ b/lib/src/screens/send/transaction_success_info_page.dart @@ -0,0 +1,32 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/Info_page.dart'; +import 'package:flutter/cupertino.dart'; + +class TransactionSuccessPage extends InfoPage { + TransactionSuccessPage({required this.content}) + : super( + imageLightPath: 'assets/images/birthday_cake.png', + imageDarkPath: 'assets/images/birthday_cake.png', + ); + + final String content; + + @override + bool get onWillPop => false; + + @override + String get pageTitle => 'Transaction Sent Successfully'; + + @override + String get pageDescription => content; + + @override + String get buttonText => S.current.ok; + + @override + Key? get buttonKey => ValueKey('transaction_success_info_page_button_key'); + + @override + void Function(BuildContext) get onPressed => + (BuildContext context) => Navigator.of(context).pop(); +} From c620d7f48620ca63a6745dc61c000b49d401ed97 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Sat, 14 Dec 2024 00:31:10 +0100 Subject: [PATCH 21/26] CW-829 Solana Enhancements (#1858) * feat: Solana enhancements with rent handling for accounts * fix: Add exception classes with handled error messages to ensure proper error handling process --------- Co-authored-by: Omar Hatem --- cw_solana/lib/solana_client.dart | 53 +++++++++++++++++++++--- cw_solana/lib/solana_exceptions.dart | 17 ++++++++ cw_solana/lib/solana_wallet.dart | 3 ++ lib/view_model/send/send_view_model.dart | 37 +++++++++++------ res/values/strings_ar.arb | 4 ++ res/values/strings_bg.arb | 4 ++ res/values/strings_cs.arb | 4 ++ res/values/strings_de.arb | 6 ++- res/values/strings_en.arb | 4 ++ res/values/strings_es.arb | 4 ++ res/values/strings_fr.arb | 4 ++ res/values/strings_ha.arb | 4 ++ res/values/strings_hi.arb | 4 ++ res/values/strings_hr.arb | 4 ++ res/values/strings_hy.arb | 4 ++ res/values/strings_id.arb | 4 ++ res/values/strings_it.arb | 4 ++ res/values/strings_ja.arb | 4 ++ res/values/strings_ko.arb | 4 ++ res/values/strings_my.arb | 4 ++ res/values/strings_nl.arb | 4 ++ res/values/strings_pl.arb | 4 ++ res/values/strings_pt.arb | 4 ++ res/values/strings_ru.arb | 4 ++ res/values/strings_th.arb | 4 ++ res/values/strings_tl.arb | 4 ++ res/values/strings_tr.arb | 4 ++ res/values/strings_uk.arb | 4 ++ res/values/strings_ur.arb | 4 ++ res/values/strings_vi.arb | 4 ++ res/values/strings_yo.arb | 4 ++ res/values/strings_zh.arb | 4 ++ 32 files changed, 206 insertions(+), 18 deletions(-) diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index 175d13195..95376c563 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -1,12 +1,13 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:math'; +import 'dart:math' as math; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_solana/pending_solana_transaction.dart'; import 'package:cw_solana/solana_balance.dart'; +import 'package:cw_solana/solana_exceptions.dart'; import 'package:cw_solana/solana_transaction_model.dart'; import 'package:http/http.dart' as http; import 'package:solana/dto.dart'; @@ -180,7 +181,7 @@ class SolanaWalletClient { bool isOutgoingTx = transfer.source == publicKey.toBase58(); double amount = (double.tryParse(transfer.amount) ?? 0.0) / - pow(10, splTokenDecimal ?? 9); + math.pow(10, splTokenDecimal ?? 9); transactions.add( SolanaTransactionModel( @@ -276,6 +277,7 @@ class SolanaWalletClient { required String destinationAddress, required Ed25519HDKeyPair ownerKeypair, required bool isSendAll, + required double solBalance, String? tokenMint, List references = const [], }) async { @@ -290,6 +292,7 @@ class SolanaWalletClient { ownerKeypair: ownerKeypair, commitment: commitment, isSendAll: isSendAll, + solBalance: solBalance, ); return pendingNativeTokenTransaction; } else { @@ -301,6 +304,7 @@ class SolanaWalletClient { destinationAddress: destinationAddress, ownerKeypair: ownerKeypair, commitment: commitment, + solBalance: solBalance, ); return pendingSPLTokenTransaction; } @@ -353,6 +357,23 @@ class SolanaWalletClient { return fee; } + Future hasSufficientFundsLeftForRent({ + required double inputAmount, + required double solBalance, + required double fee, + }) async { + final rent = + await _client!.getMinimumBalanceForMintRentExemption(commitment: Commitment.confirmed); + + final rentInSol = (rent / lamportsPerSol).toDouble(); + + final remnant = solBalance - (inputAmount + fee); + + if (remnant > rentInSol) return true; + + return false; + } + Future _signNativeTokenTransaction({ required String tokenTitle, required int tokenDecimals, @@ -361,6 +382,7 @@ class SolanaWalletClient { required Ed25519HDKeyPair ownerKeypair, required Commitment commitment, required bool isSendAll, + required double solBalance, }) async { // Convert SOL to lamport int lamports = (inputAmount * lamportsPerSol).toInt(); @@ -378,6 +400,16 @@ class SolanaWalletClient { commitment, ); + bool hasSufficientFundsLeft = await hasSufficientFundsLeftForRent( + inputAmount: inputAmount, + fee: fee, + solBalance: solBalance, + ); + + if (!hasSufficientFundsLeft) { + throw SolanaSignNativeTokenTransactionRentException(); + } + SignedTx signedTx; if (isSendAll) { final feeInLamports = (fee * lamportsPerSol).toInt(); @@ -425,6 +457,7 @@ class SolanaWalletClient { required String destinationAddress, required Ed25519HDKeyPair ownerKeypair, required Commitment commitment, + required double solBalance, }) async { final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress); final mint = Ed25519HDPublicKey.fromBase58(tokenMint); @@ -447,7 +480,7 @@ class SolanaWalletClient { // Throw an appropriate exception if the sender has no associated // token account if (associatedSenderAccount == null) { - throw NoAssociatedTokenAccountException(ownerKeypair.address, mint.toBase58()); + throw SolanaNoAssociatedTokenAccountException(ownerKeypair.address, mint.toBase58()); } try { @@ -457,11 +490,11 @@ class SolanaWalletClient { funder: ownerKeypair, ); } catch (e) { - throw Exception('Insufficient SOL balance to complete this transaction: ${e.toString()}'); + throw SolanaCreateAssociatedTokenAccountException(e.toString()); } // Input by the user - final amount = (inputAmount * pow(10, tokenDecimals)).toInt(); + final amount = (inputAmount * math.pow(10, tokenDecimals)).toInt(); final instruction = TokenInstruction.transfer( source: Ed25519HDPublicKey.fromBase58(associatedSenderAccount.pubkey), @@ -483,6 +516,16 @@ class SolanaWalletClient { commitment, ); + bool hasSufficientFundsLeft = await hasSufficientFundsLeftForRent( + inputAmount: inputAmount, + fee: fee, + solBalance: solBalance, + ); + + if (!hasSufficientFundsLeft) { + throw SolanaSignSPLTokenTransactionRentException(); + } + final signedTx = await _signTransactionInternal( message: message, signers: signers, diff --git a/cw_solana/lib/solana_exceptions.dart b/cw_solana/lib/solana_exceptions.dart index 7409b0500..888c95068 100644 --- a/cw_solana/lib/solana_exceptions.dart +++ b/cw_solana/lib/solana_exceptions.dart @@ -19,3 +19,20 @@ class SolanaTransactionWrongBalanceException implements Exception { @override String toString() => exceptionMessage; } + +class SolanaSignNativeTokenTransactionRentException implements Exception {} + +class SolanaCreateAssociatedTokenAccountException implements Exception { + final String exceptionMessage; + + SolanaCreateAssociatedTokenAccountException(this.exceptionMessage); +} + +class SolanaSignSPLTokenTransactionRentException implements Exception {} + +class SolanaNoAssociatedTokenAccountException implements Exception { + const SolanaNoAssociatedTokenAccountException(this.account, this.mint); + + final String account; + final String mint; +} diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index c884d8e82..33a2e7df4 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -228,6 +228,8 @@ abstract class SolanaWalletBase final walletBalanceForCurrency = balance[transactionCurrency]!.balance; + final solBalance = balance[CryptoCurrency.sol]!.balance; + double totalAmount = 0.0; bool isSendAll = false; @@ -279,6 +281,7 @@ abstract class SolanaWalletBase ? solCredentials.outputs.first.extractedAddress! : solCredentials.outputs.first.address, isSendAll: isSendAll, + solBalance: solBalance, ); return pendingSolanaTransaction; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index dc3b2701d..40f877fef 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/evm_transaction_error_fees_handler.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; @@ -14,7 +13,6 @@ import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/solana/solana.dart'; -import 'package:cake_wallet/src/screens/ur/animated_ur_page.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; @@ -29,6 +27,7 @@ import 'package:cw_core/unspent_coin_type.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; import 'package:cw_core/utils/print_verbose.dart'; +import 'package:cw_solana/solana_exceptions.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -427,7 +426,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor // // state = FailureState(errorMsg); // } else { - state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); // } } return null; @@ -487,10 +486,11 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor try { state = TransactionCommitting(); - + if (pendingTransaction!.shouldCommitUR()) { final urstr = await pendingTransaction!.commitUR(); - final result = await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: urstr); + final result = + await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: urstr); if (result == null) { state = FailureState("Canceled by user"); return; @@ -507,12 +507,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor final descriptionKey = '${pendingTransaction!.id}_${wallet.walletAddresses.primaryAddress}'; _settingsStore.shouldSaveRecipientAddress ? await transactionDescriptionBox.add(TransactionDescription( - id: descriptionKey, - recipientAddress: address, - transactionNote: note)) - : await transactionDescriptionBox.add(TransactionDescription( - id: descriptionKey, - transactionNote: note)); + id: descriptionKey, recipientAddress: address, transactionNote: note)) + : await transactionDescriptionBox + .add(TransactionDescription(id: descriptionKey, transactionNote: note)); } state = TransactionCommitted(); @@ -674,10 +671,26 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor lamportsNeeded != null ? ((lamportsNeeded + 5000) / lamportsPerSol) : 0.0; return S.current.insufficient_lamports(solValueNeeded.toString()); } else { - printV("No match found."); return S.current.insufficient_lamport_for_tx; } } + + if (error is SolanaSignNativeTokenTransactionRentException) { + return S.current.solana_sign_native_transaction_rent_exception; + } + + if (error is SolanaCreateAssociatedTokenAccountException) { + return S.current.solana_create_associated_token_account_exception; + } + + if (error is SolanaSignSPLTokenTransactionRentException) { + return S.current.solana_sign_spl_token_transaction_rent_exception; + } + + if (error is SolanaNoAssociatedTokenAccountException) { + return S.current.solana_no_associated_token_account_exception; + } + if (errorMessage.contains('insufficient funds for rent')) { return S.current.insufficientFundsForRentError; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index bd7fa47d7..a57a4cd1f 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "إعدادات المدفوعات الصامتة", "single_seed_wallets_group": "محافظ بذرة واحدة", "slidable": "قابل للانزلاق", + "solana_create_associated_token_account_exception": "خطأ في إنشاء حساب رمز المرتبط بعنوان المستلم.", + "solana_no_associated_token_account_exception": "لا يوجد حساب مميز مرتبط بهذا العنوان.", + "solana_sign_native_transaction_rent_exception": "لا يمكن إكمال المعاملة. غادر SOL غير كاف للإيجار بعد المعاملة. يرجى أن تصل إلى رصيد SOL أو تقليل كمية SOL التي ترسلها.", + "solana_sign_spl_token_transaction_rent_exception": "لا يمكن إكمال المعاملة. غادر SOL غير كاف للإيجار بعد المعاملة. يرجى أن تصل إلى توازن سولك.", "sort_by": "ترتيب حسب", "spend_key_private": "مفتاح الإنفاق (خاص)", "spend_key_public": "مفتاح الإنفاق (عام)", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index bff37e95c..2aca0f08e 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Настройки за безшумни плащания", "single_seed_wallets_group": "Портфейли с единични семена", "slidable": "Плъзгащ се", + "solana_create_associated_token_account_exception": "Грешка Създаване на свързана сметка за жетони за адреса на получател.", + "solana_no_associated_token_account_exception": "Няма свързана сметка за този адрес.", + "solana_sign_native_transaction_rent_exception": "Транзакцията не може да бъде завършена. Недостатъчен сол оставен под наем след транзакция. Любезно допълнете баланса си на SOL или намалете количеството SOL, което изпращате.", + "solana_sign_spl_token_transaction_rent_exception": "Транзакцията не може да бъде завършена. Недостатъчен сол оставен под наем след транзакция. Любезно допълнете баланса си на SOL.", "sort_by": "Сортирай по", "spend_key_private": "Spend key (таен)", "spend_key_public": "Spend key (публичен)", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index d8025678f..7ce5538ae 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Nastavení tichých plateb", "single_seed_wallets_group": "Jednorázové peněženky", "slidable": "Posuvné", + "solana_create_associated_token_account_exception": "Vytvoření chyby přidruženého účtu tokenů pro adresu příjmu.", + "solana_no_associated_token_account_exception": "Pro tuto adresu není přidružen žádný přidružený token.", + "solana_sign_native_transaction_rent_exception": "Transakce nelze dokončit. Po transakci nedostatek Sol odešel k pronájmu. Laskavě doplňte rovnováhu SOL nebo snižte množství SOL, které odesíláte.", + "solana_sign_spl_token_transaction_rent_exception": "Transakce nelze dokončit. Po transakci nedostatek Sol odešel k pronájmu. Laskavě doplňte rovnováhu SOL.", "sort_by": "Seřazeno podle", "spend_key_private": "Klíč pro platby (soukromý)", "spend_key_public": "Klíč pro platby (veřejný)", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index b3aad50b0..bc06b4a53 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -502,8 +502,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": "Weitere Informationen finden Sie in den Dokumenten unten.", "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_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", @@ -742,6 +742,10 @@ "silent_payments_settings": "Einstellungen für stille Zahlungen", "single_seed_wallets_group": "Einzelne Wallets", "slidable": "Verschiebbar", + "solana_create_associated_token_account_exception": "Fehler beim Erstellen des zugehörigen Token -Kontos für die Empfängeradresse.", + "solana_no_associated_token_account_exception": "Für diese Adresse ist kein Token -Konto zugeordnet.", + "solana_sign_native_transaction_rent_exception": "Transaktion kann nicht abgeschlossen werden. Unzureichende Sol ließen nach der Transaktion zur Miete gelassen. Bitte geben Sie Ihre SOL -Balance auf oder reduzieren Sie die Menge an SOL, die Sie senden.", + "solana_sign_spl_token_transaction_rent_exception": "Transaktion kann nicht abgeschlossen werden. Unzureichende Sol ließen nach der Transaktion zur Miete gelassen. Bitte geben Sie Ihre SOL -Balance auf.", "sort_by": "Sortiere nach", "spend_key_private": "Spend Key (geheim)", "spend_key_public": "Spend Key (öffentlich)", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index bd483adb1..26771edf1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Silent Payments settings", "single_seed_wallets_group": "Single Seed Wallets", "slidable": "Slidable", + "solana_create_associated_token_account_exception": "Error creating associated token account for receipient address.", + "solana_no_associated_token_account_exception": "There is no associated token account for this address.", + "solana_sign_native_transaction_rent_exception": "Transaction cannot be completed. Insufficient SOL left for rent after transaction. Kindly top up your SOL balance or reduce the amount of SOL you are sending.", + "solana_sign_spl_token_transaction_rent_exception": "Transaction cannot be completed. Insufficient SOL left for rent after transaction. Kindly top up your SOL balance.", "sort_by": "Sort by", "spend_key_private": "Spend key (private)", "spend_key_public": "Spend key (public)", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 45b1d279b..6f2bd60b9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "Configuración de pagos silenciosos", "single_seed_wallets_group": "Billeteras de semillas individuales", "slidable": "deslizable", + "solana_create_associated_token_account_exception": "Error a crear una cuenta de token asociada para la dirección recibida.", + "solana_no_associated_token_account_exception": "No hay una cuenta de token asociada para esta dirección.", + "solana_sign_native_transaction_rent_exception": "La transacción no se puede completar. Sol insuficiente que queda en alquiler después de la transacción. Por favor, supere su saldo de sol o reduzca la cantidad de sol que está enviando.", + "solana_sign_spl_token_transaction_rent_exception": "La transacción no se puede completar. Sol insuficiente que queda en alquiler después de la transacción. Por favor, supere su balance de sol.", "sort_by": "Ordenar por", "spend_key_private": "Llave de gasto (privada)", "spend_key_public": "Llave de gasto (pública)", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index a359e3630..ff5c17cde 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Paramètres de paiement silencieux", "single_seed_wallets_group": "Portefeuilles de semences simples", "slidable": "Glissable", + "solana_create_associated_token_account_exception": "Création d'erreur Création de jetons associés pour l'adresse détenue.", + "solana_no_associated_token_account_exception": "Il n'y a pas de compte de jeton associé pour cette adresse.", + "solana_sign_native_transaction_rent_exception": "La transaction ne peut pas être terminée. Sol insuffisant laissé à la location après la transaction. Veuillez compléter votre solde SOL ou réduire la quantité de Sol que vous envoyez.", + "solana_sign_spl_token_transaction_rent_exception": "La transaction ne peut pas être terminée. Sol insuffisant laissé à la location après la transaction. Veuillez compléter votre solde de Sol.", "sort_by": "Trier par", "spend_key_private": "Clef de dépense (spend key) (privée)", "spend_key_public": "Clef de dépense (spend key) (publique)", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 48ede7b7c..a13ed2af4 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -743,6 +743,10 @@ "silent_payments_settings": "Saitunan Silent", "single_seed_wallets_group": "Guaro", "slidable": "Mai iya zamewa", + "solana_create_associated_token_account_exception": "Kuskuren ƙirƙirar asusun Asusun da aka danganta don Adireshin karɓar karɓa.", + "solana_no_associated_token_account_exception": "Babu wani haɗin yanar gizo mai alaƙa don wannan adireshin.", + "solana_sign_native_transaction_rent_exception": "Ma'amala ba za a iya kammala ba. Rashin cancanta na Sol ya bar haya bayan ma'amala. Da kyau a saman ma'auni na Solku ko rage adadin Sol da kuke aikawa.", + "solana_sign_spl_token_transaction_rent_exception": "Ma'amala ba za a iya kammala ba. Rashin cancanta na Sol ya bar haya bayan ma'amala. Da kyau sama da ma'auni na Sol.", "sort_by": "Kasa", "spend_key_private": "makullin biya (maɓallin kalmar sirri)", "spend_key_public": "makullin biya (maɓallin jama'a)", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c2feea939..b73414dee 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -743,6 +743,10 @@ "silent_payments_settings": "मूक भुगतान सेटिंग्स", "single_seed_wallets_group": "एकल बीज बटुए", "slidable": "फिसलने लायक", + "solana_create_associated_token_account_exception": "रसीद पते के लिए संबद्ध टोकन खाता बनाने में त्रुटि।", + "solana_no_associated_token_account_exception": "इस पते के लिए कोई जुड़ा हुआ टोकन खाता नहीं है।", + "solana_sign_native_transaction_rent_exception": "लेन -देन पूरा नहीं किया जा सकता है। अपर्याप्त सोल लेनदेन के बाद किराए के लिए छोड़ दिया। कृपया अपने सोल बैलेंस को टॉप करें या आपके द्वारा भेजे जा रहे सोल की मात्रा को कम करें।", + "solana_sign_spl_token_transaction_rent_exception": "लेन -देन पूरा नहीं किया जा सकता है। अपर्याप्त सोल लेनदेन के बाद किराए के लिए छोड़ दिया। कृपया अपने सोल बैलेंस को ऊपर रखें।", "sort_by": "इसके अनुसार क्रमबद्ध करें", "spend_key_private": "खर्च करना (निजी)", "spend_key_public": "खर्च करना (जनता)", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c82e2a5f8..87d66122c 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Postavke tihih plaćanja", "single_seed_wallets_group": "Jednostruki novčanici", "slidable": "Klizna", + "solana_create_associated_token_account_exception": "Pogreška u stvaranju povezanog token računa za adresu primanja.", + "solana_no_associated_token_account_exception": "Za ovu adresu ne postoji povezani token račun.", + "solana_sign_native_transaction_rent_exception": "Transakcija se ne može završiti. Nedovoljno sol ostao je za najam nakon transakcije. Ljubazno nadopunite svoj SOL saldo ili smanjite količinu SOL -a koju šaljete.", + "solana_sign_spl_token_transaction_rent_exception": "Transakcija se ne može završiti. Nedovoljno sol ostao je za najam nakon transakcije. Ljubazno nadopunite svoju sol ravnotežu.", "sort_by": "Poredaj po", "spend_key_private": "Spend key (privatni)", "spend_key_public": "Spend key (javni)", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index d83bc2a3a..dfbd94cdc 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Լուռ Վճարումներ Կարգավորումներ", "single_seed_wallets_group": "Մեկ սերմերի դրամապանակներ", "slidable": "Սահելի", + "solana_create_associated_token_account_exception": "Recesient Advent- ի համար հարակից նշանների հաշիվ ստեղծելու սխալ:", + "solana_no_associated_token_account_exception": "Այս հասցեի համար կապված նշանների հաշիվ չկա:", + "solana_sign_native_transaction_rent_exception": "Գործարքը հնարավոր չէ լրացնել: Անբավարար սոլը գործարքից հետո վարձով է մնացել: Սիրով վերացրեք ձեր SOL հավասարակշռությունը կամ նվազեցրեք ձեր ուղարկած սոլի քանակը:", + "solana_sign_spl_token_transaction_rent_exception": "Գործարքը հնարավոր չէ լրացնել: Անբավարար սոլը գործարքից հետո վարձով է մնացել: Սիրով վերացրեք ձեր SOL հավասարակշռությունը:", "sort_by": "Դասավորել ըստ", "spend_key_private": "Վճարման բանալի (գախտնի)", "spend_key_public": "Վճարման բանալի (հանրային)", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ca140e63e..b3ef0c67b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -744,6 +744,10 @@ "silent_payments_settings": "Pengaturan pembayaran diam", "single_seed_wallets_group": "Dompet biji tunggal", "slidable": "Dapat digeser", + "solana_create_associated_token_account_exception": "Kesalahan Membuat Akun Token Terkait untuk Alamat Penerima.", + "solana_no_associated_token_account_exception": "Tidak ada akun token terkait untuk alamat ini.", + "solana_sign_native_transaction_rent_exception": "Transaksi tidak dapat diselesaikan. SOL yang tidak mencukupi pergi untuk disewa setelah transaksi. Mohon tambah saldo SOL Anda atau kurangi jumlah SOL yang Anda kirim.", + "solana_sign_spl_token_transaction_rent_exception": "Transaksi tidak dapat diselesaikan. SOL yang tidak mencukupi pergi untuk disewa setelah transaksi. Mohon tambah saldo SOL Anda.", "sort_by": "Sortir dengan", "spend_key_private": "Kunci pengeluaran (privat)", "spend_key_public": "Kunci pengeluaran (publik)", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index f5dbc1c5a..2cf07fdd7 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -743,6 +743,10 @@ "silent_payments_settings": "Impostazioni di pagamenti silenziosi", "single_seed_wallets_group": "Portafogli singoli", "slidable": "Scorrevole", + "solana_create_associated_token_account_exception": "Errore Creazione di account token associato per l'indirizzo dei ricevimenti.", + "solana_no_associated_token_account_exception": "Non esiste un account token associato per questo indirizzo.", + "solana_sign_native_transaction_rent_exception": "La transazione non può essere completata. Sol insufficiente lasciato in affitto dopo la transazione. Si prega di ricaricare il saldo SOL o ridurre la quantità di sol che stai inviando.", + "solana_sign_spl_token_transaction_rent_exception": "La transazione non può essere completata. Sol insufficiente lasciato in affitto dopo la transazione. Si prega di ricaricare il tuo equilibrio sol.", "sort_by": "Ordina per", "spend_key_private": "Chiave di spesa (privata)", "spend_key_public": "Chiave di spesa (pubblica)", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 182133e68..3edb9f88d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "サイレントペイメント設定", "single_seed_wallets_group": "シングルシードウォレット", "slidable": "スライド可能", + "solana_create_associated_token_account_exception": "関連するトークンの作成エラー受信アドレスのアカウント。", + "solana_no_associated_token_account_exception": "このアドレスに関連付けられたトークンアカウントはありません。", + "solana_sign_native_transaction_rent_exception": "トランザクションは完了できません。取引後にレンタルのために残された不十分なソル。ソルバランスを補充するか、送信するソルの量を減らしてください。", + "solana_sign_spl_token_transaction_rent_exception": "トランザクションは完了できません。取引後にレンタルのために残された不十分なソル。ソルバランスを補充してください。", "sort_by": "並び替え", "spend_key_private": "キーを使う (プライベート)", "spend_key_public": "キーを使う (パブリック)", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 747c316d6..6e5fb4a7b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "조용한 지불 설정", "single_seed_wallets_group": "단일 씨앗 지갑", "slidable": "슬라이딩 가능", + "solana_create_associated_token_account_exception": "오류 생성 관련 토큰 계정 수령자 주소에 대한 계정.", + "solana_no_associated_token_account_exception": "이 주소에는 관련 토큰 계정이 없습니다.", + "solana_sign_native_transaction_rent_exception": "거래는 완료 될 수 없습니다. 거래 후 SOL이 임대료로 남았습니다. SOL 밸런스를 친절하게 위로 올리거나 보내는 솔의 양을 줄입니다.", + "solana_sign_spl_token_transaction_rent_exception": "거래는 완료 될 수 없습니다. 거래 후 SOL이 임대료로 남았습니다. SOL 균형을 친절하게 위에 올리십시오.", "sort_by": "정렬 기준", "spend_key_private": "지출 키 (은밀한)", "spend_key_public": "지출 키 (공공의)", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 8fe87b34c..a7ada97ef 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "အသံတိတ်ငွေပေးချေမှုဆက်တင်များ", "single_seed_wallets_group": "တစ်ခုတည်းမျိုးစေ့ပိုက်ဆံအိတ်", "slidable": "လျှောချနိုင်သည်။", + "solana_create_associated_token_account_exception": "Encipient Token အကောင့်ကိုလက်ခံသည့်လိပ်စာအတွက်အကောင့်များဖန်တီးခြင်းအတွက်အမှားအယွင်းများဖန်တီးခြင်း။", + "solana_no_associated_token_account_exception": "ဒီလိပ်စာအတွက်မပေါင်းသင်းတဲ့လက်ခဏာသက်သေအကောင့်မရှိဘူး။", + "solana_sign_native_transaction_rent_exception": "ငွေပေးငွေယူကိုမပြီးစီးနိုင်ပါ။ ငွေပေးငွေယူပြီးနောက်ငှားရန် Sol မလုံလောက်ပါ။ ကြင်နာစွာသင်၏ SOR ချိန်ခွင်လျှာကိုငွေဖြည့်ပါသို့မဟုတ်သင်ပို့နေသည့်ပမာဏကိုလျှော့ချပါ။", + "solana_sign_spl_token_transaction_rent_exception": "ငွေပေးငွေယူကိုမပြီးစီးနိုင်ပါ။ ငွေပေးငွေယူပြီးနောက်ငှားရန် Sol မလုံလောက်ပါ။ ကြင်နာစွာသင်၏ s ကိုချိန်ခွင်လျှာကိုတက်ပါ။", "sort_by": "အလိုက်စဥ်သည်", "spend_key_private": "သော့သုံးရန် (သီးသန့်)", "spend_key_public": "သုံးစွဲရန်သော့ (အများပြည်သူ)", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ca7052b0e..ba20bb26a 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Stille betalingsinstellingen", "single_seed_wallets_group": "Enkele zaadportefeuilles", "slidable": "Verschuifbaar", + "solana_create_associated_token_account_exception": "Fout bij het maken van een geassocieerd tokenaccount voor ontvangingsadres.", + "solana_no_associated_token_account_exception": "Er is geen bijbehorende tokenaccount voor dit adres.", + "solana_sign_native_transaction_rent_exception": "Transactie kan niet worden voltooid. Onvoldoende Sol vertrok naar huur na transactie. Vul uw SOL -balans aan of verminder de hoeveelheid SOL die u verzendt.", + "solana_sign_spl_token_transaction_rent_exception": "Transactie kan niet worden voltooid. Onvoldoende Sol vertrok naar huur na transactie. Vul uw SOL -balans op.", "sort_by": "Sorteer op", "spend_key_private": "Sleutel uitgeven (privaat)", "spend_key_public": "Sleutel uitgeven (openbaar)", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index fad2bb026..d50def305 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Ustawienia o cichej płatności", "single_seed_wallets_group": "Pojedyncze portfele nasion", "slidable": "Przesuwne", + "solana_create_associated_token_account_exception": "Błąd tworzenia powiązanego konta tokena dla adresu wpływającego.", + "solana_no_associated_token_account_exception": "Nie ma powiązanego konta tokena dla tego adresu.", + "solana_sign_native_transaction_rent_exception": "Transakcji nie można zakończyć. Niewystarczający SOL w lewo do czynszu po transakcji. Uprzejmie uzupełnij saldo Sol lub zmniejsz ilość wysyłanej przez Ciebie rozwiązania.", + "solana_sign_spl_token_transaction_rent_exception": "Transakcji nie można zakończyć. Niewystarczający SOL w lewo do czynszu po transakcji. Uprzejmie uzupełnij saldo Sol.", "sort_by": "Sortuj według", "spend_key_private": "Klucz prywatny", "spend_key_public": "Klucz publiczny", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index c59afec65..7ff9fdc4e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -743,6 +743,10 @@ "silent_payments_settings": "Configurações de pagamentos silenciosos", "single_seed_wallets_group": "Carteiras de sementes únicas", "slidable": "Deslizável", + "solana_create_associated_token_account_exception": "Erro a criação de um token associado Conta do endereço de recebimento.", + "solana_no_associated_token_account_exception": "Não existe uma conta de token associada para este endereço.", + "solana_sign_native_transaction_rent_exception": "A transação não pode ser concluída. Sol insuficiente deixou para alugar após a transação. Por favor, complete seu saldo sol ou reduza a quantidade de sol que você está enviando.", + "solana_sign_spl_token_transaction_rent_exception": "A transação não pode ser concluída. Sol insuficiente deixou para alugar após a transação. Por favor, complete seu equilíbrio sol.", "sort_by": "Ordenar por", "spend_key_private": "Chave de gastos (privada)", "spend_key_public": "Chave de gastos (pública)", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 94b1c7010..b1d6c2461 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "Silent Payments Settings", "single_seed_wallets_group": "Одиночные кошельки", "slidable": "Скользящий", + "solana_create_associated_token_account_exception": "Ошибка создания ассоциированной учетной записи для адреса для адреса.", + "solana_no_associated_token_account_exception": "Для этого адреса нет связанной учетной записи токена.", + "solana_sign_native_transaction_rent_exception": "Сделка не может быть завершена. Недостаточный соль ушел в аренду после транзакции. Пожалуйста, поместите свой баланс Sol или уменьшите количество Sol, которое вы отправляете.", + "solana_sign_spl_token_transaction_rent_exception": "Сделка не может быть завершена. Недостаточный соль ушел в аренду после транзакции. Пожалуйста, пополните свой баланс Sol.", "sort_by": "Сортировать по", "spend_key_private": "Приватный ключ траты", "spend_key_public": "Публичный ключ траты", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f35187cd4..b5587073b 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "การตั้งค่าการชำระเงินแบบเงียบ", "single_seed_wallets_group": "กระเป๋าเงินเดียว", "slidable": "เลื่อนได้", + "solana_create_associated_token_account_exception": "ข้อผิดพลาดในการสร้างบัญชีโทเค็นที่เกี่ยวข้องสำหรับที่อยู่รับ", + "solana_no_associated_token_account_exception": "ไม่มีบัญชีโทเค็นที่เกี่ยวข้องสำหรับที่อยู่นี้", + "solana_sign_native_transaction_rent_exception": "การทำธุรกรรมไม่สามารถเสร็จสิ้นได้ SOL ไม่เพียงพอเหลือให้เช่าหลังการทำธุรกรรม กรุณาเติมยอดคงเหลือโซลของคุณหรือลดจำนวนโซลที่คุณกำลังส่ง", + "solana_sign_spl_token_transaction_rent_exception": "การทำธุรกรรมไม่สามารถเสร็จสิ้นได้ SOL ไม่เพียงพอเหลือให้เช่าหลังการทำธุรกรรม กรุณาเติมยอดสมดุลโซลของคุณ", "sort_by": "เรียงตาม", "spend_key_private": "คีย์จ่าย (ส่วนตัว)", "spend_key_public": "คีย์จ่าย (สาธารณะ)", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 290fcf4bf..774887859 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Mga setting ng tahimik na pagbabayad", "single_seed_wallets_group": "Solong mga pitaka ng binhi", "slidable": "Slidable", + "solana_create_associated_token_account_exception": "Error sa paglikha ng nauugnay na token account para sa resibo address.", + "solana_no_associated_token_account_exception": "Walang nauugnay na token account para sa address na ito.", + "solana_sign_native_transaction_rent_exception": "Hindi makumpleto ang transaksyon. Hindi sapat na SOL na naiwan para sa upa pagkatapos ng transaksyon. Mabuting itaas ang iyong balanse sa sol o bawasan ang dami ng sol na iyong ipinapadala.", + "solana_sign_spl_token_transaction_rent_exception": "Hindi makumpleto ang transaksyon. Hindi sapat na SOL na naiwan para sa upa pagkatapos ng transaksyon. Mabuting itaas ang iyong balanse sa sol.", "sort_by": "Pag-uri-uriin sa pamamagitan ng", "spend_key_private": "Spend key (private)", "spend_key_public": "Spend key (public)", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 912cd52e4..83d766347 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "Sessiz Ödeme Ayarları", "single_seed_wallets_group": "Tek tohum cüzdanları", "slidable": "kaydırılabilir", + "solana_create_associated_token_account_exception": "ALIPITIENT ADRESİ İÇİN BAŞLANGIÇ HESABI oluşturma Hata.", + "solana_no_associated_token_account_exception": "Bu adres için ilişkili belirteç hesabı yoktur.", + "solana_sign_native_transaction_rent_exception": "İşlem tamamlanamaz. Yetersiz Sol işlemden sonra kira için kaldı. Lütfen sol bakiyenizi doldurun veya gönderdiğiniz Sol miktarını azaltın.", + "solana_sign_spl_token_transaction_rent_exception": "İşlem tamamlanamaz. Yetersiz Sol işlemden sonra kira için kaldı. Lütfen sol bakiyenizi doldurun.", "sort_by": "Göre sırala", "spend_key_private": "Harcama anahtarı (özel)", "spend_key_public": "Harcama anahtarı (genel)", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index fd03f437e..fd69c6cbf 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "Налаштування мовчазних платежів", "single_seed_wallets_group": "Поодинокі насінні гаманці", "slidable": "Розсувний", + "solana_create_associated_token_account_exception": "Помилка створення пов’язаного облікового запису Token для адреси приймання.", + "solana_no_associated_token_account_exception": "Для цієї адреси немає пов’язаного облікового запису маркера.", + "solana_sign_native_transaction_rent_exception": "Транзакція не може бути завершена. Недостатня SOL залишила оренду після транзакції. Будь ласка, поповніть свій баланс SOL або зменшіть кількість SOL, який ви надсилаєте.", + "solana_sign_spl_token_transaction_rent_exception": "Транзакція не може бути завершена. Недостатня SOL залишила оренду після транзакції. Будь ласка, наповніть свій баланс SOL.", "sort_by": "Сортувати за", "spend_key_private": "Приватний ключ витрати", "spend_key_public": "Публічний ключ витрати", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 03140020a..e4e8d8aee 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -743,6 +743,10 @@ "silent_payments_settings": "خاموش ادائیگی کی ترتیبات", "single_seed_wallets_group": "سنگل بیج کے بٹوے", "slidable": "سلائیڈ ایبل", + "solana_create_associated_token_account_exception": "وصول کنندہ ایڈریس کے لئے وابستہ ٹوکن اکاؤنٹ بنانے میں غلطی۔", + "solana_no_associated_token_account_exception": "اس پتے کے لئے کوئی وابستہ ٹوکن اکاؤنٹ نہیں ہے۔", + "solana_sign_native_transaction_rent_exception": "لین دین مکمل نہیں کیا جاسکتا۔ ٹرانزیکشن کے بعد کرایہ کے لئے ناکافی SOL چھوڑ دیا گیا ہے۔ برائے مہربانی اپنے سول توازن کو اوپر کریں یا آپ بھیج رہے ہیں اس کی مقدار کو کم کریں۔", + "solana_sign_spl_token_transaction_rent_exception": "لین دین مکمل نہیں کیا جاسکتا۔ ٹرانزیکشن کے بعد کرایہ کے لئے ناکافی SOL چھوڑ دیا گیا ہے۔ برائے مہربانی اپنے سول توازن کو اوپر رکھیں۔", "sort_by": "ترتیب دیں", "spend_key_private": "خرچ کی کلید (نجی)", "spend_key_public": "خرچ کی کلید (عوامی)", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index e40edf458..f74078746 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -740,6 +740,10 @@ "silent_payments_settings": "Cài đặt thanh toán im lặng", "single_seed_wallets_group": "Ví hạt đơn", "slidable": "Có thể kéo", + "solana_create_associated_token_account_exception": "Lỗi Tạo tài khoản mã thông báo liên quan cho địa chỉ biên lai.", + "solana_no_associated_token_account_exception": "Không có tài khoản mã thông báo liên quan cho địa chỉ này.", + "solana_sign_native_transaction_rent_exception": "Giao dịch không thể được hoàn thành. Không đủ Sol còn lại cho thuê sau khi giao dịch. Vui lòng tăng số dư Sol của bạn hoặc giảm số lượng sol bạn đang gửi.", + "solana_sign_spl_token_transaction_rent_exception": "Giao dịch không thể được hoàn thành. Không đủ Sol còn lại cho thuê sau khi giao dịch. Vui lòng lên cân bằng sol của bạn.", "sort_by": "Sắp xếp theo", "spend_key_private": "Khóa chi tiêu (riêng tư)", "spend_key_public": "Khóa chi tiêu (công khai)", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 8b3cdc358..14f0e5cf6 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -742,6 +742,10 @@ "silent_payments_settings": "Awọn eto isanwo ti o dakẹ", "single_seed_wallets_group": "Awọn Wowei Awọn gige", "slidable": "Slidable", + "solana_create_associated_token_account_exception": "Aṣiṣe ṣiṣẹda akọọlẹ token ti o ni ibatan fun adirẹsi gbigba.", + "solana_no_associated_token_account_exception": "Ko si iroyin token ti o ni ibatan fun adirẹsi yii.", + "solana_sign_native_transaction_rent_exception": "Idunadura ko le pari. Solusi ti ko to ju fun iyalo lẹhin idunadura. Jowo oke iwọntunwọnsi rẹ tabi dinku iye sol ti o firanṣẹ.", + "solana_sign_spl_token_transaction_rent_exception": "Idunadura ko le pari. Solusi ti ko to ju fun iyalo lẹhin idunadura. Sanra si oke ni iwọntunwọnsi Sol rẹ.", "sort_by": "Sa pelu", "spend_key_private": "Kọ́kọ́rọ́ sísan (àdáni)", "spend_key_public": "Kọ́kọ́rọ́ sísan (kò àdáni)", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 63e92a67d..8d9828c6a 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -741,6 +741,10 @@ "silent_payments_settings": "无声付款设置", "single_seed_wallets_group": "单个种子钱包", "slidable": "可滑动", + "solana_create_associated_token_account_exception": "错误创建有关接收地址的关联令牌帐户。", + "solana_no_associated_token_account_exception": "该地址没有关联的令牌帐户。", + "solana_sign_native_transaction_rent_exception": "交易无法完成。交易后剩下的溶胶不足。请增强您的溶胶余额或减少您发送的SOL的量。", + "solana_sign_spl_token_transaction_rent_exception": "交易无法完成。交易后剩下的溶胶不足。请增强您的溶液余额。", "sort_by": "排序方式", "spend_key_private": "Spend 密钥 (私钥)", "spend_key_public": "Spend 密钥 (公钥)", From ae758756d8e2f870dd43f2740234c432770f2de5 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 14 Dec 2024 00:32:36 +0100 Subject: [PATCH 22/26] Ledger monero fix (#1834) * Fix sending for monero ledger * Ignore no tx keys found error * re-add Monero to Ledger enabled wallets * Fix No Element Exception on requireHardwareWalletConnection check * Fix Showing connection screen again * Maybe fix Race condition * fix namespace * Maybe fix Race condition and add missing pop * Minor fixes * Minor fixes * Fix minor localization * Fix minor localization * Add Text prompt if device is not showing after 10 seconds. --------- Co-authored-by: OmarHatem Co-authored-by: Czarek Nakamoto --- android/app/build.gradle | 2 +- .../lib/hardware/device_connection_type.dart | 2 +- cw_monero/lib/api/transaction_history.dart | 13 +++- cw_monero/lib/ledger.dart | 70 +++++++++++++++++- cw_monero/lib/monero_wallet_service.dart | 56 +++++++-------- .../on_authentication_state_change.dart | 25 ++++--- .../connect_device/connect_device_page.dart | 71 ++++++++++++++----- .../screens/restore/restore_options_page.dart | 5 +- lib/src/screens/send/send_page.dart | 5 +- .../screens/wallet_list/wallet_list_page.dart | 10 +-- lib/store/authentication_store.dart | 8 ++- .../hardware_wallet/ledger_view_model.dart | 47 +++++++++--- lib/view_model/wallet_creation_vm.dart | 3 +- res/values/strings_ar.arb | 2 + res/values/strings_bg.arb | 2 + res/values/strings_cs.arb | 2 + res/values/strings_de.arb | 4 +- res/values/strings_en.arb | 2 + res/values/strings_es.arb | 2 + res/values/strings_fr.arb | 2 + res/values/strings_ha.arb | 2 + res/values/strings_hi.arb | 2 + res/values/strings_hr.arb | 2 + res/values/strings_hy.arb | 2 + res/values/strings_id.arb | 2 + res/values/strings_it.arb | 2 + res/values/strings_ja.arb | 2 + res/values/strings_ko.arb | 4 +- res/values/strings_my.arb | 2 + res/values/strings_nl.arb | 2 + res/values/strings_pl.arb | 2 + res/values/strings_pt.arb | 2 + res/values/strings_ru.arb | 2 + res/values/strings_th.arb | 2 + res/values/strings_tl.arb | 2 + res/values/strings_tr.arb | 2 + res/values/strings_uk.arb | 2 + res/values/strings_ur.arb | 2 + res/values/strings_vi.arb | 2 + res/values/strings_yo.arb | 2 + res/values/strings_zh.arb | 2 + 41 files changed, 287 insertions(+), 90 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 238dc769d..b65c54108 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -99,4 +99,4 @@ configurations { implementation.exclude module:'proto-google-common-protos' implementation.exclude module:'protolite-well-known-types' implementation.exclude module:'protobuf-javalite' -} \ No newline at end of file +} diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart index 466d58e2a..76a501af1 100644 --- a/cw_core/lib/hardware/device_connection_type.dart +++ b/cw_core/lib/hardware/device_connection_type.dart @@ -7,7 +7,7 @@ enum DeviceConnectionType { static List supportedConnectionTypes(WalletType walletType, [bool isIOS = false]) { switch (walletType) { - // case WalletType.monero: + case WalletType.monero: case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index aa6cac18a..854ee01c3 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -200,9 +200,16 @@ String? commitTransactionFromPointerAddress({required int address, required bool commitTransaction(transactionPointer: monero.PendingTransaction.fromAddress(address), useUR: useUR); String? commitTransaction({required monero.PendingTransaction transactionPointer, required bool useUR}) { + final transactionPointerAddress = transactionPointer.address; final txCommit = useUR - ? monero.PendingTransaction_commitUR(transactionPointer, 120) - : monero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false); + ? monero.PendingTransaction_commitUR(transactionPointer, 120) + : Isolate.run(() { + monero.PendingTransaction_commit( + Pointer.fromAddress(transactionPointerAddress), + filename: '', + overwrite: false, + ); + }); String? error = (() { final status = monero.PendingTransaction_status(transactionPointer.cast()); @@ -221,7 +228,7 @@ String? commitTransaction({required monero.PendingTransaction transactionPointer })(); } - if (error != null) { + if (error != null && error != "no tx keys found for this txid") { throw CreationTransactionException(message: error); } if (useUR) { diff --git a/cw_monero/lib/ledger.dart b/cw_monero/lib/ledger.dart index e7af9f390..b95c655a0 100644 --- a/cw_monero/lib/ledger.dart +++ b/cw_monero/lib/ledger.dart @@ -2,11 +2,12 @@ import 'dart:async'; import 'dart:ffi'; import 'dart:typed_data'; +import 'package:collection/collection.dart'; +import 'package:cw_core/utils/print_verbose.dart'; import 'package:ffi/ffi.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus_dart.dart'; import 'package:monero/monero.dart' as monero; -// import 'package:polyseed/polyseed.dart'; LedgerConnection? gLedger; @@ -28,9 +29,16 @@ void enableLedgerExchange(monero.wallet ptr, LedgerConnection connection) { ptr, emptyPointer.cast(), 0); malloc.free(emptyPointer); - // printV("> ${ledgerRequest.toHexString()}"); + _logLedgerCommand(ledgerRequest, false); final response = await exchange(connection, ledgerRequest); - // printV("< ${response.toHexString()}"); + _logLedgerCommand(response, true); + + if (ListEquality().equals(response, [0x55, 0x15])) { + await connection.disconnect(); + // // TODO: Show POPUP pls unlock your device + // await Future.delayed(Duration(seconds: 15)); + // response = await exchange(connection, ledgerRequest); + } final Pointer result = malloc(response.length); for (var i = 0; i < response.length; i++) { @@ -82,3 +90,59 @@ class ExchangeOperation extends LedgerRawOperation { @override Future> write(ByteDataWriter writer) async => [inputData]; } + +const _ledgerMoneroCommands = { + 0x00: "INS_NONE", + 0x02: "INS_RESET", + 0x20: "INS_GET_KEY", + 0x21: "INS_DISPLAY_ADDRESS", + 0x22: "INS_PUT_KEY", + 0x24: "INS_GET_CHACHA8_PREKEY", + 0x26: "INS_VERIFY_KEY", + 0x28: "INS_MANAGE_SEEDWORDS", + 0x30: "INS_SECRET_KEY_TO_PUBLIC_KEY", + 0x32: "INS_GEN_KEY_DERIVATION", + 0x34: "INS_DERIVATION_TO_SCALAR", + 0x36: "INS_DERIVE_PUBLIC_KEY", + 0x38: "INS_DERIVE_SECRET_KEY", + 0x3A: "INS_GEN_KEY_IMAGE", + 0x3B: "INS_DERIVE_VIEW_TAG", + 0x3C: "INS_SECRET_KEY_ADD", + 0x3E: "INS_SECRET_KEY_SUB", + 0x40: "INS_GENERATE_KEYPAIR", + 0x42: "INS_SECRET_SCAL_MUL_KEY", + 0x44: "INS_SECRET_SCAL_MUL_BASE", + 0x46: "INS_DERIVE_SUBADDRESS_PUBLIC_KEY", + 0x48: "INS_GET_SUBADDRESS", + 0x4A: "INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY", + 0x4C: "INS_GET_SUBADDRESS_SECRET_KEY", + 0x70: "INS_OPEN_TX", + 0x72: "INS_SET_SIGNATURE_MODE", + 0x74: "INS_GET_ADDITIONAL_KEY", + 0x76: "INS_STEALTH", + 0x77: "INS_GEN_COMMITMENT_MASK", + 0x78: "INS_BLIND", + 0x7A: "INS_UNBLIND", + 0x7B: "INS_GEN_TXOUT_KEYS", + 0x7D: "INS_PREFIX_HASH", + 0x7C: "INS_VALIDATE", + 0x7E: "INS_MLSAG", + 0x7F: "INS_CLSAG", + 0x80: "INS_CLOSE_TX", + 0xA0: "INS_GET_TX_PROOF", + 0xC0: "INS_GET_RESPONSE" +}; + +void _logLedgerCommand(Uint8List command, [bool isResponse = true]) { + String toHexString(Uint8List data) => + data.map((e) => e.toRadixString(16).padLeft(2, '0')).join(); + + + + if (isResponse) { + printV("< ${toHexString(command)}"); + } else { + printV( + "> ${_ledgerMoneroCommands[command[1]]} ${toHexString(command.sublist(2))}"); + } +} diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 6f2435258..18171a568 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -1,5 +1,7 @@ import 'dart:ffi'; import 'dart:io'; + +import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -9,16 +11,16 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/api/wallet_manager.dart'; import 'package:cw_monero/ledger.dart'; import 'package:cw_monero/monero_wallet.dart'; +import 'package:collection/collection.dart'; import 'package:hive/hive.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; -import 'package:polyseed/polyseed.dart'; import 'package:monero/monero.dart' as monero; +import 'package:polyseed/polyseed.dart'; class MoneroNewWalletCredentials extends WalletCredentials { MoneroNewWalletCredentials( @@ -133,14 +135,12 @@ class MoneroWalletService extends WalletService< try { final path = await pathForWallet(name: name, type: getType()); - if (walletFilesExist(path)) { - await repairOldAndroidWallet(name); - } + if (walletFilesExist(path)) await repairOldAndroidWallet(name); await monero_wallet_manager .openWalletAsync({'path': path, 'password': password}); - final walletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(name, getType())); + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); final wallet = MoneroWallet( walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, @@ -204,7 +204,7 @@ class MoneroWalletService extends WalletService< @override Future rename(String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(currentName, getType())); + (info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = MoneroWallet( walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource, @@ -255,14 +255,14 @@ class MoneroWalletService extends WalletService< final password = credentials.password; final height = credentials.height; - if (wptr == null ) monero_wallet_manager.createWalletPointer(); + if (wptr == null) monero_wallet_manager.createWalletPointer(); enableLedgerExchange(wptr!, credentials.ledgerConnection); await monero_wallet_manager.restoreWalletFromHardwareWallet( - path: path, - password: password!, - restoreHeight: height!, - deviceName: 'Ledger'); + path: path, + password: password!, + restoreHeight: height!, + deviceName: 'Ledger'); final wallet = MoneroWallet( walletInfo: credentials.walletInfo!, @@ -279,7 +279,8 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, + Future restoreFromSeed( + MoneroRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { @@ -313,7 +314,8 @@ class MoneroWalletService extends WalletService< final path = await pathForWallet(name: credentials.name, type: getType()); final polyseedCoin = PolyseedCoin.POLYSEED_MONERO; final lang = PolyseedLang.getByPhrase(credentials.mnemonic); - final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin); + final polyseed = + Polyseed.decode(credentials.mnemonic, lang, polyseedCoin); return _restoreFromPolyseed( path, credentials.password!, polyseed, credentials.walletInfo!, lang); @@ -355,24 +357,18 @@ class MoneroWalletService extends WalletService< Future repairOldAndroidWallet(String name) async { try { - if (!Platform.isAndroid) { - return; - } + if (!Platform.isAndroid) return; final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name); final dir = Directory(oldAndroidWalletDirPath); - if (!dir.existsSync()) { - return; - } + if (!dir.existsSync()) return; final newWalletDirPath = await pathForWalletDir(name: name, type: getType()); dir.listSync().forEach((f) { final file = File(f.path); - final name = f.path - .split('/') - .last; + final name = f.path.split('/').last; final newPath = newWalletDirPath + '/$name'; final newFile = File(newPath); @@ -391,9 +387,7 @@ class MoneroWalletService extends WalletService< try { final path = await pathForWallet(name: name, type: getType()); - if (walletFilesExist(path)) { - await repairOldAndroidWallet(name); - } + if (walletFilesExist(path)) await repairOldAndroidWallet(name); await monero_wallet_manager.openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values @@ -412,8 +406,10 @@ class MoneroWalletService extends WalletService< @override bool requireHardwareWalletConnection(String name) { - final walletInfo = walletInfoSource.values - .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - return walletInfo.isHardwareWallet; + return walletInfoSource.values + .firstWhereOrNull( + (info) => info.id == WalletBase.idFor(name, getType())) + ?.isHardwareWallet ?? + false; } } diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 88b03ca59..c05f6fb0d 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -44,13 +44,16 @@ void startAuthenticationStateChange( } catch (error, stack) { loginError = error; await ExceptionHandler.resetLastPopupDate(); - await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack)); + await ExceptionHandler.onError( + FlutterErrorDetails(exception: error, stack: stack)); } return; } - if (state == AuthenticationState.allowed) { - if (requireHardwareWalletConnection()) { + if ([AuthenticationState.allowed, AuthenticationState.allowedCreate] + .contains(state)) { + if (state == AuthenticationState.allowed && + requireHardwareWalletConnection()) { await navigatorKey.currentState!.pushNamedAndRemoveUntil( Routes.connectDevices, (route) => false, @@ -58,14 +61,14 @@ void startAuthenticationStateChange( walletType: WalletType.monero, onConnectDevice: (context, ledgerVM) async { monero!.setGlobalLedgerConnection(ledgerVM.connection); - showPopUp( - context: context, - builder: (BuildContext context) => AlertWithOneAction( - alertTitle: S.of(context).proceed_on_device, - alertContent: S.of(context).proceed_on_device_description, - buttonText: S.of(context).cancel, - buttonAction: () => Navigator.of(context).pop()), - ); + showPopUp( + context: context, + builder: (BuildContext context) => AlertWithOneAction( + alertTitle: S.of(context).proceed_on_device, + alertContent: S.of(context).proceed_on_device_description, + buttonText: S.of(context).cancel, + buttonAction: () => Navigator.of(context).pop()), + ); await loadCurrentWallet(); getIt.get().resetCurrentSheet(); await navigatorKey.currentState! diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart index 109c5eee2..5e94c78a4 100644 --- a/lib/src/screens/connect_device/connect_device_page.dart +++ b/lib/src/screens/connect_device/connect_device_page.dart @@ -22,11 +22,13 @@ class ConnectDevicePageParams { final WalletType walletType; final OnConnectDevice onConnectDevice; final bool allowChangeWallet; + final bool isReconnect; ConnectDevicePageParams({ required this.walletType, required this.onConnectDevice, this.allowChangeWallet = false, + this.isReconnect = false, }); } @@ -34,19 +36,33 @@ class ConnectDevicePage extends BasePage { final WalletType walletType; final OnConnectDevice onConnectDevice; final bool allowChangeWallet; + final bool isReconnect; final LedgerViewModel ledgerVM; ConnectDevicePage(ConnectDevicePageParams params, this.ledgerVM) : walletType = params.walletType, onConnectDevice = params.onConnectDevice, - allowChangeWallet = params.allowChangeWallet; + allowChangeWallet = params.allowChangeWallet, + isReconnect = params.isReconnect; @override - String get title => S.current.restore_title_from_hardware_wallet; + String get title => isReconnect + ? S.current.reconnect_your_hardware_wallet + : S.current.restore_title_from_hardware_wallet; @override - Widget body(BuildContext context) => ConnectDevicePageBody( - walletType, onConnectDevice, allowChangeWallet, ledgerVM); + Widget? leading(BuildContext context) => + !isReconnect ? super.leading(context) : null; + + @override + Widget body(BuildContext context) => PopScope( + canPop: !isReconnect, + child: ConnectDevicePageBody( + walletType, + onConnectDevice, + allowChangeWallet, + ledgerVM, + )); } class ConnectDevicePageBody extends StatefulWidget { @@ -75,6 +91,8 @@ class ConnectDevicePageBodyState extends State { late Timer? _bleStateTimer = null; late StreamSubscription? _bleRefresh = null; + bool longWait = false; + @override void initState() { super.initState(); @@ -89,6 +107,11 @@ class ConnectDevicePageBodyState extends State { _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices()); } + + Future.delayed(Duration(seconds: 10), () { + if (widget.ledgerVM.bleIsEnabled && bleDevices.isEmpty) + setState(() => longWait = true); + }); }); } @@ -98,6 +121,8 @@ class ConnectDevicePageBodyState extends State { _bleStateTimer?.cancel(); _usbRefreshTimer?.cancel(); _bleRefresh?.cancel(); + + widget.ledgerVM.stopScanning(); super.dispose(); } @@ -118,12 +143,14 @@ class ConnectDevicePageBodyState extends State { Future _refreshBleDevices() async { try { if (widget.ledgerVM.bleIsEnabled) { - _bleRefresh = widget.ledgerVM - .scanForBleDevices() - .listen((device) => setState(() => bleDevices.add(device))) - ..onError((e) { - throw e.toString(); - }); + _bleRefresh = + widget.ledgerVM.scanForBleDevices().listen((device) => setState(() { + bleDevices.add(device); + if (longWait) longWait = false; + })) + ..onError((e) { + throw e.toString(); + }); _bleRefreshTimer?.cancel(); _bleRefreshTimer = null; } @@ -175,15 +202,21 @@ class ConnectDevicePageBodyState extends State { textAlign: TextAlign.center, ), ), - // DeviceTile( - // onPressed: () => Navigator.of(context).push( - // MaterialPageRoute( - // builder: (BuildContext context) => DebugDevicePage(), - // ), - // ), - // title: "Debug Ledger", - // leading: imageLedger, - // ), + Offstage( + offstage: !longWait, + child: Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Text(S.of(context).if_you_dont_see_your_device, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .titleColor), + textAlign: TextAlign.center, + ), + ), + ), Observer( builder: (_) => Offstage( offstage: widget.ledgerVM.bleIsEnabled, diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 79714aa05..2e9e04acd 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -56,9 +56,8 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> { } if (isMoneroOnly) { - // return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS) - // .isNotEmpty; - return false; + return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS) + .isNotEmpty; } return true; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index ddf2d7c89..ca471c4f2 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -580,7 +580,10 @@ class SendPage extends BasePage { alertTitle: S.of(context).proceed_on_device, alertContent: S.of(context).proceed_on_device_description, buttonText: S.of(context).cancel, - buttonAction: () => Navigator.of(context).pop()); + buttonAction: () { + sendViewModel.state = InitialExecutionState(); + Navigator.of(context).pop(); + }); }); }); } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 63f28d285..9bf924f61 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -422,8 +422,9 @@ class WalletListBodyState extends State { if (!isAuthenticatedSuccessfully) return; try { - if (widget.walletListViewModel - .requireHardwareWalletConnection(wallet)) { + final requireHardwareWalletConnection = widget.walletListViewModel + .requireHardwareWalletConnection(wallet); + if (requireHardwareWalletConnection) { await Navigator.of(context).pushNamed( Routes.connectDevices, arguments: ConnectDevicePageParams( @@ -445,8 +446,6 @@ class WalletListBodyState extends State { ); } - - changeProcessText( S.of(context).wallet_list_loading_wallet(wallet.name)); await widget.walletListViewModel.loadWallet(wallet); @@ -456,6 +455,9 @@ class WalletListBodyState extends State { if (responsiveLayoutUtil.shouldRenderMobileUI) { WidgetsBinding.instance.addPostFrameCallback((_) { if (this.mounted) { + if (requireHardwareWalletConnection) { + Navigator.of(context).pop(); + } widget.onWalletLoaded.call(context); } }); diff --git a/lib/store/authentication_store.dart b/lib/store/authentication_store.dart index 815b1ed60..db4c4861e 100644 --- a/lib/store/authentication_store.dart +++ b/lib/store/authentication_store.dart @@ -4,7 +4,7 @@ part 'authentication_store.g.dart'; class AuthenticationStore = AuthenticationStoreBase with _$AuthenticationStore; -enum AuthenticationState { uninitialized, installed, allowed, _reset } +enum AuthenticationState { uninitialized, installed, allowed, allowedCreate, _reset } abstract class AuthenticationStoreBase with Store { AuthenticationStoreBase() : state = AuthenticationState.uninitialized; @@ -23,4 +23,10 @@ abstract class AuthenticationStoreBase with Store { state = AuthenticationState._reset; state = AuthenticationState.allowed; } + + @action + void allowedCreate() { + state = AuthenticationState._reset; + state = AuthenticationState.allowedCreate; + } } diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart index 9a4bb6a45..b48f641a2 100644 --- a/lib/view_model/hardware_wallet/ledger_view_model.dart +++ b/lib/view_model/hardware_wallet/ledger_view_model.dart @@ -4,14 +4,18 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/hardware/device_connection_type.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/widgets.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as sdk; import 'package:mobx/mobx.dart'; @@ -59,15 +63,18 @@ abstract class LedgerViewModelBase with Store { bool _bleIsInitialized = false; Future _initBLE() async { if (bleIsEnabled && !_bleIsInitialized) { - ledgerPlusBLE = sdk.LedgerInterface.ble(onPermissionRequest: (_) async { - Map statuses = await [ - Permission.bluetoothScan, - Permission.bluetoothConnect, - Permission.bluetoothAdvertise, - ].request(); + ledgerPlusBLE = sdk.LedgerInterface.ble( + onPermissionRequest: (_) async { + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.bluetoothAdvertise, + ].request(); - return statuses.values.where((status) => status.isDenied).isEmpty; - }); + return statuses.values.where((status) => status.isDenied).isEmpty; + }, + bleOptions: + sdk.BluetoothOptions(maxScanDuration: Duration(minutes: 5))); _bleIsInitialized = true; } } @@ -84,16 +91,26 @@ abstract class LedgerViewModelBase with Store { Stream scanForUsbDevices() => ledgerPlusUSB.scan(); + Future stopScanning() async { + await ledgerPlusBLE.stopScanning(); + if (!Platform.isIOS) { + await ledgerPlusUSB.stopScanning(); + } + } + Future connectLedger(sdk.LedgerDevice device, WalletType type) async { if (isConnected) { try { - await _connection!.disconnect(); + await _connectionChangeListener?.cancel(); + _connectionChangeListener = null; + await _connection!.disconnect().catchError((_) {}); } catch (_) {} } final ledger = device.connectionType == sdk.ConnectionType.ble ? ledgerPlusBLE : ledgerPlusUSB; + if (_connectionChangeListener == null) { _connectionChangeListener = ledger.deviceStateChanges.listen((event) { printV('Ledger Device State Changed: $event'); @@ -101,6 +118,18 @@ abstract class LedgerViewModelBase with Store { _connection = null; if (type == WalletType.monero) { monero!.resetLedgerConnection(); + + Navigator.of( navigatorKey.currentContext!).pushNamed( + Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: WalletType.monero, + allowChangeWallet: true, + isReconnect: true, + onConnectDevice: (context, ledgerVM) async { + Navigator.of(context).pop(); + }, + ), + ); } } }); diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 68548b64a..c2cfcbd24 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -8,7 +8,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:cake_wallet/view_model/seed_settings_view_model.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -114,7 +113,7 @@ abstract class WalletCreationVMBase with Store { await _walletInfoSource.add(walletInfo); await _appStore.changeCurrentWallet(wallet); getIt.get().registerSyncTask(); - _appStore.authenticationStore.allowed(); + _appStore.authenticationStore.allowedCreate(); state = ExecutedSuccessfullyState(); } catch (e, s) { printV("error: $e"); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a57a4cd1f..1bb1ec5f1 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -355,6 +355,7 @@ "how_to_use": " ﻞﻤﻌﺘﺴﺗ ﻒﻴﻛ", "how_to_use_card": "كيفية استخدام هذه البطاقة", "id": "رقم المعرف:", + "if_you_dont_see_your_device": "إذا كنت لا ترى جهازك أعلاه ، فيرجى التأكد من أن دفتر الأستاذ الخاص بك مستيقظًا ومؤمنًا!", "ignor": "تجاهل", "import": "ﺩﺭﻮﺘﺴﻳ", "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", @@ -538,6 +539,7 @@ "recipient_address": "عنوان المستلم", "reconnect": "أعد الاتصال", "reconnect_alert_text": "هل أنت متأكد من رغبتك في إعادة الاتصال؟", + "reconnect_your_hardware_wallet": "أعد توصيل محفظة الأجهزة الخاصة بك", "reconnection": "إعادة الاتصال", "red_dark_theme": "موضوع الظلام الأحمر", "red_light_theme": "موضوع الضوء الأحمر", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 2aca0f08e..b624c2b9a 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -355,6 +355,7 @@ "how_to_use": "Как да използвам", "how_to_use_card": "Как се ползва тази карта", "id": "ID: ", + "if_you_dont_see_your_device": "Ако не виждате устройството си по -горе, моля, уверете се, че вашата книга е будна и отключена!", "ignor": "Игнориране", "import": "Импортиране", "importNFTs": "Импортирайте NFT", @@ -538,6 +539,7 @@ "recipient_address": "Адрес на получател", "reconnect": "Reconnect", "reconnect_alert_text": "Сигурни ли сте, че искате да се свържете отново?", + "reconnect_your_hardware_wallet": "Свържете отново хардуерния си портфейл", "reconnection": "Свързване отново", "red_dark_theme": "Червена тъмна тема", "red_light_theme": "Тема на червената светлина", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 7ce5538ae..be273c4d9 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -355,6 +355,7 @@ "how_to_use": "Jak používat", "how_to_use_card": "Jak použít tuto kartu", "id": "ID: ", + "if_you_dont_see_your_device": "Pokud vaše zařízení nevidíte výše, ujistěte se, že vaše kniha je vzhůru a odemknutá!", "ignor": "Ignorovat", "import": "Import", "importNFTs": "Importujte NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adresa příjemce", "reconnect": "Znovu připojit", "reconnect_alert_text": "Opravdu se chcete znovu připojit?", + "reconnect_your_hardware_wallet": "Znovu připojte svou hardwarovou peněženku", "reconnection": "Znovu připojit", "red_dark_theme": "Červené temné téma", "red_light_theme": "Téma červeného světla", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index bc06b4a53..ec0a9bb1f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -355,6 +355,7 @@ "how_to_use": "Wie benutzt man", "how_to_use_card": "Wie man diese Karte benutzt", "id": "ID: ", + "if_you_dont_see_your_device": "Wenn Sie Ihr Gerät nicht sehen, stellen Sie bitte sicher, dass Ihr Ledger an und entsperrt ist!", "ignor": "Ignorieren", "import": "Importieren", "importNFTs": "NFTs importieren", @@ -539,6 +540,7 @@ "recipient_address": "Empfängeradresse", "reconnect": "Erneut verbinden", "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", + "reconnect_your_hardware_wallet": "Hardware-Wallet neu verbinden", "reconnection": "Neu verbinden", "red_dark_theme": "Red Dark Thema", "red_light_theme": "Red Light Thema", @@ -973,4 +975,4 @@ "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 26771edf1..be732e3c0 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -355,6 +355,7 @@ "how_to_use": "How to use", "how_to_use_card": "How to use this card", "id": "ID: ", + "if_you_dont_see_your_device": "If you don't see your device above, please be sure your Ledger is awake and unlocked!", "ignor": "Ignore", "import": "Import", "importNFTs": "Import NFTs", @@ -538,6 +539,7 @@ "recipient_address": "Recipient address", "reconnect": "Reconnect", "reconnect_alert_text": "Are you sure you want to reconnect?", + "reconnect_your_hardware_wallet": "Reconnect your Hardware Wallet", "reconnection": "Reconnection", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Red Light Theme", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6f2bd60b9..7373baae9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -355,6 +355,7 @@ "how_to_use": "Cómo utilizar", "how_to_use_card": "Cómo usar esta tarjeta", "id": "ID: ", + "if_you_dont_see_your_device": "Si no ve su dispositivo arriba, ¡asegúrese de que su libro mayor esté despierto y desbloqueado!", "ignor": "Pasar por alto", "import": "Importar", "importNFTs": "Importar NFT", @@ -539,6 +540,7 @@ "recipient_address": "Dirección del receptor", "reconnect": "Volver a conectar", "reconnect_alert_text": "¿Estás seguro de reconectar?", + "reconnect_your_hardware_wallet": "Vuelva a conectar su billetera de hardware", "reconnection": "Reconexión", "red_dark_theme": "Tema rojo oscuro", "red_light_theme": "Tema de la luz roja", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index ff5c17cde..b50211d4b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -355,6 +355,7 @@ "how_to_use": "Comment utiliser", "how_to_use_card": "Comment utiliser cette carte", "id": "ID : ", + "if_you_dont_see_your_device": "Si vous ne voyez pas votre appareil ci-dessus, assurez-vous que votre grand livre est éveillé et déverrouillé!", "ignor": "Ignorer", "import": "Importer", "importNFTs": "Importer des NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adresse bénéficiaire", "reconnect": "Reconnecter", "reconnect_alert_text": "Êtes vous certain de vouloir vous reconnecter ?", + "reconnect_your_hardware_wallet": "Reconnectez votre portefeuille matériel", "reconnection": "Reconnexion", "red_dark_theme": "Thème rouge sombre", "red_light_theme": "Thème rouge clair", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index a13ed2af4..71aa7f490 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -355,6 +355,7 @@ "how_to_use": "Yadda ake amfani da shi", "how_to_use_card": "Yadda ake amfani da wannan kati", "id": "ID:", + "if_you_dont_see_your_device": "Idan baku ga na'urarka da ke sama ba, da fatan za a tabbata Ledger dinku yana farkawa kuma a buɗe!", "ignor": "Yi watsi da shi", "import": "Shigo da", "importNFTs": "Shigo da NFTs", @@ -540,6 +541,7 @@ "recipient_address": "Adireshin mai karɓa", "reconnect": "Sake haɗawa", "reconnect_alert_text": "Shin kun tabbata kuna son sake haɗawa?", + "reconnect_your_hardware_wallet": "Sake kunnawa kayan aiki", "reconnection": "Sake haɗawa", "red_dark_theme": "Ja duhu taken", "red_light_theme": "Ja mai haske", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b73414dee..811d34cd1 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -355,6 +355,7 @@ "how_to_use": "का उपयोग कैसे करें", "how_to_use_card": "इस कार्ड का उपयोग कैसे करें", "id": "ID: ", + "if_you_dont_see_your_device": "यदि आप अपने डिवाइस को ऊपर नहीं देखते हैं, तो कृपया सुनिश्चित करें कि आपका लेजर जागृत और अनलॉक हो गया है!", "ignor": "नज़रअंदाज़ करना", "import": "आयात", "importNFTs": "एनएफटी आयात करें", @@ -540,6 +541,7 @@ "recipient_address": "प्राप्तकर्ता का पता", "reconnect": "रिकनेक्ट", "reconnect_alert_text": "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?", + "reconnect_your_hardware_wallet": "अपने हार्डवेयर वॉलेट को फिर से कनेक्ट करें", "reconnection": "पुनर्संयोजन", "red_dark_theme": "लाल डार्क थीम", "red_light_theme": "लाल प्रकाश थीम", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 87d66122c..71be8f531 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -355,6 +355,7 @@ "how_to_use": "Kako koristiti", "how_to_use_card": "Kako koristiti ovu karticu", "id": "ID: ", + "if_you_dont_see_your_device": "Ako svoj uređaj ne vidite gore, budite sigurni da je vaša knjiga budna i otključana!", "ignor": "Zanemariti", "import": "Uvoz", "importNFTs": "Uvoz NFT-ova", @@ -538,6 +539,7 @@ "recipient_address": "Primateljeva adresa", "reconnect": "Ponovno povezivanje", "reconnect_alert_text": "Jeste li sigurni da se želite ponovno povezati?", + "reconnect_your_hardware_wallet": "Ponovno spojite svoj hardverski novčanik", "reconnection": "Ponovno povezivanje", "red_dark_theme": "Crvena tamna tema", "red_light_theme": "Tema crvenog svjetla", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index dfbd94cdc..f17c91878 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -355,6 +355,7 @@ "how_to_use": "Ինչպես օգտագործել", "how_to_use_card": "Ինչպես օգտագործել այս քարտը", "id": "ID: ", + "if_you_dont_see_your_device": "Եթե ​​ձեր սարքը վերեւում չեք տեսնում, համոզվեք, որ ձեր Ledger- ը արթուն է եւ բացված:", "ignor": "Անտեսել", "import": "Ներմուծել", "importNFTs": "Ներմուծել NFT-ներ", @@ -538,6 +539,7 @@ "recipient_address": "Ստացողի հասցե", "reconnect": "Վերակապվել", "reconnect_alert_text": "Դուք վստահ եք, որ ուզում եք վերակապվել?", + "reconnect_your_hardware_wallet": "Միացրեք ձեր ապարատային դրամապանակը", "reconnection": "Վերակապում", "red_dark_theme": "Կարմիր մութ տեսք", "red_light_theme": "Կարմիր պայծառ տեսք", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b3ef0c67b..66fbaa320 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -355,6 +355,7 @@ "how_to_use": "Cara Penggunaan", "how_to_use_card": "Bagaimana menggunakan kartu ini", "id": "ID: ", + "if_you_dont_see_your_device": "Jika Anda tidak melihat perangkat Anda di atas, pastikan buku besar Anda terjaga dan tidak terkunci!", "ignor": "Abaikan", "import": "Impor", "importNFTs": "Impor NFT", @@ -540,6 +541,7 @@ "recipient_address": "Alamat penerima", "reconnect": "Sambungkan kembali", "reconnect_alert_text": "Apakah Anda yakin ingin menyambungkan kembali?", + "reconnect_your_hardware_wallet": "Hubungkan kembali dompet perangkat keras Anda", "reconnection": "Koneksi kembali", "red_dark_theme": "Tema gelap merah", "red_light_theme": "Tema lampu merah", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 2cf07fdd7..84f2e6c3a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -356,6 +356,7 @@ "how_to_use": "Come usare", "how_to_use_card": "Come usare questa carta", "id": "ID: ", + "if_you_dont_see_your_device": "Se non vedi il tuo dispositivo sopra, assicurati che il tuo libro mastro sia sveglio e sbloccato!", "ignor": "Ignorare", "import": "Importare", "importNFTs": "Importa NFT", @@ -540,6 +541,7 @@ "recipient_address": "Indirizzo di destinazione", "reconnect": "Riconnetti", "reconnect_alert_text": "Sei sicuro di volerti riconnettere?", + "reconnect_your_hardware_wallet": "Ricollega il tuo portafoglio hardware", "reconnection": "Riconnessione", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Tema della luce rossa", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3edb9f88d..36be2118e 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -356,6 +356,7 @@ "how_to_use": "使い方", "how_to_use_card": "このカードの使用方法", "id": "ID: ", + "if_you_dont_see_your_device": "上記のデバイスが表示されない場合は、元帳が目を覚ましてロック解除されていることを確認してください!", "ignor": "無視", "import": "輸入", "importNFTs": "NFTのインポート", @@ -539,6 +540,7 @@ "recipient_address": "受信者のアドレス", "reconnect": "再接続", "reconnect_alert_text": "再接続しますか?", + "reconnect_your_hardware_wallet": "ハードウェアウォレットを再接続します", "reconnection": "再接続", "red_dark_theme": "赤い暗いテーマ", "red_light_theme": "赤色光のテーマ", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6e5fb4a7b..8f36fc56c 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -355,6 +355,7 @@ "how_to_use": "사용하는 방법", "how_to_use_card": "이 카드를 사용하는 방법", "id": "ID: ", + "if_you_dont_see_your_device": "위의 장치가 표시되지 않으면 원장이 깨어 있고 잠금 해제되었는지 확인하십시오!", "ignor": "무시하다", "import": "수입", "importNFTs": "NFT 가져오기", @@ -502,8 +503,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": "다른 노드에 연결을 시도하십시오", @@ -539,6 +540,7 @@ "recipient_address": "받는 사람 주소", "reconnect": "다시 연결", "reconnect_alert_text": "다시 연결 하시겠습니까?", + "reconnect_your_hardware_wallet": "하드웨어 지갑을 다시 연결하십시오", "reconnection": "재 연결", "red_dark_theme": "빨간 어두운 테마", "red_light_theme": "빨간불 테마", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index a7ada97ef..c41ce87b3 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -355,6 +355,7 @@ "how_to_use": "အသုံးပြုနည်း", "how_to_use_card": "ဒီကတ်ကို ဘယ်လိုသုံးမလဲ။", "id": "ID:", + "if_you_dont_see_your_device": "သင်၏စက်ကိုအထက်တွင်မတွေ့ပါကသင်၏ Ledger သည်နိုးလာပြီးသော့ဖွင့်နေသည်ကိုသေချာပါစေ။", "ignor": "လျစ်လျူရှုပါ။", "import": "သွင်းကုန်", "importNFTs": "NFTs များကို တင်သွင်းပါ။", @@ -538,6 +539,7 @@ "recipient_address": "လက်ခံသူလိပ်စာ", "reconnect": "ပြန်လည်ချိတ်ဆက်ပါ။", "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား။ ?", + "reconnect_your_hardware_wallet": "သင့်ရဲ့ hardware ပိုက်ဆံအိတ်ကိုပြန်လည်ချိတ်ဆက်ပါ", "reconnection": "ပြန်လည်ချိတ်ဆက်မှု", "red_dark_theme": "အနီရောင်မှောင်မိုက်ဆောင်ပုဒ်", "red_light_theme": "အနီရောင်အလင်းအကြောင်းအရာ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ba20bb26a..d4f81e00f 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -355,6 +355,7 @@ "how_to_use": "Hoe te gebruiken", "how_to_use_card": "Hoe deze kaart te gebruiken", "id": "ID: ", + "if_you_dont_see_your_device": "Als u uw apparaat hierboven niet ziet, zorg er dan voor dat uw grootboek wakker is en ontgrendeld is!", "ignor": "Negeren", "import": "Importeren", "importNFTs": "NFT's importeren", @@ -538,6 +539,7 @@ "recipient_address": "Adres ontvanger", "reconnect": "Sluit", "reconnect_alert_text": "Weet u zeker dat u opnieuw verbinding wilt maken?", + "reconnect_your_hardware_wallet": "Sluit uw hardware -portemonnee opnieuw aan", "reconnection": "Reconnection", "red_dark_theme": "Rood donker thema", "red_light_theme": "Rood licht thema", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index d50def305..aa2832a0e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -355,6 +355,7 @@ "how_to_use": "Jak używać", "how_to_use_card": "Jak korzystać z tej karty?", "id": "ID: ", + "if_you_dont_see_your_device": "Jeśli nie widzisz swojego urządzenia powyżej, upewnij się, że Twoja księga nie śpi i odblokowana!", "ignor": "Ignorować", "import": "Import", "importNFTs": "Importuj NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adres odbiorcy", "reconnect": "Połącz ponownie", "reconnect_alert_text": "Czy na pewno ponownie się ponownie połączysz?", + "reconnect_your_hardware_wallet": "Ponownie podłącz portfel sprzętowy", "reconnection": "Ponowne łączenie", "red_dark_theme": "Czerwony Mroczny motyw", "red_light_theme": "Motyw czerwony światło", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7ff9fdc4e..929187ff3 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -355,6 +355,7 @@ "how_to_use": "Como usar", "how_to_use_card": "Como usar este cartão", "id": "ID: ", + "if_you_dont_see_your_device": "Se você não vê seu dispositivo acima, certifique -se de que seu livro esteja acordado e desbloqueado!", "ignor": "Ignorar", "import": "Importar", "importNFTs": "Importar NFTs", @@ -540,6 +541,7 @@ "recipient_address": "Endereço do destinatário", "reconnect": "Reconectar", "reconnect_alert_text": "Você tem certeza de que deseja reconectar?", + "reconnect_your_hardware_wallet": "Reconecte sua carteira de hardware", "reconnection": "Reconectar", "red_dark_theme": "Tema escuro vermelho", "red_light_theme": "Tema da luz vermelha", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b1d6c2461..459d3a843 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -355,6 +355,7 @@ "how_to_use": "Как использовать", "how_to_use_card": "Как использовать эту карту", "id": "ID: ", + "if_you_dont_see_your_device": "Если вы не видите свое устройство выше, пожалуйста, убедитесь, что ваша бухгалтерская книга бодрствует и разблокирована!", "ignor": "Игнорировать", "import": "Импортировать", "importNFTs": "Импортировать NFT", @@ -539,6 +540,7 @@ "recipient_address": "Адрес получателя", "reconnect": "Переподключиться", "reconnect_alert_text": "Вы хотите переподключиться?", + "reconnect_your_hardware_wallet": "Воссоедините свой аппаратный кошелек", "reconnection": "Переподключение", "red_dark_theme": "Красная темная тема", "red_light_theme": "Тема красного света", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b5587073b..12fef4d1c 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -355,6 +355,7 @@ "how_to_use": "วิธีใช้", "how_to_use_card": "วิธีใช้บัตรนี้", "id": "ID: ", + "if_you_dont_see_your_device": "หากคุณไม่เห็นอุปกรณ์ของคุณด้านบนโปรดตรวจสอบให้แน่ใจว่าบัญชีแยกประเภทของคุณตื่นและปลดล็อค!", "ignor": "ละเว้น", "import": "นำเข้า", "importNFTs": "นำเข้า NFT", @@ -538,6 +539,7 @@ "recipient_address": "ที่อยู่ผู้รับ", "reconnect": "เชื่อมต่อใหม่", "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", + "reconnect_your_hardware_wallet": "เชื่อมต่อกระเป๋าเงินฮาร์ดแวร์ของคุณอีกครั้ง", "reconnection": "เชื่อมต่อใหม่", "red_dark_theme": "ธีมสีแดงเข้ม", "red_light_theme": "ธีมแสงสีแดง", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 774887859..1a9e17ad9 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -355,6 +355,7 @@ "how_to_use": "Paano gamitin", "how_to_use_card": "Paano gamitin ang card na ito", "id": "ID: ", + "if_you_dont_see_your_device": "Kung hindi mo nakikita ang iyong aparato sa itaas, siguraduhin na ang iyong ledger ay gising at naka -lock!", "ignor": "Huwag pansinin", "import": "Mag-import", "importNFTs": "Mag-import ng mga NFT", @@ -538,6 +539,7 @@ "recipient_address": "Address ng tatanggap", "reconnect": "Kumonekta muli", "reconnect_alert_text": "Sigurado ka bang gusto mong kumonekta uli?", + "reconnect_your_hardware_wallet": "Ikonekta muli ang iyong wallet ng hardware", "reconnection": "Muling pagkakakonekta", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Red Light Theme", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 83d766347..b0341b6e0 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -355,6 +355,7 @@ "how_to_use": "Nasıl kullanılır", "how_to_use_card": "Bu kart nasıl kullanılır", "id": "ID: ", + "if_you_dont_see_your_device": "Cihazınızı yukarıda görmüyorsanız, lütfen defterinizin uyanık olduğundan ve kilidinin açıldığından emin olun!", "ignor": "Yoksay", "import": "İçe aktarmak", "importNFTs": "NFT'leri içe aktar", @@ -538,6 +539,7 @@ "recipient_address": "Alıcı adresi", "reconnect": "Yeniden Bağlan", "reconnect_alert_text": "Yeniden bağlanmak istediğinden emin misin?", + "reconnect_your_hardware_wallet": "Donanım cüzdanınızı yeniden bağlayın", "reconnection": "Yeniden bağlantı", "red_dark_theme": "Kırmızı Karanlık Tema", "red_light_theme": "Kırmızı Işık Teması", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index fd69c6cbf..aa4aa7d5e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -355,6 +355,7 @@ "how_to_use": "Як використовувати", "how_to_use_card": "Як використовувати цю картку", "id": "ID: ", + "if_you_dont_see_your_device": "Якщо ви не бачите свого пристрою вище, будь ласка, переконайтеся, що ваша книга прокинеться і розблокована!", "ignor": "Ігнорувати", "import": "Імпорт", "importNFTs": "Імпорт NFT", @@ -538,6 +539,7 @@ "recipient_address": "Адреса одержувача", "reconnect": "Перепідключитися", "reconnect_alert_text": "Ви хочете перепідключитися?", + "reconnect_your_hardware_wallet": "Повторно підключіть свій апаратний гаманець", "reconnection": "Перепідключення", "red_dark_theme": "Червона темна тема", "red_light_theme": "Тема червоного світла", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e4e8d8aee..2beef4559 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -355,6 +355,7 @@ "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ", "how_to_use_card": "اس کارڈ کو استعمال کرنے کا طریقہ", "id": "ID:", + "if_you_dont_see_your_device": "اگر آپ اوپر اپنا آلہ نہیں دیکھتے ہیں تو ، براہ کرم یقینی بنائیں کہ آپ کا لیجر بیدار اور غیر مقفل ہے!", "ignor": "نظر انداز کرنا", "import": " ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", @@ -540,6 +541,7 @@ "recipient_address": "وصول کنندہ کا پتہ", "reconnect": "دوبارہ جڑیں۔", "reconnect_alert_text": "کیا آپ واقعی دوبارہ جڑنا چاہتے ہیں؟", + "reconnect_your_hardware_wallet": "اپنے ہارڈ ویئر پرس کو دوبارہ مربوط کریں", "reconnection": "دوبارہ رابطہ", "red_dark_theme": "ریڈ ڈارک تھیم", "red_light_theme": "ریڈ لائٹ تھیم", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index f74078746..8ea1d1672 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -354,6 +354,7 @@ "how_to_use": "Cách sử dụng", "how_to_use_card": "Cách sử dụng thẻ này", "id": "ID: ", + "if_you_dont_see_your_device": "Nếu bạn không thấy thiết bị của mình ở trên, xin hãy chắc chắn rằng sổ cái của bạn đã tỉnh táo và mở khóa!", "ignor": "Bỏ qua", "import": "Nhập", "importNFTs": "Nhập NFT", @@ -537,6 +538,7 @@ "recipient_address": "Địa chỉ người nhận", "reconnect": "Kết nối lại", "reconnect_alert_text": "Bạn có chắc chắn muốn kết nối lại không?", + "reconnect_your_hardware_wallet": "Kết nối lại ví phần cứng của bạn", "reconnection": "Kết nối lại", "red_dark_theme": "Chủ đề tối đỏ", "red_light_theme": "Chủ đề sáng đỏ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 14f0e5cf6..5b7e9048e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -356,6 +356,7 @@ "how_to_use": "Bawo ni lati lo", "how_to_use_card": "Báyìí ni wọ́n ṣe ń lo káàdì yìí.", "id": "Àmì Ìdánimọ̀: ", + "if_you_dont_see_your_device": "Ti o ko ba ri ẹrọ rẹ loke, jọwọ rii daju pe a le jiji rẹ ati ṣiṣi!", "ignor": "Ṣàìfiyèsí", "import": "gbe wọle", "importNFTs": "Gbe awọn NFT wọle", @@ -539,6 +540,7 @@ "recipient_address": "Àdírẹ́sì olùgbà", "reconnect": "Ṣe àtúnse", "reconnect_alert_text": "Ṣó dá ẹ lójú pé ẹ fẹ́ ṣe àtúnse?", + "reconnect_your_hardware_wallet": "Ṣe atunṣe apamọwọ ohun elo rẹ", "reconnection": "Àtúnṣe", "red_dark_theme": "Akọle dudu pupa", "red_light_theme": "Akori ina pupa", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8d9828c6a..0ccd89271 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -355,6 +355,7 @@ "how_to_use": "如何使用", "how_to_use_card": "如何使用这张卡", "id": "ID: ", + "if_you_dont_see_your_device": "如果您在上面看不到设备,请确保您的分类帐已经清醒并解锁!", "ignor": "忽视", "import": "进口", "importNFTs": "导入 NFT", @@ -538,6 +539,7 @@ "recipient_address": "收件人地址", "reconnect": "重新连接", "reconnect_alert_text": "您确定要重新连接吗?", + "reconnect_your_hardware_wallet": "重新连接您的硬件钱包", "reconnection": "重新连接", "red_dark_theme": "红色的黑暗主题", "red_light_theme": "红灯主题", From ca4d4ae6412c5da45ec18803868411064899a39e Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 13 Dec 2024 19:20:16 -0500 Subject: [PATCH 23/26] Update support links (#1876) --- .../screens/dashboard/pages/balance_page.dart | 4 ++-- .../dashboard/pages/transactions_page.dart | 2 +- lib/src/screens/setup_2fa/setup_2fa.dart | 2 +- .../screens/setup_2fa/setup_2fa_qr_page.dart | 3 +-- lib/src/screens/support/support_page.dart | 2 +- lib/view_model/support_view_model.dart | 17 +++++++++++------ res/values/strings_ar.arb | 2 +- res/values/strings_bg.arb | 2 +- res/values/strings_cs.arb | 2 +- res/values/strings_de.arb | 2 +- res/values/strings_en.arb | 2 +- res/values/strings_es.arb | 2 +- res/values/strings_fr.arb | 2 +- res/values/strings_ha.arb | 2 +- res/values/strings_hi.arb | 2 +- res/values/strings_hr.arb | 2 +- res/values/strings_hy.arb | 2 +- res/values/strings_id.arb | 2 +- res/values/strings_it.arb | 2 +- res/values/strings_ja.arb | 2 +- res/values/strings_ko.arb | 2 +- res/values/strings_my.arb | 2 +- res/values/strings_nl.arb | 2 +- res/values/strings_pl.arb | 2 +- res/values/strings_pt.arb | 2 +- res/values/strings_ru.arb | 2 +- res/values/strings_th.arb | 2 +- res/values/strings_tl.arb | 2 +- res/values/strings_tr.arb | 2 +- res/values/strings_uk.arb | 2 +- res/values/strings_ur.arb | 2 +- res/values/strings_vi.arb | 2 +- res/values/strings_yo.arb | 2 +- res/values/strings_zh.arb | 2 +- 34 files changed, 45 insertions(+), 41 deletions(-) diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 46c01254a..a0886ab9b 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -320,7 +320,7 @@ class CryptoBalanceWidget extends StatelessWidget { behavior: HitTestBehavior.opaque, onTap: () => launchUrl( Uri.parse( - "https://guides.cakewallet.com/docs/cryptos/bitcoin/#silent-payments"), + "https://docs.cakewallet.com/cryptos/bitcoin#silent-payments"), mode: LaunchMode.externalApplication, ), child: Row( @@ -894,7 +894,7 @@ class BalanceRowWidget extends StatelessWidget { behavior: HitTestBehavior.opaque, onTap: () => launchUrl( Uri.parse( - "https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"), + "https://docs.cakewallet.com/cryptos/litecoin.html#mweb"), mode: LaunchMode.externalApplication, ), child: Row( diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index 0db9ac35b..9472110ea 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -53,7 +53,7 @@ class TransactionsPage extends StatelessWidget { onTap: () { try { final uri = Uri.parse( - "https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/"); + "https://docs.cakewallet.com/faq/funds-not-appearing"); launchUrl(uri, mode: LaunchMode.externalApplication); } catch (_) {} }, diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index 5fa5cabb8..f74c2bf36 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -20,7 +20,7 @@ class Setup2FAPage extends BasePage { Widget body(BuildContext context) { final cake2FAGuideTitle = 'Cake 2FA Guide'; final cake2FAGuideUri = - Uri.parse('https://guides.cakewallet.com/docs/advanced-features/authentication'); + Uri.parse('https://docs.cakewallet.com/features/advanced/authentication/'); return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ diff --git a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart index 3ce10b596..48a90b329 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -6,7 +6,6 @@ import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; @@ -30,7 +29,7 @@ class Setup2FAQRPage extends BasePage { width: 16, color: Theme.of(context).extension()!.titleColor); final cake2FAHowToUseUrl = Uri.parse( - 'https://guides.cakewallet.com/docs/advanced-features/authentication/#enabling-cake-2fa'); + 'https://docs.cakewallet.com/features/advanced/authentication/#enabling-cake-2fa'); return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( diff --git a/lib/src/screens/support/support_page.dart b/lib/src/screens/support/support_page.dart index 049ab2fb7..88154e91d 100644 --- a/lib/src/screens/support/support_page.dart +++ b/lib/src/screens/support/support_page.dart @@ -70,7 +70,7 @@ class SupportPage extends BasePage { ), title: S.of(context).support_title_guides, description: S.of(context).support_description_guides, - onPressed: () => _launchUrl(supportViewModel.guidesUrl), + onPressed: () => _launchUrl(supportViewModel.docsUrl), ), ), Padding( diff --git a/lib/view_model/support_view_model.dart b/lib/view_model/support_view_model.dart index 45b9cb9bf..f6f1cba0f 100644 --- a/lib/view_model/support_view_model.dart +++ b/lib/view_model/support_view_model.dart @@ -31,10 +31,15 @@ abstract class SupportViewModelBase with Store { linkTitle: S.current.apk_update, link: 'https://github.com/cake-tech/cake_wallet/releases'), LinkListItem( - title: 'Telegram Community', - icon: 'assets/images/Telegram.png', - linkTitle: 't.me/cakewallet', - link: 'https://t.me/cakewallet'), + title: 'Discord', + icon: 'assets/images/discord.png', + linkTitle: 'discord.gg/pwmWa6aFpX', + link: 'https://discord.gg/pwmWa6aFpX'), + LinkListItem( + title: 'Telegram', + icon: 'assets/images/Telegram.png', + linkTitle: 't.me/cakewallet', + link: 'https://t.me/cakewalletannouncements'), LinkListItem( title: 'Telegram Support Bot', icon: 'assets/images/Telegram.png', @@ -75,7 +80,7 @@ abstract class SupportViewModelBase with Store { icon: 'assets/images/onramper_dark.png', lightIcon: 'assets/images/onramper_light.png', linkTitle: 'View exchanges', - link: 'https://guides.cakewallet.com/docs/service-support/buy/#onramper'), + link: 'https://docs.cakewallet.com/support/buy/#onramper'), LinkListItem( title: 'DFX', icon: 'assets/images/dfx_dark.png', @@ -103,7 +108,7 @@ abstract class SupportViewModelBase with Store { // link: 'mailto:support@y.at') ]; - final guidesUrl = 'https://guides.cakewallet.com'; + final docsUrl = 'https://docs.cakewallet.com'; String fetchUrl({String locale = "en", String authToken = ""}) { var supportUrl = diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 1bb1ec5f1..97e18a9b3 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -759,7 +759,7 @@ "support_description_guides": "توثيق ودعم القضايا المشتركة", "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", - "support_title_guides": "أدلة محفظة كعكة", + "support_title_guides": "مستندات محفظة كعكة", "support_title_live_chat": "الدعم المباشر", "support_title_other_links": "روابط دعم أخرى", "sweeping_wallet": "كنس المحفظة", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b624c2b9a..73a310ae7 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -759,7 +759,7 @@ "support_description_guides": "Документация и подкрепа за общи проблеми", "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", - "support_title_guides": "Ръководства за портфейл за торта", + "support_title_guides": "Документи за портфейл за торта", "support_title_live_chat": "Подкрепа на живо", "support_title_other_links": "Други връзки за поддръжка", "sweeping_wallet": "Метещ портфейл", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index be273c4d9..67c1e6901 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -759,7 +759,7 @@ "support_description_guides": "Dokumentace a podpora běžných otázek", "support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory", "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody", - "support_title_guides": "Průvodce peněženkami dortu", + "support_title_guides": "Dokumenty peněženky dortu", "support_title_live_chat": "Živá podpora", "support_title_other_links": "Další odkazy na podporu", "sweeping_wallet": "Zametací peněženka", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index ec0a9bb1f..604c50500 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -760,7 +760,7 @@ "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", "support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen", "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden", - "support_title_guides": "Cake Wallet Guides", + "support_title_guides": "Kuchenbrieftasche Docs", "support_title_live_chat": "Live Support", "support_title_other_links": "Andere Support-Links", "sweeping_wallet": "Wallet leeren", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index be732e3c0..3b7e97801 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -759,7 +759,7 @@ "support_description_guides": "Documentation and support for common issues", "support_description_live_chat": "Free and fast! Trained support representatives are available to assist", "support_description_other_links": "Join our communities or reach us or our partners through other methods", - "support_title_guides": "Cake Wallet guides", + "support_title_guides": "Cake Wallet docs", "support_title_live_chat": "Live support", "support_title_other_links": "Other support links", "sweeping_wallet": "Sweeping wallet", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7373baae9..52bc670ce 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -760,7 +760,7 @@ "support_description_guides": "Documentación y apoyo para problemas comunes", "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar", "support_description_other_links": "Únete a nuestras comunidades o comunícate con nosotros nuestros socios a través de otros métodos", - "support_title_guides": "Guías de billetera para pastel", + "support_title_guides": "Documentos de billetera de pastel", "support_title_live_chat": "Soporte en tiempo real", "support_title_other_links": "Otros enlaces de soporte", "sweeping_wallet": "Barrer billetera (gastar todos los fondos disponibles)", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index b50211d4b..c1ef104fc 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -759,7 +759,7 @@ "support_description_guides": "Documentation et support pour les problèmes communs", "support_description_live_chat": "GRATUIT ET RAPIDE ! Des représentants de soutien formé sont disponibles pour aider", "support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes", - "support_title_guides": "Guides de Cake Wallet", + "support_title_guides": "Docs de portefeuille à gâteau", "support_title_live_chat": "Support en direct", "support_title_other_links": "Autres liens d'assistance", "sweeping_wallet": "Portefeuille (wallet) de consolidation", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 71aa7f490..02cebd0fb 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -761,7 +761,7 @@ "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", "support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa", "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi", - "support_title_guides": "Jagorar Cake", + "support_title_guides": "Docs Bakin", "support_title_live_chat": "Tallafi na Live", "support_title_other_links": "Sauran hanyoyin tallafi", "sweeping_wallet": "Kashi na kasa", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 811d34cd1..973cc5521 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -761,7 +761,7 @@ "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", - "support_title_guides": "केक वॉलेट गाइड", + "support_title_guides": "केक बटुए डॉक्स", "support_title_live_chat": "लाइव सहायता", "support_title_other_links": "अन्य समर्थन लिंक", "sweeping_wallet": "स्वीपिंग वॉलेट", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 71be8f531..e7362ac20 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -759,7 +759,7 @@ "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", "support_description_live_chat": "Besplatno i brzo! Obučeni predstavnici podrške dostupni su za pomoć", "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama", - "support_title_guides": "Vodiči za torte", + "support_title_guides": "Dokumenti s kolačem kolača", "support_title_live_chat": "Podrška uživo", "support_title_other_links": "Ostale veze za podršku", "sweeping_wallet": "Čisti novčanik", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index f17c91878..38117026d 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -759,7 +759,7 @@ "support_description_guides": "Տարածված խնդիրների փաստաթղթավորում և աջակցություն", "support_description_live_chat": "Անվճար և արագ աջակցություն! Պատրաստված մասնագետները պատրաստ են օգնել", "support_description_other_links": "Միացեք մեր համայնքին կամ հասեք մեզ այլ միջոցներով", - "support_title_guides": "Cake Wallet ուղեցույց", + "support_title_guides": "Տորթ դրամապանակի փաստաթղթեր", "support_title_live_chat": "Անմիջական աջակցություն", "support_title_other_links": "Այլ աջակցության հղումներ", "sweeping_wallet": "Դրամապանակը մաքրվում է", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 66fbaa320..56033231d 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -762,7 +762,7 @@ "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", "support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu", "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain", - "support_title_guides": "Panduan Dompet Kue", + "support_title_guides": "DOKS DOKO CAKE", "support_title_live_chat": "Dukungan langsung", "support_title_other_links": "Tautan dukungan lainnya", "sweeping_wallet": "Dompet menyapu", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 84f2e6c3a..0f0816fdb 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -761,7 +761,7 @@ "support_description_guides": "Documentazione e supporto per problemi comuni", "support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere", "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi", - "support_title_guides": "Guide del portafoglio per torte", + "support_title_guides": "Documenti del portafoglio per torta", "support_title_live_chat": "Supporto dal vivo", "support_title_other_links": "Altri collegamenti di supporto", "sweeping_wallet": "Portafoglio ampio", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 36be2118e..f7c95a044 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -760,7 +760,7 @@ "support_description_guides": "一般的な問題のドキュメントとサポート", "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", - "support_title_guides": "ケーキウォレットガイド", + "support_title_guides": "ケーキウォレットドキュメント", "support_title_live_chat": "ライブサポート", "support_title_other_links": "その他のサポートリンク", "sweeping_wallet": "スイープウォレット", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 8f36fc56c..f02757a27 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -760,7 +760,7 @@ "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", - "support_title_guides": "케이크 지갑 가이드", + "support_title_guides": "케이크 지갑 문서", "support_title_live_chat": "실시간 지원", "support_title_other_links": "다른 지원 링크", "sweeping_wallet": "스위핑 지갑", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c41ce87b3..dbc01c728 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -759,7 +759,7 @@ "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", - "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", + "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်များ", "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", "sweeping_wallet": "ိုက်ဆံအိတ် တံမြက်လှည်း", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index d4f81e00f..101592be7 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -759,7 +759,7 @@ "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", "support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen", "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons ​​onze partners via andere methoden", - "support_title_guides": "Cake -portemonnee gidsen", + "support_title_guides": "Cake -portemonnee documenten", "support_title_live_chat": "Live ondersteuning", "support_title_other_links": "Andere ondersteuningslinks", "sweeping_wallet": "Vegende portemonnee", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index aa2832a0e..ce243fee7 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -759,7 +759,7 @@ "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", "support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia", "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod", - "support_title_guides": "Przewodniki portfela ciasta", + "support_title_guides": "Dokumenty portfela ciasta", "support_title_live_chat": "Wsparcie na żywo", "support_title_other_links": "Inne linki wsparcia", "sweeping_wallet": "Zamiatanie portfela", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 929187ff3..07dd9ac97 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -761,7 +761,7 @@ "support_description_guides": "Documentação e suporte para problemas comuns", "support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar", "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos", - "support_title_guides": "Guias da carteira de bolo", + "support_title_guides": "Documentos da carteira de bolo", "support_title_live_chat": "Apoio ao vivo", "support_title_other_links": "Outros links de suporte", "sweeping_wallet": "Carteira varrendo", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 459d3a843..95596a17c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -760,7 +760,7 @@ "support_description_guides": "Документация и поддержка общих вопросов", "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", - "support_title_guides": "Корт -гиды", + "support_title_guides": "Корт кошелек документов", "support_title_live_chat": "Живая поддержка", "support_title_other_links": "Другие ссылки на поддержку", "sweeping_wallet": "Подметание кошелька", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 12fef4d1c..0f0069057 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -759,7 +759,7 @@ "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", - "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", + "support_title_guides": "เอกสารกระเป๋าเงินเค้ก", "support_title_live_chat": "การสนับสนุนสด", "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", "sweeping_wallet": "กวาดกระเป๋าสตางค์", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 1a9e17ad9..2c47c4713 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -759,7 +759,7 @@ "support_description_guides": "Dokumentasyon at suporta para sa mga karaniwang isyu", "support_description_live_chat": "Libre at mabilis! Ang mga bihasang kinatawan ng suporta ay magagamit upang tulungan", "support_description_other_links": "Sumali sa aming mga komunidad o maabot sa amin ang aming mga kasosyo sa pamamagitan ng iba pang mga pamamaraan", - "support_title_guides": "Mga guide sa Cake Wallet", + "support_title_guides": "Cake wallet doc", "support_title_live_chat": "Live na suporta", "support_title_other_links": "Iba pang mga link sa suporta", "sweeping_wallet": "Sweeping wallet", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b0341b6e0..f3a8b6362 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -759,7 +759,7 @@ "support_description_guides": "Ortak sorunlara belge ve destek", "support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur", "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın", - "support_title_guides": "Kek Cüzdan Kılavuzları", + "support_title_guides": "Kek Cüzdan Dokümanlar", "support_title_live_chat": "Canlı destek", "support_title_other_links": "Diğer destek bağlantıları", "sweeping_wallet": "Süpürme cüzdanı", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index aa4aa7d5e..4d0a9fc1d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -760,7 +760,7 @@ "support_description_guides": "Документація та підтримка загальних питань", "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", - "support_title_guides": "Поклики для гаманців тортів", + "support_title_guides": "Торт гаманці", "support_title_live_chat": "Жива підтримка", "support_title_other_links": "Інші посилання на підтримку", "sweeping_wallet": "Підмітаня гаманця", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 2beef4559..6cbbd2a9f 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -761,7 +761,7 @@ "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", - "support_title_guides": "کیک پرس گائڈز", + "support_title_guides": "کیک پرس کے دستاویزات", "support_title_live_chat": "براہ راست مدد", "support_title_other_links": "دوسرے سپورٹ لنکس", "sweeping_wallet": "جھاڑو دینے والا پرس", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 8ea1d1672..09371db98 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -758,7 +758,7 @@ "support_description_guides": "Tài liệu và hỗ trợ cho các vấn đề phổ biến", "support_description_live_chat": "Miễn phí và nhanh chóng! Các đại diện hỗ trợ được đào tạo sẵn sàng hỗ trợ", "support_description_other_links": "Tham gia cộng đồng của chúng tôi hoặc liên hệ với chúng tôi hoặc các đối tác của chúng tôi qua các phương pháp khác", - "support_title_guides": "Hướng dẫn Cake Wallet", + "support_title_guides": "Cake Wallet Docs", "support_title_live_chat": "Hỗ trợ trực tiếp", "support_title_other_links": "Liên kết hỗ trợ khác", "sweeping_wallet": "Quét ví", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 5b7e9048e..5becf208e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -760,7 +760,7 @@ "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", "support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ", "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran", - "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", + "support_title_guides": "Awọn iwe apamọwọ oyinbo akara oyinbo", "support_title_live_chat": "Atilẹyin ifiwe", "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", "sweeping_wallet": "Fi owo iwe iwe wofo", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 0ccd89271..2c28f07d3 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -759,7 +759,7 @@ "support_description_guides": "对常见问题的文档和支持", "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴", - "support_title_guides": "蛋糕钱包指南", + "support_title_guides": "蛋糕钱包文档", "support_title_live_chat": "实时支持", "support_title_other_links": "其他支持链接", "sweeping_wallet": "扫一扫钱包", From 707395b71a674774c420158370b74678a410dfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?rafael=20x=C9=B1r?= Date: Fri, 13 Dec 2024 21:21:04 -0300 Subject: [PATCH 24/26] Confirmation checkboxes (#1877) * feat: confirmation checkboxes * Update lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart --------- Co-authored-by: Omar Hatem --- lib/cake_pay/cake_pay_api.dart | 8 +- lib/cake_pay/cake_pay_service.dart | 26 +- .../cake_pay_confirm_purchase_card_page.dart | 253 +++++++++++++++++- lib/src/widgets/standard_checkbox.dart | 20 +- .../cake_pay_purchase_view_model.dart | 17 +- res/values/strings_ar.arb | 4 + res/values/strings_bg.arb | 4 + res/values/strings_cs.arb | 4 + res/values/strings_de.arb | 4 + res/values/strings_en.arb | 4 + res/values/strings_es.arb | 4 + res/values/strings_fr.arb | 4 + res/values/strings_ha.arb | 4 + res/values/strings_hi.arb | 4 + res/values/strings_hr.arb | 4 + res/values/strings_hy.arb | 4 + res/values/strings_id.arb | 4 + res/values/strings_it.arb | 4 + res/values/strings_ja.arb | 4 + res/values/strings_ko.arb | 4 + res/values/strings_my.arb | 4 + res/values/strings_nl.arb | 4 + res/values/strings_pl.arb | 4 + res/values/strings_pt.arb | 4 + res/values/strings_ru.arb | 4 + res/values/strings_th.arb | 4 + res/values/strings_tl.arb | 4 + res/values/strings_tr.arb | 4 + res/values/strings_uk.arb | 4 + res/values/strings_ur.arb | 4 + res/values/strings_vi.arb | 4 + res/values/strings_yo.arb | 4 + res/values/strings_zh.arb | 4 + 33 files changed, 417 insertions(+), 19 deletions(-) diff --git a/lib/cake_pay/cake_pay_api.dart b/lib/cake_pay/cake_pay_api.dart index cc04a0ca1..f9aa2f0f1 100644 --- a/lib/cake_pay/cake_pay_api.dart +++ b/lib/cake_pay/cake_pay_api.dart @@ -93,6 +93,9 @@ class CakePayApi { required int quantity, required String userEmail, required String token, + required bool confirmsNoVpn, + required bool confirmsVoidedRefund, + required bool confirmsTermsAgreed, }) async { final uri = Uri.https(baseCakePayUri, createOrderPath); final headers = { @@ -106,7 +109,10 @@ class CakePayApi { 'quantity': quantity, 'user_email': userEmail, 'token': token, - 'send_email': true + 'send_email': true, + 'confirms_no_vpn': confirmsNoVpn, + 'confirms_voided_refund': confirmsVoidedRefund, + 'confirms_terms_agreed': confirmsTermsAgreed, }; try { diff --git a/lib/cake_pay/cake_pay_service.dart b/lib/cake_pay/cake_pay_service.dart index 9e43c23c7..768588775 100644 --- a/lib/cake_pay/cake_pay_service.dart +++ b/lib/cake_pay/cake_pay_service.dart @@ -90,17 +90,27 @@ class CakePayService { } /// Purchase Gift Card - Future createOrder( - {required int cardId, required String price, required int quantity}) async { + Future createOrder({ + required int cardId, + required String price, + required int quantity, + required bool confirmsNoVpn, + required bool confirmsVoidedRefund, + required bool confirmsTermsAgreed, + }) async { final userEmail = (await secureStorage.read(key: cakePayEmailStorageKey))!; final token = (await secureStorage.read(key: cakePayUserTokenKey))!; return await cakePayApi.createOrder( - apiKey: cakePayApiKey, - cardId: cardId, - price: price, - quantity: quantity, - token: token, - userEmail: userEmail); + apiKey: cakePayApiKey, + cardId: cardId, + price: price, + quantity: quantity, + token: token, + userEmail: userEmail, + confirmsNoVpn: confirmsNoVpn, + confirmsVoidedRefund: confirmsVoidedRefund, + confirmsTermsAgreed: confirmsTermsAgreed, + ); } ///Simulate Purchase Gift Card diff --git a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart index 9357df2c3..fc3679104 100644 --- a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart +++ b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart @@ -10,8 +10,10 @@ import 'package:cake_wallet/src/screens/cake_pay/widgets/text_icon_button.dart'; import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; @@ -23,6 +25,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; +import 'package:url_launcher/url_launcher.dart'; class CakePayBuyCardDetailPage extends BasePage { CakePayBuyCardDetailPage(this.cakePayPurchaseViewModel); @@ -207,8 +210,10 @@ class CakePayBuyCardDetailPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: Observer(builder: (_) { return LoadingPrimaryButton( - isLoading: cakePayPurchaseViewModel.sendViewModel.state is IsExecutingState, - onPressed: () => purchaseCard(context), + isDisabled: cakePayPurchaseViewModel.isPurchasing, + isLoading: cakePayPurchaseViewModel.isPurchasing || + cakePayPurchaseViewModel.sendViewModel.state is IsExecutingState, + onPressed: () => confirmPurchaseFirst(context), text: S.of(context).purchase_gift_card, color: Theme.of(context).primaryColor, textColor: Colors.white, @@ -253,6 +258,48 @@ class CakePayBuyCardDetailPage extends BasePage { }); } + Future _showconfirmPurchaseFirstAlert(BuildContext context) async { + if (!cakePayPurchaseViewModel.confirmsNoVpn || + !cakePayPurchaseViewModel.confirmsVoidedRefund || + !cakePayPurchaseViewModel.confirmsTermsAgreed) { + await showPopUp( + context: context, + builder: (BuildContext context) => ThreeCheckboxAlert( + alertTitle: S.of(context).cakepay_confirm_purchase, + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).confirm, + actionLeftButton: () { + cakePayPurchaseViewModel.isPurchasing = false; + Navigator.of(context).pop(); + }, + actionRightButton: (confirmsNoVpn, confirmsVoidedRefund, confirmsTermsAgreed) { + cakePayPurchaseViewModel.confirmsNoVpn = confirmsNoVpn; + cakePayPurchaseViewModel.confirmsVoidedRefund = confirmsVoidedRefund; + cakePayPurchaseViewModel.confirmsTermsAgreed = confirmsTermsAgreed; + + Navigator.of(context).pop(); + }, + ), + ); + } + + if (cakePayPurchaseViewModel.confirmsNoVpn && + cakePayPurchaseViewModel.confirmsVoidedRefund && + cakePayPurchaseViewModel.confirmsTermsAgreed) { + await purchaseCard(context); + } + } + + Future confirmPurchaseFirst(BuildContext context) async { + bool isLogged = await cakePayPurchaseViewModel.cakePayService.isLogged(); + if (!isLogged) { + Navigator.of(context).pushNamed(Routes.cakePayWelcomePage); + } else { + cakePayPurchaseViewModel.isPurchasing = true; + await _showconfirmPurchaseFirstAlert(context); + } + } + Future purchaseCard(BuildContext context) async { bool isLogged = await cakePayPurchaseViewModel.cakePayService.isLogged(); if (!isLogged) { @@ -263,7 +310,9 @@ class CakePayBuyCardDetailPage extends BasePage { } catch (_) { await cakePayPurchaseViewModel.cakePayService.logout(); } - } + + } + cakePayPurchaseViewModel.isPurchasing = false; } void _showHowToUseCard( @@ -428,3 +477,201 @@ class CakePayBuyCardDetailPage extends BasePage { } } } + +class ThreeCheckboxAlert extends BaseAlertDialog { + ThreeCheckboxAlert({ + required this.alertTitle, + required this.leftButtonText, + required this.rightButtonText, + required this.actionLeftButton, + required this.actionRightButton, + this.alertBarrierDismissible = true, + Key? key, + }); + + final String alertTitle; + final String leftButtonText; + final String rightButtonText; + final VoidCallback actionLeftButton; + final Function(bool, bool, bool) actionRightButton; + final bool alertBarrierDismissible; + + bool checkbox1 = false; + void toggleCheckbox1() => checkbox1 = !checkbox1; + bool checkbox2 = false; + void toggleCheckbox2() => checkbox2 = !checkbox2; + bool checkbox3 = false; + void toggleCheckbox3() => checkbox3 = !checkbox3; + + bool showValidationMessage = true; + + @override + String get titleText => alertTitle; + + @override + bool get isDividerExists => true; + + @override + String get leftActionButtonText => leftButtonText; + + @override + String get rightActionButtonText => rightButtonText; + + @override + VoidCallback get actionLeft => actionLeftButton; + + @override + VoidCallback get actionRight => () { + actionRightButton(checkbox1, checkbox2, checkbox3); + }; + + @override + bool get barrierDismissible => alertBarrierDismissible; + + @override + Widget content(BuildContext context) { + return ThreeCheckboxAlertContent( + checkbox1: checkbox1, + toggleCheckbox1: toggleCheckbox1, + checkbox2: checkbox2, + toggleCheckbox2: toggleCheckbox2, + checkbox3: checkbox3, + toggleCheckbox3: toggleCheckbox3, + ); + } +} + +class ThreeCheckboxAlertContent extends StatefulWidget { + ThreeCheckboxAlertContent({ + required this.checkbox1, + required this.toggleCheckbox1, + required this.checkbox2, + required this.toggleCheckbox2, + required this.checkbox3, + required this.toggleCheckbox3, + Key? key, + }) : super(key: key); + + bool checkbox1; + void Function() toggleCheckbox1; + bool checkbox2; + void Function() toggleCheckbox2; + bool checkbox3; + void Function() toggleCheckbox3; + + @override + _ThreeCheckboxAlertContentState createState() => _ThreeCheckboxAlertContentState( + checkbox1: checkbox1, + toggleCheckbox1: toggleCheckbox1, + checkbox2: checkbox2, + toggleCheckbox2: toggleCheckbox2, + checkbox3: checkbox3, + toggleCheckbox3: toggleCheckbox3, + ); + + static _ThreeCheckboxAlertContentState? of(BuildContext context) { + return context.findAncestorStateOfType<_ThreeCheckboxAlertContentState>(); + } +} + +class _ThreeCheckboxAlertContentState extends State { + _ThreeCheckboxAlertContentState({ + required this.checkbox1, + required this.toggleCheckbox1, + required this.checkbox2, + required this.toggleCheckbox2, + required this.checkbox3, + required this.toggleCheckbox3, + }); + + bool checkbox1; + void Function() toggleCheckbox1; + bool checkbox2; + void Function() toggleCheckbox2; + bool checkbox3; + void Function() toggleCheckbox3; + + bool showValidationMessage = true; + + bool get areAllCheckboxesChecked => checkbox1 && checkbox2 && checkbox3; + + @override + Widget build(BuildContext context) { + return Form( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + StandardCheckbox( + value: checkbox1, + caption: S.of(context).cakepay_confirm_no_vpn, + onChanged: (bool? value) { + setState(() { + checkbox1 = value ?? false; + toggleCheckbox1(); + showValidationMessage = !areAllCheckboxesChecked; + }); + }, + ), + StandardCheckbox( + value: checkbox2, + caption: S.of(context).cakepay_confirm_voided_refund, + onChanged: (bool? value) { + setState(() { + checkbox2 = value ?? false; + toggleCheckbox2(); + showValidationMessage = !areAllCheckboxesChecked; + }); + }, + ), + StandardCheckbox( + value: checkbox3, + caption: S.of(context).cakepay_confirm_terms_agreed, + onChanged: (bool? value) { + setState(() { + checkbox3 = value ?? false; + toggleCheckbox3(); + showValidationMessage = !areAllCheckboxesChecked; + }); + }, + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => launchUrl( + Uri.parse("https://cakepay.com/cakepay-web-terms.txt"), + mode: LaunchMode.externalApplication, + ), + child: Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + S.of(context).settings_terms_and_conditions, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).primaryColor, + decoration: TextDecoration.none, + height: 1, + ), + softWrap: true, + ), + ), + ), + if (showValidationMessage) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + 'Please confirm all checkboxes', + style: TextStyle( + color: Colors.red, + fontSize: 14, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + decoration: TextDecoration.none, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index 46c5f8a34..d61b84d1d 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -26,7 +26,9 @@ class StandardCheckbox extends StatelessWidget { ], begin: Alignment.centerLeft, end: Alignment.centerRight); final boxBorder = Border.all( - color: borderColor ?? Theme.of(context).extension()!.secondaryTextColor, width: 1.0); + color: borderColor ?? Theme.of(context).extension()!.secondaryTextColor, + width: 1.0, + ); final checkedBoxDecoration = BoxDecoration( gradient: gradientBackground ? baseGradient : null, @@ -41,6 +43,7 @@ class StandardCheckbox extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( height: 24.0, @@ -55,13 +58,22 @@ class StandardCheckbox extends StatelessWidget { : Offstage(), ), if (caption.isNotEmpty) - Padding( + Flexible( + child: Padding( padding: EdgeInsets.only(left: 10), child: Text( caption, + softWrap: true, style: TextStyle( - fontSize: 16.0, color: Theme.of(context).extension()!.titleColor), - )) + fontSize: 16.0, + fontFamily: 'Lato', + fontWeight: FontWeight.normal, + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ), + ), + ) ], ), ); diff --git a/lib/view_model/cake_pay/cake_pay_purchase_view_model.dart b/lib/view_model/cake_pay/cake_pay_purchase_view_model.dart index a580db054..f95f9e2b7 100644 --- a/lib/view_model/cake_pay/cake_pay_purchase_view_model.dart +++ b/lib/view_model/cake_pay/cake_pay_purchase_view_model.dart @@ -49,6 +49,13 @@ abstract class CakePayPurchaseViewModelBase with Store { String get fiatCurrency => paymentCredential.fiatCurrency; + bool confirmsNoVpn = false; + bool confirmsVoidedRefund = false; + bool confirmsTermsAgreed = false; + + @observable + bool isPurchasing = false; + CryptoPaymentData? get cryptoPaymentData { if (order == null) return null; @@ -86,9 +93,13 @@ abstract class CakePayPurchaseViewModelBase with Store { } try { order = await cakePayService.createOrder( - cardId: card.id, - price: paymentCredential.amount.toString(), - quantity: paymentCredential.quantity); + cardId: card.id, + price: paymentCredential.amount.toString(), + quantity: paymentCredential.quantity, + confirmsNoVpn: confirmsNoVpn, + confirmsVoidedRefund: confirmsVoidedRefund, + confirmsTermsAgreed: confirmsTermsAgreed, + ); await confirmSending(); expirationTime = order!.paymentData.expirationTime; updateRemainingTime(); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 97e18a9b3..b9b643804 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "بطاقات Cake Pay Web", "cake_seeds_save_disclaimer": "يرجى حفظ هذه الكلمات في مكان آمن! ستحتاج إلى هذه الكلمات لاستعادة محفظتك على جهاز جديد.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "أؤكد أنني لا أستخدم وكيلًا أو VPN", + "cakepay_confirm_purchase": "تأكيد الشراء", + "cakepay_confirm_terms_agreed": "أوافق على الشروط والأحكام المقدمة هنا:", + "cakepay_confirm_voided_refund": "أفهم أن محاولات الفداء من بلد محظور سوف تبطل أي استرداد", "cakepay_ios_not_available": "آسف ، بطاقة الهدايا هذه غير متوفرة على iOS. يمكنك شرائه على Android أو من خلال موقعنا بدلاً من ذلك.", "cakepay_prepaid_card": "بطاقة ائتمان CakePay مسبقة الدفع", "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 73a310ae7..650480044 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Онлайн Карти", "cake_seeds_save_disclaimer": "Моля, запазете тези думи на сигурно място! Ще ви трябват тези думи, за да възстановите портфейла си на ново устройство.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Потвърждавам, че не използвам прокси или VPN", + "cakepay_confirm_purchase": "Потвърдете покупката", + "cakepay_confirm_terms_agreed": "Съгласен съм с условията, представени тук:", + "cakepay_confirm_voided_refund": "Разбирам, че опитите за обратно изкупуване от ограничена държава ще анулират всяко възстановяване", "cakepay_ios_not_available": "За съжаление тази карта за подарък не се предлага в iOS. Можете да го закупите на Android или чрез нашия уебсайт вместо това.", "cakepay_prepaid_card": "CakePay предплатена дебитна карта", "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 67c1e6901..9f5897046 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay webové karty", "cake_seeds_save_disclaimer": "Uložte tato slova na bezpečném místě! Tato slova budete potřebovat k obnovení peněženky na novém zařízení.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Potvrzuji, že nepoužívám proxy nebo VPN", + "cakepay_confirm_purchase": "Potvrďte nákup", + "cakepay_confirm_terms_agreed": "Souhlasím s zde uvedenými podmínkami:", + "cakepay_confirm_voided_refund": "Chápu, že pokusy o vykoupení z omezené země zruší jakékoli vrácení peněz", "cakepay_ios_not_available": "Je nám líto, tato dárková karta není k dispozici na iOS. Místo toho si jej můžete zakoupit na Androidu nebo prostřednictvím našeho webu.", "cakepay_prepaid_card": "CakePay předplacená debetní karta", "camera_consent": "Váš fotoaparát použije k pořízení snímku pro účely identifikace ${provider}. Podrobnosti najdete v jejich Zásadách ochrany osobních údajů.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 604c50500..227e84d21 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay-Webkarten", "cake_seeds_save_disclaimer": "Bitte speichern Sie diese Wörter an einem sicheren Ort! Sie benötigen diese Wörter, um Ihre Brieftasche auf einem neuen Gerät wiederherzustellen.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Ich bestätige, dass ich keinen Proxy oder VPN benutze", + "cakepay_confirm_purchase": "Kauf bestätigen", + "cakepay_confirm_terms_agreed": "Ich stimme den hier vorgestellten Bedingungen zu:", + "cakepay_confirm_voided_refund": "Ich verstehe", "cakepay_ios_not_available": "Entschuldigung, diese Geschenkkarte ist auf iOS nicht erhältlich. Sie können es stattdessen auf Android oder über unsere Website kaufen.", "cakepay_prepaid_card": "CakePay-Prepaid-Debitkarte", "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3b7e97801..3d1255ce2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Cards", "cake_seeds_save_disclaimer": "Please save these words in a secure place! You will need these words to restore your wallet on a new device.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "I confirm I am not using a Proxy or VPN", + "cakepay_confirm_purchase": "Confirm Purchase", + "cakepay_confirm_terms_agreed": "I agree to the terms and conditions presented here:", + "cakepay_confirm_voided_refund": "I understand redemption attempts from a restricted country will void any refund", "cakepay_ios_not_available": "Sorry, this gift card is not available on iOS. You can purchase it on Android or through our website instead.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 52bc670ce..797cecdd0 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", "cake_seeds_save_disclaimer": "¡Guarde estas palabras en un lugar seguro! Necesitará estas palabras para restaurar su billetera en un nuevo dispositivo.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Confirmo que no estoy usando un proxy o VPN", + "cakepay_confirm_purchase": "Confirmar la compra", + "cakepay_confirm_terms_agreed": "Estoy de acuerdo con los términos y condiciones presentados aquí:", + "cakepay_confirm_voided_refund": "Entiendo que los intentos de redención de un país restringido anularán cualquier reembolso", "cakepay_ios_not_available": "Lo siento, esta tarjeta de regalo no está disponible en iOS. Puede comprarlo en Android o a través de nuestro sitio web.", "cakepay_prepaid_card": "Tarjeta de Débito Prepago CakePay", "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulta tu Política de privacidad para obtener más detalles.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index c1ef104fc..6a775a4f4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cartes Web Cake Pay", "cake_seeds_save_disclaimer": "Veuillez enregistrer ces mots dans un endroit sécurisé! Vous aurez besoin de ces mots pour restaurer votre portefeuille sur un nouvel appareil.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Je confirme que je n'utilise pas de proxy ou de VPN", + "cakepay_confirm_purchase": "Confirmer l'achat", + "cakepay_confirm_terms_agreed": "J'accepte les termes et conditions présentés ici:", + "cakepay_confirm_voided_refund": "Je comprends que les tentatives de rachat d'un pays restreint annulent tout remboursement", "cakepay_ios_not_available": "Désolé, cette carte-cadeau n'est pas disponible sur iOS. Vous pouvez l'acheter sur Android ou via notre site Web à la place.", "cakepay_prepaid_card": "Carte de débit prépayée Cake Pay", "camera_consent": "Votre appareil photo sera utilisé pour capturer une image à des fins d'identification par ${provider}. Veuillez consulter leur politique de confidentialité pour plus de détails.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 02cebd0fb..364c8a796 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Cards", "cake_seeds_save_disclaimer": "Da fatan za a ceci waɗannan kalmomin a cikin amintaccen wuri! Kuna buƙatar waɗannan kalmomin don dawo da walat ɗinku a kan sabon na'ura.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Na tabbatar ba na amfani da wakili ko VPN", + "cakepay_confirm_purchase": "Tabbatar da sayan", + "cakepay_confirm_terms_agreed": "Na yarda da sharuɗɗan da sharuɗɗan da aka gabatar anan:", + "cakepay_confirm_voided_refund": "Na fahimci fansa daga ƙasar da aka ƙuntata ba za ta yi amfani da wani maida ba", "cakepay_ios_not_available": "Yi haƙuri, wannan katin kyautar ba a samuwa akan iOS. Kuna iya sayan shi a kan Android ko ta yanar gizo a maimakon.", "cakepay_prepaid_card": "Katin zare kudi na CakePay", "camera_consent": "Za a yi amfani da kyamarar ku don ɗaukar hoto don dalilai na tantancewa ta ${provider}. Da fatan za a duba Manufar Sirri don cikakkun bayanai.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 973cc5521..03fc08134 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", "cake_seeds_save_disclaimer": "कृपया इन शब्दों को सुरक्षित स्थान पर सहेजें! एक नए डिवाइस पर अपने बटुए को पुनर्स्थापित करने के लिए आपको इन शब्दों की आवश्यकता होगी।", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "मैं पुष्टि करता हूं कि मैं एक प्रॉक्सी या वीपीएन का उपयोग नहीं कर रहा हूं", + "cakepay_confirm_purchase": "खरीद की पुष्टि करें", + "cakepay_confirm_terms_agreed": "मैं यहां प्रस्तुत नियमों और शर्तों से सहमत हूं:", + "cakepay_confirm_voided_refund": "मैं समझता हूं कि एक प्रतिबंधित देश से मोचन प्रयास किसी भी धनवापसी को शून्य कर देंगे", "cakepay_ios_not_available": "क्षमा करें, यह उपहार कार्ड iOS पर उपलब्ध नहीं है। आप इसे Android पर या हमारी वेबसाइट के बजाय खरीद सकते हैं।", "cakepay_prepaid_card": "केकपे प्रीपेड डेबिट कार्ड", "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e7362ac20..58fef20f9 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web kartice", "cake_seeds_save_disclaimer": "Molimo spremite ove riječi na sigurno mjesto! Trebat će vam ove riječi da biste vratili novčanik na novi uređaj.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Potvrđujem da ne koristim proxy ili vpn", + "cakepay_confirm_purchase": "Potvrdi kupnju", + "cakepay_confirm_terms_agreed": "Slažem se s ovdje predstavljenim uvjetima:", + "cakepay_confirm_voided_refund": "Razumijem da će pokušaji otkupa od ograničene zemlje poništiti bilo koji povrat novca", "cakepay_ios_not_available": "Oprostite, ova poklon kartica nije dostupna na iOS -u. Umjesto toga, možete ga kupiti na Androidu ili putem naše web stranice.", "cakepay_prepaid_card": "CakePay unaprijed plaćena debitna kartica", "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti.", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 38117026d..95da83928 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Վեբ Քարտեր", "cake_seeds_save_disclaimer": "Խնդրում ենք պահպանել այս բառերը անվտանգ տեղում: Ձեզ հարկավոր կլինի այս բառերը `ձեր դրամապանակը նոր սարքում վերականգնելու համար:", "cake_wallet": "Cake Գաղտնապահոց", + "cakepay_confirm_no_vpn": "Ես հաստատում եմ, որ ես չեմ օգտագործում վստահված անձ կամ VPN", + "cakepay_confirm_purchase": "Հաստատեք գնումը", + "cakepay_confirm_terms_agreed": "Ես համաձայն եմ այստեղ ներկայացված պայմաններին.", + "cakepay_confirm_voided_refund": "Ես հասկանում եմ, որ սահմանափակված երկրի մարման փորձերը կվերականգնեն ցանկացած փոխհատուցում", "cakepay_ios_not_available": "Ներեցեք, այս նվեր քարտը հասանելի չէ iOS- ում: Փոխարենը կարող եք այն գնել Android- ում կամ մեր կայքում:", "cakepay_prepaid_card": "CakePay Նախավճարային Դեբետային Քարտ", "camera_consent": "Ձեր տեսախցիկը կօգտագործվի ${provider}-ի կողմից ինքնությունը հաստատելու նպատակով: Խնդրում ենք ծանոթանալ նրանց Գաղտնիության Քաղաքականության հետ:", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 56033231d..c275a70df 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Kartu Web Cake Pay", "cake_seeds_save_disclaimer": "Harap simpan kata -kata ini di tempat yang aman! Anda akan membutuhkan kata -kata ini untuk mengembalikan dompet Anda pada perangkat baru.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Saya mengkonfirmasi saya tidak menggunakan proxy atau vpn", + "cakepay_confirm_purchase": "Konfirmasi pembelian", + "cakepay_confirm_terms_agreed": "Saya setuju dengan syarat dan ketentuan yang disajikan di sini:", + "cakepay_confirm_voided_refund": "Saya mengerti upaya penebusan dari negara terbatas akan membatalkan pengembalian dana", "cakepay_ios_not_available": "Maaf, kartu hadiah ini tidak tersedia di iOS. Anda dapat membelinya di Android atau melalui situs web kami sebagai gantinya.", "cakepay_prepaid_card": "Kartu Debit Prabayar CakePay", "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0f0816fdb..2d3561144 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Carte Web Cake Pay", "cake_seeds_save_disclaimer": "Si prega di salvare queste parole in un posto sicuro! Avrai bisogno di queste parole per ripristinare il portafoglio su un nuovo dispositivo.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Conferma che non sto usando un proxy o una VPN", + "cakepay_confirm_purchase": "Conferma l'acquisto", + "cakepay_confirm_terms_agreed": "Accetto i termini e le condizioni presentati qui:", + "cakepay_confirm_voided_refund": "Capisco che i tentativi di rimborso da un paese limitato annullano qualsiasi rimborso", "cakepay_ios_not_available": "Mi dispiace, questa carta regalo non è disponibile su iOS. Puoi acquistarlo su Android o tramite il nostro sito Web.", "cakepay_prepaid_card": "Carta di debito prepagata CakePay", "camera_consent": "La tua fotocamera verrà utilizzata per acquisire un'immagine a scopo identificativo da ${provider}. Si prega di controllare la loro Informativa sulla privacy per i dettagli.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f7c95a044..6c0a8f8f3 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay ウェブカード", "cake_seeds_save_disclaimer": "これらの言葉を安全な場所に保存してください!新しいデバイスで財布を復元するには、これらの単語が必要です。", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "私はプロキシまたはVPNを使用していないことを確認します", + "cakepay_confirm_purchase": "購入を確認します", + "cakepay_confirm_terms_agreed": "ここに提示されている条件に同意します。", + "cakepay_confirm_voided_refund": "制限された国からの償還の試みが払い戻しを無効にすることを理解しています", "cakepay_ios_not_available": "申し訳ありませんが、このギフトカードはiOSでは利用できません。代わりにAndroidまたは当社のWebサイトから購入できます。", "cakepay_prepaid_card": "CakePayプリペイドデビットカード", "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index f02757a27..2f1684b5a 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "케이크페이 웹카드", "cake_seeds_save_disclaimer": "이 단어를 안전한 장소에 저장하십시오! 새 장치에서 지갑을 복원하려면이 단어가 필요합니다.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "프록시 나 VPN을 사용하지 않는지 확인합니다.", + "cakepay_confirm_purchase": "구매 확인", + "cakepay_confirm_terms_agreed": "여기에 제시된 이용 약관에 동의합니다.", + "cakepay_confirm_voided_refund": "제한된 국가의 상환 시도는 환불을 무효화한다는 것을 이해합니다.", "cakepay_ios_not_available": "죄송합니다.이 기프트 카드는 iOS에서 사용할 수 없습니다. Android 또는 웹 사이트를 통해 구매할 수 있습니다.", "cakepay_prepaid_card": "CakePay 선불 직불 카드", "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index dbc01c728..ed5e91fce 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay ဝဘ်ကတ်များ", "cake_seeds_save_disclaimer": "ကျေးဇူးပြုပြီးဒီစကားလုံးတွေကိုလုံခြုံတဲ့နေရာမှာသိမ်းထားပါ။ သင်၏ပိုက်ဆံအိတ်ကိုကိရိယာအသစ်တစ်ခုတွင်သင်၏ပိုက်ဆံအိတ်ကိုပြန်လည်ရယူရန်ဤစကားလုံးများကိုသင်လိုအပ်လိမ့်မည်။", "cake_wallet": "Cake ပိုက်ဆံအိတ်", + "cakepay_confirm_no_vpn": "ငါ proxy သို့မဟုတ် vpn ကိုမသုံးပါ", + "cakepay_confirm_purchase": "ဝယ်ယူမှုအတည်ပြုပါ", + "cakepay_confirm_terms_agreed": "ဒီမှာတင်ပြထားတဲ့စည်းကမ်းချက်များကိုငါသဘောတူတယ်။", + "cakepay_confirm_voided_refund": "ကန့်သတ်ထားသောနိုင်ငံမှရွေးနုတ်ခြင်းကြိုးပမ်းမှုများကိုကျွန်ုပ်နားလည်ပါသည်", "cakepay_ios_not_available": "တောင်းပန်ပါတယ်, ဒီလက်ဆောင်ကဒ်ကို iOS မှာမရနိုင်ပါ။ ၎င်းကို Android တွင်သို့မဟုတ်ကျွန်ုပ်တို့၏ဝက်ဘ်ဆိုက်တွင် 0 ယ်နိုင်သည်။", "cakepay_prepaid_card": "CakePay ကြိုတင်ငွေဖြည့်ဒက်ဘစ်ကတ်", "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 101592be7..bc3106b28 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay-webkaarten", "cake_seeds_save_disclaimer": "Bewaar deze woorden op een veilige plek! U hebt deze woorden nodig om uw portemonnee op een nieuw apparaat te herstellen.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Ik bevestig dat ik geen proxy of VPN gebruik", + "cakepay_confirm_purchase": "Bevestig aankoop", + "cakepay_confirm_terms_agreed": "Ik ga akkoord met de hier gepresenteerde algemene voorwaarden:", + "cakepay_confirm_voided_refund": "Ik begrijp dat de aflossingspogingen van een beperkt land elke terugbetaling zullen ongeldig maken", "cakepay_ios_not_available": "Sorry, deze cadeaubon is niet beschikbaar op iOS. U kunt het in plaats daarvan kopen op Android of via onze website.", "cakepay_prepaid_card": "CakePay Prepaid Debetkaart", "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index ce243fee7..947b1bc6e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Cards", "cake_seeds_save_disclaimer": "Zapisz te słowa w bezpiecznym miejscu! Będziesz potrzebować tych słów, aby przywrócić portfel na nowym urządzeniu.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Potwierdzam, że nie używam proxy ani VPN", + "cakepay_confirm_purchase": "Potwierdź zakup", + "cakepay_confirm_terms_agreed": "Zgadzam się na przedstawione tutaj warunki:", + "cakepay_confirm_voided_refund": "Rozumiem, że próby odkupienia z ograniczonego kraju nie unieważają wszelkich", "cakepay_ios_not_available": "Przepraszam, ta karta podarunkowa nie jest dostępna na iOS. Zamiast tego możesz go kupić na Android lub za pośrednictwem naszej strony internetowej.", "cakepay_prepaid_card": "Przedpłacona karta debetowa CakePay", "camera_consent": "Twój aparat zostanie użyty do przechwycenia obrazu w celach identyfikacyjnych przez ${provider}. Aby uzyskać szczegółowe informacje, sprawdź ich Politykę prywatności.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 07dd9ac97..87ecf3f23 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cartões Cake Pay Web", "cake_seeds_save_disclaimer": "Por favor, salve estas palavras em um local seguro! Você precisará dessas palavras para restaurar sua carteira em um novo dispositivo.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Eu confirmo que não estou usando um proxy ou VPN", + "cakepay_confirm_purchase": "Confirme a compra", + "cakepay_confirm_terms_agreed": "Eu concordo com os termos e condições apresentados aqui:", + "cakepay_confirm_voided_refund": "Eu entendo que as tentativas de resgate de um país restrito anularão qualquer reembolso", "cakepay_ios_not_available": "Desculpe, este cartão -presente não está disponível no iOS. Você pode comprá -lo no Android ou através do nosso site.", "cakepay_prepaid_card": "Cartão de débito pré-pago CakePay", "camera_consent": "Sua câmera será usada para capturar uma imagem para fins de identificação por ${provider}. Por favor, verifique a Política de Privacidade para obter detalhes.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 95596a17c..8993f6b29 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Веб-карты Cake Pay", "cake_seeds_save_disclaimer": "Пожалуйста, сохраните эти слова в безопасном месте! Вам понадобятся эти слова, чтобы восстановить свой кошелек на новом устройстве.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Я подтверждаю, что не использую прокси или VPN", + "cakepay_confirm_purchase": "Подтвердите покупку", + "cakepay_confirm_terms_agreed": "Я согласен с условиями, представленными здесь:", + "cakepay_confirm_voided_refund": "Я понимаю, что попытки выкупа из ограниченной страны будут аннулировать любые возмещение", "cakepay_ios_not_available": "Извините, эта подарочная карта недоступна на iOS. Вместо этого вы можете приобрести его на Android или через наш веб -сайт.", "cakepay_prepaid_card": "Предоплаченная дебетовая карта CakePay", "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0f0069057..7db703fc2 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Cards", "cake_seeds_save_disclaimer": "โปรดบันทึกคำเหล่านี้ในสถานที่ที่ปลอดภัย! คุณจะต้องใช้คำเหล่านี้เพื่อกู้คืนกระเป๋าเงินของคุณในอุปกรณ์ใหม่", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "ฉันยืนยันว่าฉันไม่ได้ใช้พร็อกซีหรือ VPN", + "cakepay_confirm_purchase": "ยืนยันการซื้อ", + "cakepay_confirm_terms_agreed": "ฉันเห็นด้วยกับข้อกำหนดและเงื่อนไขที่นำเสนอที่นี่:", + "cakepay_confirm_voided_refund": "ฉันเข้าใจความพยายามในการไถ่ถอนจากประเทศที่ถูก จำกัด จะทำให้คืนเงินใด ๆ", "cakepay_ios_not_available": "ขออภัยบัตรของขวัญนี้ไม่มีใน iOS คุณสามารถซื้อได้บน Android หรือผ่านเว็บไซต์ของเราแทน", "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 2c47c4713..6945d088b 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Cards", "cake_seeds_save_disclaimer": "Mangyaring i -save ang mga salitang ito sa isang ligtas na lugar! Kakailanganin mo ang mga salitang ito upang maibalik ang iyong pitaka sa isang bagong aparato.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Kinukumpirma kong hindi ako gumagamit ng isang proxy o vpn", + "cakepay_confirm_purchase": "Kumpirmahin ang pagbili", + "cakepay_confirm_terms_agreed": "Sumasang -ayon ako sa mga termino at kundisyon na ipinakita dito:", + "cakepay_confirm_voided_refund": "Naiintindihan ko ang mga pagtatangka sa pagtubos mula sa isang pinigilan na bansa ay walang bisa sa anumang refund", "cakepay_ios_not_available": "Paumanhin, ang gift card na ito ay hindi magagamit sa iOS. Maaari mo itong bilhin sa Android o sa pamamagitan ng aming website sa halip.", "cakepay_prepaid_card": "CakePay Prepaid Debit Card", "camera_consent": "Gagamitin ang iyong camera upang kumuha ng larawan para sa mga layunin ng pagkakakilanlan sa pamamagitan ng ${provider}. Pakisuri ang kanilang Patakaran sa Privacy para sa mga detalye.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f3a8b6362..51b0dd18d 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake Pay Web Kartları", "cake_seeds_save_disclaimer": "Lütfen bu kelimeleri güvenli bir yerde kaydedin! Cüzdanınızı yeni bir cihazda geri yüklemek için bu kelimelere ihtiyacınız olacak.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Bir proxy veya vpn kullanmadığımı onaylıyorum", + "cakepay_confirm_purchase": "Satın Alma Onay", + "cakepay_confirm_terms_agreed": "Burada sunulan şartlar ve koşulları kabul ediyorum:", + "cakepay_confirm_voided_refund": "Kısıtlı bir ülkeden kurtuluş girişimlerinin herhangi bir geri ödemeyi geçersiz kılacağını anlıyorum", "cakepay_ios_not_available": "Üzgünüm, bu hediye kartı iOS'ta mevcut değil. Bunun yerine Android'de veya web sitemizden satın alabilirsiniz.", "cakepay_prepaid_card": "CakePay Ön Ödemeli Kart", "camera_consent": "Kameranız ${provider} tarihine kadar tanımlama amacıyla bir görüntü yakalamak için kullanılacaktır. Ayrıntılar için lütfen Gizlilik Politikalarını kontrol edin.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 4d0a9fc1d..f591a8e06 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Веб-картки Cake Pay", "cake_seeds_save_disclaimer": "Збережіть ці слова в безпечному місці! Вам знадобляться ці слова, щоб відновити гаманець на новому пристрої.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Я підтверджую, що не використовую проксі або VPN", + "cakepay_confirm_purchase": "Підтвердьте покупку", + "cakepay_confirm_terms_agreed": "Я погоджуюся з представленими тут умовами та умовами:", + "cakepay_confirm_voided_refund": "Я розумію, що спроби викупу з обмеженої країни пошкодять будь -яке повернення коштів", "cakepay_ios_not_available": "Вибачте, ця подарункова карта недоступна на iOS. Ви можете придбати його на Android або через наш веб -сайт.", "cakepay_prepaid_card": "Передплачена дебетова картка CakePay", "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 6cbbd2a9f..372f875ea 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Cake پے ویب کارڈز", "cake_seeds_save_disclaimer": "براہ کرم ان الفاظ کو ایک محفوظ جگہ پر محفوظ کریں! اپنے بٹوے کو کسی نئے آلے پر بحال کرنے کے ل You آپ کو ان الفاظ کی ضرورت ہوگی۔", "cake_wallet": "Cake والیٹ", + "cakepay_confirm_no_vpn": "میں تصدیق کرتا ہوں کہ میں پراکسی یا وی پی این استعمال نہیں کر رہا ہوں", + "cakepay_confirm_purchase": "خریداری کی تصدیق کریں", + "cakepay_confirm_terms_agreed": "میں یہاں پیش کردہ شرائط و ضوابط سے اتفاق کرتا ہوں:", + "cakepay_confirm_voided_refund": "میں سمجھتا ہوں کہ کسی محدود ملک سے چھٹکارے کی کوششیں کسی بھی رقم کی واپسی کو کالعدم کردیں گی", "cakepay_ios_not_available": "معذرت ، یہ گفٹ کارڈ iOS پر دستیاب نہیں ہے۔ اس کے بجائے آپ اسے اینڈروئیڈ پر یا ہماری ویب سائٹ کے ذریعے خرید سکتے ہیں۔", "cakepay_prepaid_card": "Cake پے پری پیڈ ڈیبٹ کارڈ", "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 09371db98..74cc9c3af 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Thẻ Cake Pay Web", "cake_seeds_save_disclaimer": "Vui lòng lưu những từ này ở một nơi an toàn! Bạn sẽ cần những từ này để khôi phục ví của bạn trên một thiết bị mới.", "cake_wallet": "Ví Cake", + "cakepay_confirm_no_vpn": "Tôi xác nhận tôi không sử dụng proxy hoặc VPN", + "cakepay_confirm_purchase": "Xác nhận mua hàng", + "cakepay_confirm_terms_agreed": "Tôi đồng ý với các điều khoản và điều kiện được trình bày ở đây:", + "cakepay_confirm_voided_refund": "Tôi hiểu những nỗ lực cứu chuộc từ một quốc gia bị hạn chế sẽ vô hiệu hóa bất kỳ khoản hoàn trả nào", "cakepay_ios_not_available": "Xin lỗi, thẻ quà tặng này không có sẵn trên iOS. Thay vào đó, bạn có thể mua nó trên Android hoặc thông qua trang web của chúng tôi.", "cakepay_prepaid_card": "Thẻ Ghi Nợ Trả Trước CakePay", "camera_consent": "Máy ảnh của bạn sẽ được sử dụng để chụp hình nhằm mục đích xác minh danh tính bởi ${provider}. Vui lòng kiểm tra Chính sách quyền riêng tư của họ để biết thêm chi tiết.", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 5becf208e..4131d4211 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "Àwọn káàdì wẹ́ẹ̀bù ti Cake Pay", "cake_seeds_save_disclaimer": "Jọwọ fi awọn ọrọ wọnyi pamọ ni aaye aabo! Iwọ yoo nilo awọn ọrọ wọnyi lati mu pada apamọwọ rẹ sori ẹrọ tuntun.", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "Mo jẹrisi pe Emi ko lo aṣoju tabi VPN", + "cakepay_confirm_purchase": "Jẹrisi rira", + "cakepay_confirm_terms_agreed": "Mo gba si awọn ofin ati ipo ti a ṣafihan nibi:", + "cakepay_confirm_voided_refund": "Mo ye awọn igbiyanju irapada lati orilẹ-ede ihamọ kan yoo di agbapada eyikeyi", "cakepay_ios_not_available": "Ma binu, kaadi ẹbun yii ko wa lori iOS. O le ra lori Android tabi nipasẹ oju opo wẹẹbu wa dipo.", "cakepay_prepaid_card": "Káàdì ìrajà ti CakePay", "camera_consent": "Kamẹra rẹ yoo ṣee lo lati ya aworan kan fun awọn idi idanimọ nipasẹ ${provider}. Jọwọ ṣayẹwo Ilana Aṣiri wọn fun awọn alaye.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 2c28f07d3..797aee624 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -103,6 +103,10 @@ "cake_pay_web_cards_title": "蛋糕支付网络卡", "cake_seeds_save_disclaimer": "请在安全的地方保存这些单词!您将需要这些单词来恢复新设备上的钱包。", "cake_wallet": "Cake Wallet", + "cakepay_confirm_no_vpn": "我确认我不使用代理或VPN", + "cakepay_confirm_purchase": "确认购买", + "cakepay_confirm_terms_agreed": "我同意此处介绍的条款和条件:", + "cakepay_confirm_voided_refund": "我了解限制国家的赎回尝试将使任何退款无效", "cakepay_ios_not_available": "抱歉,这张礼品卡在iOS上不可用。您可以在Android或通过我们的网站上购买它。", "cakepay_prepaid_card": "CakePay 预付借记卡", "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", From d55e635f61c2f91798bc0c19fd31ffc0e813774b Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 14 Dec 2024 02:37:48 +0200 Subject: [PATCH 25/26] Cw 853 mweb utxos are not displayed in coin control screen (#1873) * fix displaying mweb utxos * fallback for failed electrum UTXO updates * remove throwing uncaught exception and un needed try/catch --------- Co-authored-by: OmarHatem --- cw_bitcoin/lib/electrum.dart | 24 +++---- cw_bitcoin/lib/electrum_wallet.dart | 68 +++++++++---------- .../unspent_coins_list_page.dart | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 28e3f47be..4fc4c1ad8 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -235,21 +235,21 @@ class ElectrumClient { return []; }); - Future>> getListUnspent(String scriptHash) => - call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]) - .then((dynamic result) { - if (result is List) { - return result.map((dynamic val) { - if (val is Map) { - return val; - } + Future>> getListUnspent(String scriptHash) async { + final result = await call(method: 'blockchain.scripthash.listunspent', params: [scriptHash]); - return {}; - }).toList(); + if (result is List) { + return result.map((dynamic val) { + if (val is Map) { + return val; } - return []; - }); + return {}; + }).toList(); + } + + return []; + } Future>> getMempool(String scriptHash) => call(method: 'blockchain.scripthash.get_mempool', params: [scriptHash]) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index a5bb9c655..d9041cba4 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -1382,8 +1382,9 @@ abstract class ElectrumWalletBase })); unspentCoins = updatedUnspentCoins; - - final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); + + final currentWalletUnspentCoins = + unspentCoinsInfo.values.where((element) => element.walletId == id); if (currentWalletUnspentCoins.length != updatedUnspentCoins.length) { unspentCoins.forEach((coin) => addCoinInfo(coin)); @@ -1450,10 +1451,9 @@ abstract class ElectrumWalletBase @action Future addCoinInfo(BitcoinUnspent coin) async { - // Check if the coin is already in the unspentCoinsInfo for the wallet - final existingCoinInfo = unspentCoinsInfo.values.firstWhereOrNull( - (element) => element.walletId == walletInfo.id && element == coin); + final existingCoinInfo = unspentCoinsInfo.values + .firstWhereOrNull((element) => element.walletId == walletInfo.id && element == coin); if (existingCoinInfo == null) { final newInfo = UnspentCoinsInfo( @@ -1475,19 +1475,18 @@ abstract class ElectrumWalletBase Future _refreshUnspentCoinsInfo() async { try { - final List keys = []; + final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + unspentCoinsInfo.values.where((record) => record.walletId == id); - if (currentWalletUnspentCoins.isNotEmpty) { - currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins - .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout); + for (final element in currentWalletUnspentCoins) { + if (RegexUtils.addressTypeFromStr(element.address, network) is MwebAddress) continue; - if (existUnspentCoins.isEmpty) { - keys.add(element.key); - } - }); + final existUnspentCoins = unspentCoins.where((coin) => element == coin); + + if (existUnspentCoins.isEmpty) { + keys.add(element.key); + } } if (keys.isNotEmpty) { @@ -1499,7 +1498,8 @@ abstract class ElectrumWalletBase } Future cleanUpDuplicateUnspentCoins() async { - final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => element.walletId == id); + final currentWalletUnspentCoins = + unspentCoinsInfo.values.where((element) => element.walletId == id); final Map uniqueUnspentCoins = {}; final List duplicateKeys = []; @@ -1535,7 +1535,8 @@ abstract class ElectrumWalletBase final ownAddresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); final receiverAmount = outputs - .where((output) => !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) + .where((output) => + !ownAddresses.contains(addressFromOutputScript(output.scriptPubKey, network))) .fold(0, (sum, output) => sum + output.amount.toInt()); if (receiverAmount == 0) { @@ -1584,7 +1585,7 @@ abstract class ElectrumWalletBase allInputsAmount += outTransaction.amount.toInt(); final addressRecord = - walletAddresses.allAddresses.firstWhere((element) => element.address == address); + walletAddresses.allAddresses.firstWhere((element) => element.address == address); final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network); final privkey = generateECPrivate( hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, @@ -1602,7 +1603,7 @@ abstract class ElectrumWalletBase scriptType: _getScriptType(btcAddress), ), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), ), ); } @@ -1630,7 +1631,7 @@ abstract class ElectrumWalletBase // Calculate the total amount and fees int totalOutAmount = - outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); + outputs.fold(0, (previousValue, output) => previousValue + output.value.toInt()); int currentFee = allInputsAmount - totalOutAmount; int remainingFee = newFee - currentFee; @@ -1686,7 +1687,7 @@ abstract class ElectrumWalletBase vout: utxo.vout, scriptType: _getScriptType(address)), ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), )); allInputsAmount += utxo.value; @@ -1743,11 +1744,11 @@ abstract class ElectrumWalletBase final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden); final List changeOutputs = outputs .where((output) => changeAddresses - .any((element) => element.address == output.address.toAddress(network))) + .any((element) => element.address == output.address.toAddress(network))) .toList(); int totalChangeAmount = - changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); + changeOutputs.fold(0, (sum, output) => sum + output.value.toInt()); // The final amount that the receiver will receive int sendingAmount = allInputsAmount - newFee - totalChangeAmount; @@ -1764,7 +1765,7 @@ abstract class ElectrumWalletBase final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = - privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); if (key == null) { throw Exception("Cannot find private key"); } @@ -1774,7 +1775,6 @@ abstract class ElectrumWalletBase } else { return key.signInput(txDigest, sigHash: sighash); } - }); return PendingBitcoinTransaction( @@ -1787,16 +1787,16 @@ abstract class ElectrumWalletBase hasChange: changeOutputs.isNotEmpty, feeRate: newFee.toString(), )..addListener((transaction) async { - transactionHistory.transactions.values.forEach((tx) { - if (tx.id == hash) { - tx.isReplaced = true; - tx.isPending = false; - transactionHistory.addOne(tx); - } + transactionHistory.transactions.values.forEach((tx) { + if (tx.id == hash) { + tx.isReplaced = true; + tx.isPending = false; + transactionHistory.addOne(tx); + } + }); + transactionHistory.addOne(transaction); + await updateBalance(); }); - transactionHistory.addOne(transaction); - await updateBalance(); - }); } catch (e) { throw e; } diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index f26a2a17f..d44107939 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -154,7 +154,7 @@ class UnspentCoinsListFormState extends State { SizedBox(height: 15), Expanded( child: unspentCoinsListViewModel.items.isEmpty - ? Center(child: Text('No unspent coins available\ntry to reconnect',textAlign: TextAlign.center)) + ? Center(child: Text('No unspent coins available',textAlign: TextAlign.center)) : ListView.separated( itemCount: unspentCoinsListViewModel.items.length, separatorBuilder: (_, __) => SizedBox(height: 15), From ae80fb3b55132a6e3e5a550718987b2d113739af Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Sat, 14 Dec 2024 01:55:49 +0100 Subject: [PATCH 26/26] CW-774: Enforce Seed Verification (#1874) * feat: Switch UI for seeds display * feat: Add localization for disclaimer text * fix: Modify color for warning on seeds screen * Fix: Adjust UI styling for seed page * chore: Revert podfile.lock * Fix column colors * Fix more colors * Fix more colors and update strings * feat: Enforce Seed Verification Implementation * fix: Error extracting seed words in Japanese because of spacing type used * fix: Modify styling for copy image button * fix: Add back button to the seed page and adjust styling to seed verification question text * Update seed verification image [skip ci] * Update description text weight [skip ci] * Make seed page wider * Seed page changes --------- Co-authored-by: tuxpizza Co-authored-by: Omar Hatem --- assets/images/seed_verified.png | Bin 0 -> 24167 bytes lib/di.dart | 3 + lib/router.dart | 7 + lib/routes.dart | 1 + lib/src/screens/seed/pre_seed_page.dart | 2 +- .../seed_verification_page.dart | 35 +++++ .../seed_verification_step_view.dart | 135 ++++++++++++++++++ .../seed_verification_success_view.dart | 74 ++++++++++ lib/src/screens/seed/wallet_seed_page.dart | 118 ++++++--------- lib/utils/feature_flag.dart | 1 + lib/view_model/wallet_seed_view_model.dart | 95 +++++++++++- res/values/strings_ar.arb | 9 ++ res/values/strings_bg.arb | 9 ++ res/values/strings_cs.arb | 9 ++ res/values/strings_de.arb | 9 ++ res/values/strings_en.arb | 9 ++ res/values/strings_es.arb | 9 ++ res/values/strings_fr.arb | 9 ++ res/values/strings_ha.arb | 9 ++ res/values/strings_hi.arb | 9 ++ res/values/strings_hr.arb | 9 ++ res/values/strings_hy.arb | 9 ++ res/values/strings_id.arb | 9 ++ res/values/strings_it.arb | 9 ++ res/values/strings_ja.arb | 9 ++ res/values/strings_ko.arb | 9 ++ res/values/strings_my.arb | 9 ++ res/values/strings_nl.arb | 9 ++ res/values/strings_pl.arb | 9 ++ res/values/strings_pt.arb | 9 ++ res/values/strings_ru.arb | 9 ++ res/values/strings_th.arb | 9 ++ res/values/strings_tl.arb | 9 ++ res/values/strings_tr.arb | 9 ++ res/values/strings_uk.arb | 9 ++ res/values/strings_ur.arb | 9 ++ res/values/strings_vi.arb | 9 ++ res/values/strings_yo.arb | 9 ++ res/values/strings_zh.arb | 9 ++ 39 files changed, 647 insertions(+), 76 deletions(-) create mode 100644 assets/images/seed_verified.png create mode 100644 lib/src/screens/seed/seed_verification/seed_verification_page.dart create mode 100644 lib/src/screens/seed/seed_verification/seed_verification_step_view.dart create mode 100644 lib/src/screens/seed/seed_verification/seed_verification_success_view.dart diff --git a/assets/images/seed_verified.png b/assets/images/seed_verified.png new file mode 100644 index 0000000000000000000000000000000000000000..e0370619335177ad97881365a078484bb2292cf5 GIT binary patch literal 24167 zcmeFZbx>6C`#-w7EU|P*Nh&Gbh%|__fKrl6BOTJQiwL5mfOLu=NVhadmw?g@0wUeD zuzL@FzMtRk-aB*W&fLH6%rY=L=bZOb@7MD@ulI9!r~Oo!2>&iV2m~ThReAgj1cCs6 zLO^&pz^@bE@hjjL%uVHmCkRA9ar*-XrDf27K+GW3$MU+qX1kfV8Kz37y(7)Mf8UV* zRr$b<`5(F_9C(Pn<1sQo!iPC+@J=k15}@;JV5*;ZsN14eljH3;RTEuZByGPbkRWAEU;wu$-2Kv+34=!z6=5S z1{=N5xV%(-;K|s^l(*Y!?--1xMj#B-jta&H>DU67E?b0p4-y~{4bU@E)-;vd0R4zp z(wMzh6fk)8m6^^Gz6hc|C#p@_=VTkybJ#xGAH50rd6c1l#1kxoMVF=LxqgXhdLr61 zuK3~%ngW^@{tP8&29rl*wr?r_UH_~p#!YF>Y`d!{FiH|eCT%7D89z(~GHbE)ONH3> zYrK@6eH^Y?n_P>Y(sRbu4!|s3JgYYCeg;}X;%XvB8OfPLOeh4-j|f_9lnLJlEJIqb zHZEE`upbXfT?9+UXVR&e_vw}~98d?bgV58@gkW(Xn64&#B74(|fNh2;bV>f307+q^ zMK}pGa-@9~$23lTu~|hr)50M1TMv{O&zp-442bvPv}dy?30!5Tx~4tki~B)!3K~Z! z6}4~Eg5eNv7El^Shy-jVG++$%?F#)fp zb^v={LqB^h?M?o%28ah-CGk%v_2u;6r}#u(9`rb9_ZOz42D}7wzXu3#YfWMF9i9<4~Q2f)s5zS+K;t>gxV|8+Rd@J{T$Ji+>ZQE8tVe|s|k33r8l_~gdx{7m6lZ&OU z5fU#QnXknOv4`QUm|^ZdyPmgopK6+AVf+W(c43E&;*7>S7U+dy)|*O}C2?juIn{n4 z!=(y(MmrM*gb@(|{qTtBf#%vAURzXj(gWYaQ44<45}BvI&6a|(Fgc!-qBp=6cZ5z# zX}E^UACP>DD2wA-U}a3-s)uN|rAQKzxf(2=H&e++q9jd(}_m8ZVfrTMqT0 z~OF*r=88=5;r3#&@geaD%4H1+7QD-_|atWd!b&s81H-1R5#nQBj~ zhZ5QaCIH48TPREbY^emTG5SM#$wrtJ;c8kE?)b8U=aik5Apz~#pwY{Kdu>N0Yg8Ik zNZ1=48M?B-r-Cy;Kw@=$=L0R6|cAUv?~`o+aw=n-yi1|7bs9=!P-}3FdVJmdL^@ku-CC9l0vY z9E{|kw5d$lMTD#e{;4@lT-sOfH`+Fd}{{m4L^yqUK`fF~mrq0n8{^*F)XF>6VQ%c5{7U!ia3NPh7(c;NB=gD|bYn4!}9bphVnEWEX-KS?;b9jh} zx>LsX$=bDJT_&Z(7X;G`GPDg9bN+LED{E10s4;r!cOCwuOJi*AU%G-=CxNFVulD61 zzAFK}vCMbQT}i&81&5 zXmj>S)2(KbX07#dB~c;`-JjC}$V`q`;uB|fSNQm?JNOk^=Vf4=;&_||*w0mx6ESOg>>X3mgklJVj?Za?yTM7{B~gT!%a|JIwF zA3A=T(29o#zJ!5xfC|-W* zC2`>><>1YOiy#3X^Zb;`44DJ>O6pgOtS#76r94X7)}yBYmHR%(0G1UAS@c{dG}#pM z{)RVHa`lKj6w{C!l!vy5W@VQAP#DakKZ8|=t`!j7tc#EF;QxAG5Bl!*MIS(P8oa=B zW@-GqTEC|3CPxO_SgjEzxeHZ^km#Pjc`M)dGaEumBPtul#YW8X_dMBuHbKXb>;Lzv)elB>7(JQSxxL6~XBX_%7BH8^hY?EdG%>H9^)K6k*ErX|))54j&Lgd2zko(v{A~qB;8t1QrKKZz%+x&Rb(%=Rf< z=ut#%#Xw*KS*GFa{s4l#;XvwPnpR%7(ot<$WK(f0%}rgI#1QS%@*c>8DsPJT`gvon z-v9Nq5__bL8GT#IXLCe_R8LC;3JTH;kQ(MjUCECzykzY=P2#I;uG)bLyD~lVZ*j`B z{jA8~Urpm?!NO~{d_0fa{LHCsTE3L)RGai2-wUM#G3h?I%?31JldchWv5Uy&Dec5D z`s>gzVX_Bk$vkDx5q-%8Ja4j+; z9gU0m`VJ7s-7@`zbsWWRs7;g#WUm{v2rq?bVaxSsJ1JjB)bfx(48aGWkN1H+4I#Dv zi7j<>E*W+G&3j}7(j|tQgJ7DCGT(*;iZ>u%Tf-AV_WNY` ztQ(R#pzWeMx4RlB!k4kUWQS&hqk9{=<hUN=}bV{3Wom#8n8JgdT7%J#1e5%R7g* zp8X9A6&9aU=eKZ9v;u2@=&|x20`YYL6CpVB_NiPU*_&DY^zA$^;iF#zfvg1k!A}0x z^O7}L&_~dAz0_*fxJNgmua)(889u53)*-gE+hoN7S(27RVC|m=F~H=^9ouR%j>jjq zs3$!*nT4TZ658orY_io}cwxwq?OE$+)?Ly*e5AAPOxC}R=+D+`6+SWLJw|2g?^;va z59~s1zg4_toz{f0db8?Xa~h}Q(bM?CwRlQomzVfmpm5XX4cXuQlH7Z>H6?)BH+4?u zixDnAU)bm`o@hz(n3f8Kip`kEa^C4WA(|6Bj(o(n+n?1gj|AvBv^HR0QI+ zK7(+bo1vw0Fa;cBgm*N$m5tCo&x20pu>`6613d+bUU?B(g(fab8 zcd6s=Ma4}@z+xni*25lrozN$q`xDxJ;;1V;87VU39|^V0Z*8$5F_x&?O$AMpTL%EX zpN1_%{8M&$2zRp)PNEHh-oJ|kCZPJ6+=wTX%SvKb6z${?%p3Cwe+fXs#DM?t=y`?#Wa#!x&0zfx9eXx*4kC>HwxNqhY#rNf-p=xo2|&2$1%c`6Qd_;5L0->@d??n5(i zK!Q;~0;s){!mR`$=pbv(#U9&9P@;Js<9cM|iTTB*d9!=?Tqv z!2K=|L#SAnL&(RzFJblThu?M!TDM>+sfZ$ux^qfe2iom&{)%5h6x-WhbX_%TShg4A zQw{B}QloFYd==p$yJJQG^7KTP-q!vsa4(&%mYIM8ErZ>|RCUc-Qh`v}v(D_Tzzx@^ z_GNRYxLu}Jwc)bv0?ytvneYw_n$uZwcDbxuJN>M-&IY2*Ey$<^IFl{}+f{9D`pG^0 zcw^H<=U3Iv=g=yl3&h|2BvgrIna#4d@)o1Mkc0gYGzZ5}DiP4a7Q%K(Y^xV7W-}4r z7nM?4(8z`NiV(e_Bb$EVJuB9eiuqnfwPjrp&Hrs-!fKD_MLB-pQ(_CqGL$6@aQg)_ zGJZ3h^LN@am(ToJH`$_|UVdY5ofBy@+ml1v{3^A&roCs%ScT`TxKR90;a3hvgf0?6 zw!fb@jP#yZKu9U^&r2eks|H)u75Zm^4Y=;-=Gk3CzgCEI678P+r*pr-TvoC!v zVhm6+R=@1Vyu+}y+I;u5H9*ZQ1rPv;Iic^3^pzw%d84mV#dGw`qGwZf=SeqduJ1W> zi<7s-TiT+X@9kgutZE-J_|baT8eTYDT{}?i7P|~Ua~yP~;s94Yg%~!}H%>Tg#W%|U z;NA05*o#*!N9uw=>~d_+0L9^cAil^y{c1}yy_LJ$mmKNuZTOFSyAPJ4Xle9Q;Mu~B ztXzzkP1@aorF1aO@jpFvA7PptcG8?4LReV(3XakhnwC<0yq{9aSnJHYYX~k3qlyKp z%7|zX7l?a?vy<>pGyTkoE>o^|nFMC6l>F0XFqId^cpW{VV&a@I@=@9im8PN(TFud5 z01PZj(avL!9EO0TVuztQwp(XJfg{)H6fzfduQ%&mr%z0+Nh_PFQYb+v^ivpcy$qhA z8B|YR=D>o=##<8^ih+o!$<*v{3>wyzf0dv>eib-m222Tpme|TGu`yv+NYrylT=3uV zN445boEPuDX~x#(eZZ&;Yy@s_;z4rdgFH*D3Q4-rFrF&=T^tudVWE!3#O(^*nw$#}AISXfGlUy47{7gY21kMQ;`3Pj8a7gG>lI zpT?MeuL{x|=JiPYx^@gG0NC>hsQgLoj818p61jMjSg35E0~ada+HK#qfqPgLz;D56 z&2EckCHBO}M+fV>Fk#+vjQCo&x;C|FSan_}2XhyHR6D{jEy* z-sQH4_jfqJ456|~&93Wr=?2ikfAU`)i1YYU?p$R(IoeKpX?K(Y>XJ`=1Ypl6(h4<@ zz>Ss$Wc2Uyl00jeDhL;|*HpdbSW8(kqXG~ViQG810B;>Gm#0bV_3;fWC~rs_6I0dp z;Kt|7G!D9x_*xWfdqACdqqA}L>})?_H5JjDI<@`0!#I}L%!mFtHc|_0yYE-Kh@DdNjF z31x;&?@hj0Jm(`pEA8yM4xp0`Uu3+SnQQampOGnQHK6EJig6$MVtb<}0*7d0e{N=| z8m4Kf86S*wXL4XNNfa}lN2DuPAN9neHi}E(19A6^1wVTkR@V)(6;Z=2y+_@BW?PnPgj+Wy7?d*$h>PTC>8LqMDC-y zo61Gnbl+<->NG>|Of^oNG$qJWJg4d}GNiB5==o#l=A{hw+Vz{}dRyqSW)`W9XBXdf zAPTLrp#*5#nmaZqgo%ykmwDCcX1oWK716ayILLzPW}3Pb?J{sgs0YN$ss76%3ByS_ zCyL+V^c#MlRe+F+B~t{d=GSTA=XX-eY1lu;a$C06ncQXW+uNc?{nE#FXPH*$0Ves3 zQ~!fo_Wov&1>DaSaa@@F&3xCD@pOAkQZe?*i_D(&sXqU){Lw+fTbUEl4<)xokbk5x z!?a;i2Vc!%9<;}Yea@DfO#l(2U9RA&gGWj6G8InddY(XDuo&o(pW7*&;#tm;eI3&h zWLU=@>U18WZRe~^zWm!8`GRJ%m>iCS@vmMc5k^e?34eh4W3jO`_NT(d(u+G>Z816z zBlOQIuTqq6v?rU$@)3L&>T*){3U#m))|`c3yC5c206h1Lca~B@t1y<*{-VW@!%})v;qcjf)JFLC^QDbWmx@0zAk{xEB9w`czw3u5q-Ze`$ zX1tc3{?@*fO62K2g7KH6Gp&kLOycTyD1W zmdFi06}lViB@O3y)`6|F=J-g!BANw8&zH?zaS(&hZc*{2BaPaLc}T@rXm@=1Tupf$ zuPazrovXXI_N7Ep6Dt29Qbc+J8lMJrJ2?MUnv~79E$6Y82@_UvR7%r+E+t|8tGllPfhVAXAlfj_Nkf=GC<1E${Y~tl`N7*@A>mkIOboh! zpekgd;q{U1qO}Bn40;eBAc3&9>^b{lB~T1T!F}lF$t98zVsKKCc z3`!|^6)~fJl%#F8KLr zq;aunkA3|?Kdy?b3sskvG^a6Syf*&eYtPD9=S1!3>U}YIGsKi>Jw#)Q zTNhe#k+k+Q`KDCz1pxH-8RWEzSUWWp9P;k|@#D6=p3`d4F%@#Z&*-x97OK*oCMN;2 ze@vdUAj^OhMmwtBmR=raUMaH2*~x7a=uEHINsneosptE&Y-m!K`=RYugn1z0BUg)B znr>?nqu_8_%uSanP!Lt@Ho4Ck7q`Z+g8rl&hlOw|B2u9#9c>)8=#7u9bsE&JB-yta z*H>2|d|Dv9(2tv+ZDeXT`4i&^zMQVdUwb=7<;qK`DfPj1G01ch(Aqfy5xiMsqf9T@ zDaw%m-8A!19uaFGs17ML859>g=X!Vgd|nEqII4d2 zzq0^F_W3)8uL^3Ns&r~v$Yb;FJl_x-9>xO?wx-|3f7rVrBHrh{;f*XE$*d7CKlVba znI9K2G3w5BOlRF4%_8c)!8|FPo@Ec;#ESJ5^CUY2Z2Fm@o{vr4sEDUuT7P#2sONLI zAO+;3QKDeZd$QVkp%u8pcNUK^Mo=T&hHKXV3})q_;vkgy>8$(q&&?>Y;vnO--EW!& zG5|r1)LhbB!FprP4i3&DuJ9+{9Nbn>eR$#H^?u8PvNzl_z*M~%#!P`EGz27kjCNJAJj^EX{bDKvj0O|1|(U++C(WR4WxY$m^h= zu>c%IWz-Z!-X6(ukqW4`OR<9AH8LPO%smhGg*<#$W(zKUr-^0Kb%#ni&nmwJWW}#d ztf?G$@_dzLc!)1V>U=4NwSAD~^`=m5g_7v&P(;|T676_t2aDO6O0V}YIq!1Ylc?Lr zJ21oJk^EHi#D%%3zZ8dw5gC_0u{A}oatztb0)BJSIXc)X&=>@CP54N?@oB(zNa!^g zUMc_w<$PtBV4Wu`eXjaGul^{%3~RYNROcv&0Ll$Qsi$5Ak~4w7Yd$urz}+EYLE>oj zqP7b!R`B{9IO)%;+TFt}$dBt{!Uria#Yv6^y_B!6*Ac%NDUe*DL!H1HD$IAl3D65xx=~x#sR?45=JEI(w3vQk7@0d=Yf%#E@%}a0FKD^bGqwHo!@24N%=vJ z13HbM4zr9$$`HhZjKxfA#RNqEJ>XLZQl;mYR1mTwkr?haYW z-e+-xxV%Bh7q9$@_bscrSL4ig$|U?8(VIB9yrhyLP%Q7wlze15puoePCHYv>?Lk77 zN_$d!tqSC9(Kr_U37h|%tR96*PeptX#(Y(*S@3SeC6=k$!ZD>U#P^6UjVc7FoyTl{ zau)cSHYs&8Gv3>IoOL6AHSv(!dHGQ!)a+URge4dJdG)*b#ZiC>oLK2u!o}AF+Ut>( z<^7zu&)<+hWa5ELR;&EgM|Os;G^xC0U4gfz+56WWzdp5aC4i-%I`|~ktMXT2ZGVE)rGySz=&)W_J2_br^tYPI7 z(W^>0Ins@Z9VA%QyNoe??$GJvi&d<|QXvs@R%f5)Ho_EJPyf37^RncjIQ_M=;$BUQ zGn0>lhC&z+Kyb?S1u*?JOBdyoyKwT$s@-gM+xq#O#VGjeYIY4!M(&PTT=(b&d-LIKoSY?W zJO$Veu{5flyuFWI6uLId#X_T~r;N19g1Ji&dk4+=!H2hFha81 zQa4lE`rZ^+m>k&A*_rP;tCzIysC}J}Va;ip16O2*wrPUYJ$Nq49OlFYQL+K6kM*hq zyOoUDL42IvES*wYZ=FREW@a~8b>(d7k9dO)KRymt7h2K%am~xJ)6lScxjNI#`d(aB zj>J$C3K({e?4j!;ji|?}lUDN`DU>2pvSLzEc+Uwze1FahN~#&?rnE@^xpA z(@sPqLIciJ7z^V`7D@qq``qx2hb>xcwY&}Hlf@$wu=jq| zr(FwR_#dE{1mn-IvBI;zsxsF?&!+Wa!VV=RJ(hp8&3_&eJ9vi@03Xnh7mv+_nC70Q zi`zmk;Rj4Wjf3Z(tfqKwp4_Uf?~ixwYamT8{N)$Ji}@IXHl{x+NuGeB87%qj#E=j! z5JivsfgK0yE!zW+%{=8YJn@l^*AlnNOR9FgZt~}Q{h(6B{kJth=4q*J(rVb>fG0s3 z592}+S5Fi9c!(De!dUS!x=PFKnXlUXygazCGSkKD9Q=wbU=pQV>mkIJkY$R%QON^0 zo(i-fH;5Cp-$t~5iQ4&5IY>N@usTo14<&22mGwHFT{GgDN0(8s)Z`rTqf9-c9lY<4 zB#^R$vf7`O_<6Gzkl(~!Kg9|g)m{Xvm<&owl_k5%Gw6wvbLNot?*EQ#4Yx9)&AK+ zW(t(@=epOWHvrApsVn^Z= zn0_ZLUFv*_qzLZoSh9-MOxhg15q}|KAI%$L(fR6zOTAxd(_oM4dbk`lqQf?W9dLuN zb+noXwsM!Il=4-EK1lm)=_T&s@rcfOZZYd}6e#O>e=biC{kj8DBb;jvdvqOJU-U=1 z@01S!CgrYNJAvF&NnSV6hM}j2RmdX?&Y(w#&JPVd!O6PIr}M8*cV99MrGzf zd26kkU()0%A=*T2j1=#XyLUm=%dV0?u30MWSjhV%LvDf#dy_@>F1cU24MV01UaHsi zp(!|4_Ym)8H9%50{3rgSqgT$8AfOYhV;H`5o879?+r74TxR0?U*#x|67)K2`3@qIj zf2@<&Z+l%DWqogNI1ckEN~(Daur9MKDR5LCJIHoJ_I)VgHH-Q$73Ngv+1v|PqQSBb zA2xm}2ftFYK@#?*0^5KOOx4;zXob8r>$+ovNW^9bSfjMiwqCPT#@k5oR~h@+Svi1k zDZa*Gjp>@wni@L_Zc5UbnlF$U!gpr}y?AF0xhbrLzz5KsK9)1GA-SJbS>p^LD73aK zMk&(deZWnzzc6_yBKK)s!`c28k?SJ}o-KqFoS>sO zLUiMU2GHp@ap%{?vG%PogbRpcCCP?GG10%@jWLPRpI@X29F$WeF3~Z`Cm|tq6 zlFEDjc?-sMrk-{A zzosZl`}*S@AFC;ED#$m=V3XX|{w7loG_>3%2t;}dpX6<%@5E`ea;yts+N_~vw7>IB zy?ef*dkjk_g^ampP+#Z9ODngCN}^!M5zx2A*H!w)Sli}-L`c6Mh&)rjk+w;JjkAmP z8}a&it5?_UnI{FlvsUNz?y*dv81Xh;2CJRit$av)Oux_9WUE)wWM5N2zJ!YZaEQR* zRuJ&5AiM$p1R*2ZAGQ7+8f2$!oe~)vS-yr@^CYKILNjWnQiKq zo|f@vQxM$ec_NK!g>$sS96b-tHPTj9nWaJsEE>@ZY}O1V(@P-AwrKbmyO0)+Mb7Sd zzL&i64Yt00>WlHJ{fXxj+bcz3wZMU&GCCLK?{;IvURF!De;Kf2nM%dbh_Suv^6^J% z^3G<%Pi^}+1y7x%ug|MADme$4#jteclX~Ua?mjM!kq@ptuPF&x5>Ly#Y>hIFe_fbQ z8LpW!q5dOHNQtueaopd|6p;0!W{b?uW!ZZr*yCAt5ZwKUm3P4CsPl%ZZ*>Z8Xa1!{ z1QnIheCQ0?Ae)uwEYgptDVvwlx~i{FYhSy`g1pj-UFk!GowERZ+YuJFqqdBejsZVCgCyB_4li(%SgybjEOa5 z8PD3zQegzHuzenp^vP2Wc_WT1U+1nfNI-KjViFv4-5_;v{9G8!4iaT4&XwPM8>g^c z4yGhw3n?dqV{E=`z5y}*4S+PkvRZZuj>MC$b{p|1K$5{un*WCLm($y?>rZd6mj)}p z?PuF~@thhzw}Zf=D;&Z9GVuS&QU=~*C7aowulln2Q$KC!%48^yD*$N9TjR@fYp6Im z9;o&Plked;cJ+;+$c7dS7;Y9Mkq(8GF0mNB{{aS{Ezv_8=%^(wP_dZre13&mss#s6)AAo(Xh&S0x&Lf&fu zu=2$P*&xQXK}&Yf<$Lj#+p*)2E!gs*B>j9$M>CPEY;QYSkg;1h^qS-19C6r$;eO!P z^t4~HRLv|~L@#Lk-gN|n2nBLW6<6Xm|Ly$CfB(_j?T{g|*;xjcvB~R@LlQnnA336w zbnSOjiDY{IoDUKO6PdWx{8ssRyb8#&@Lm1OdaO=`ZJ%X`67cn7R?@3$l2Y0GbyA{0 z6(Bg9s}BE9^Z{owlz4AsFpArDxJ4SsdJvcJDjD$Q?I%tGQUajD%T2taESd+q8BXfP-aK6 z{Qthup^Xh*gcL%ajVmf7w<~PN4n*$)UfhBG)2E&zB?zVg3ha4!z-7{0mcRta&`gdO zgnm1jJ@svBS)2lS7e3){f2$qZ$nVe>5XlFskd4VbZDL6^RW-qiTbTYS{6B(j#slv6 zCjQ@IFG3DzPDa@({+HPJ|GBq1RF}OSU(V)<)a(BVDIsM*qS!iH-L74w+Vb7yQm$AnH&FddUbpj!g~`~hv|OW zXl^FuI{TFWgSENht(7<=#8fMz>p}74uvvM?1Gdre&jiCHgCyGSGHM$G;*U>yRDu+# zb6S2%xfr*gn?FhU&2t9PRb6}jXf&4I)4LazfW!p`?xo~*NooD57>wE+Yh>pX&K-8R zu~w!?OJS3K(ZH**@gmf1`8dRxL`|}2*pB- zD>jnIveLV?jt<921}8?z95Xfy*S50uKUb2#mN|c;X+=6H2p1%h9od)AbxD7y^D!Ro zxOpsFgJ$hw{wpQ`R`Gx1;k0xS(rA&IZzD{Y$bz(h@>PTiw4Yp%ze}>cmh^&wt}pIg z3%nbWn?~Hhi5FwVj$K(g-;UQvpJR?S@lAG6b=cIJHY&e|O&j}-9>SEwv-HR4#Pi87 zfuKJCl1dlJOi!NkO}yeOy8mHRwQ_)5Q5USyEPm!quYO9N42*LeXp7hBzMwZ;PQC3n_)fD0s!UF&tMF581=oB{6Wuvt z#?M)@s563NHKIM8AOG_(mt`VKF$J{NO7I2?ZoALvCu^Lgxq|s*BH&hiYG+92Hnz{C zcl_P&S*C4bcR-zkgw*T2n^9X_`0-PdXn|6R;u))3?|b5(lg%maQyq5 z-hy-x6V?e$+h}aZn@Mw6>4SwlEEx+cJNbTmX;j}gwZ`~^^CX;07|t8Y(rZe;wfb}J z^3b*yPVc}N?CIGz7d+GxW;F}wF0!LY){6St4p!G?H>|)dx{tWNE^p2ZPMs45opy@~ zf~+O)HJ=6UZ&QU$niJ(UGj&3l_obO@FayE05BWqW(zP}5cGY~YhNJF!XRWpO7}NJ{ z>c1%}fLAp3gfaF>Fto;c+~fWnRp;LTZFSme$GHPuQ^57$d<_);0^o`#)6t-6yq*n5 z$MopE6sm(e?~e=wgfNjm)U1o@;xk+$2R%`d?kna$2eh=mw_K!4%}JOCW@bcJc~$4P z*r?Jx#CU&qbI$TrS;vJ9y%e|xIZ_>?E;7F?m7{41@X|d8x-XfG5Ik|eO5ebcy%%A8 zA-8JGnrl7Bbhwku%)UPh$f~IoBY;qxU#?I3OS$On*zV>fp%B8FEmUtqzhD$wNCG&F z=LoIt0B85=W2a1q)%)oxOqEWDG&pkDWtRt%j!?)ko zoqZBMFZtzh+|P1aUp%pU{BXJwtac`Db+B!*O*h*%_bqXL=htGljaIX95TvEe10K*T zDVW4H(ceO2==1JZtdW;Rhq?4uRcgxv+0NYky6Gxf{yX;QO!jX1CYC(-#y5Lecam{pMQD1}*E)*lj)_ zd4VFJ4mz_43u#>Rc)%C`)cd5fJK(Z0UMlct(!Yk{x5FKe0hJbBDsdU)7%@LU6pbCB z=lR#vaN`}Q1pht=JN>vmoHXm;GCwgyI?}`PL~}dvK1r5{31aZ0iLnGn>}Y^xEanTf z(|2p`y}`51DXnqpbsjs&g9s=+8T>!x=@4qvskN?PW-|t5>O%45YXi-lr}eddxo0;T zmp6$kS5q6AkUE~?m#*H!p{>Fds5yp%{5Ed$(P;MY`OU&+2h%}UlgsM3j1C&7Y^-Y7 zdJ8TjD6MYN(dwX$KoCXXWIT|cy*wGUi##VdG=mz;I(3p6wUyrZ*^fY(NpzmRi#5C# zB&ZQIo7#X+QoYi;U3IhW&Lbl{x8;w5v!iZ)Dj%_)FtowX#SI#>N|t^O-&dszb>m)s zRf8CR^5l!E(4;f+#q;dNBOw|_+j!2YM~(4z12B7xAYlR2?GL(G@&>+xU3 zX{NHm)q%9m+u<_%)(lEvgebKito|HN4{oY0-6g13=D_gTT99NuGFciIQE+`$Y`VY@ zi*1!|N!ozz+T#bp!r<`j_Uw=mVAdnPo!#vJ(DLNY;XGm)+A5)T^zOk6E+Y(2W`5_7 z<^BlUWLQ0+IZ#6=BITxGl)e0W(&2^Jw3r?@rVsS3wB5G9dP=r>V>Lf$Mu%TZAMRgn69-}we-b=K6pSkODA%U$sxT7+wZ`o{ zjVM`r3(9=i@+QcnM7*TP;uM#pqZ^@OrTRVvCKGPGOh&k-WvP0#?fYjBQ!73=U(KXn zjSw_E-(Fx2I)G&9Sw#AgMa|%Qlj5`wSG*rS$3Ocr4w9(!PhOSqSQR;C7CVu+gHBg^ zhYr_12s`*ND)>{18~J%xwCgX-{#yJiDZiz~YLg1#qVof_L0aMQFYEPGt^7g$<143Q zL{&mK%X){Oiik+-_dj*X;>ji-*zH*E)HV~Kyss!HYr7~Y9qxtL0~Oli-}-vR(|iw2 z4FS*V#XXYflcI`vc4JuWf0uf1QDJ>QHT6rTOooG*(7muR>z`J77Je_kgN$Nh~f-tLqg#` zB{0rMv!T*gO*l>xlRtx7+XAdsrn#vun#HAegT2@-J-y2;pG(A4>om+V!s464O2j^t zIJutxc@ypOOY9cIJOKtq@itzg65MYLGW4$7%4xG!4gn$qJN2_wk$E>=xa01e zz1eZ>t&Gl@dYpZAZH-#e2jNSLBJa|*&c`sXg-mIov{+6PNO1*>H=(2eewbKV>Ac&4= zP7^PqXb&rG-852XL{p6yw|vqbH55F7N%%q-y%gEtJkOBxy#9*wS>1ey(5ISeGqU%B zUfX^Sz3m{~@oy`oCAQh4<%pYc=O8ts00E%@#taDNsarp{%ZozjJTmowlojI27G237 z(0<|l_nxAbpGpgv_`bu*%$4c?T^qYDWkR7Z%fP6z+ZPD}K8tpz5GItU=JU26uVsDx ze=nV4&k(lGf5b*Kp2(|nTly&c5}9#dHQhSaK&kx^(gYx+_uxNHW3t!EEGz4Mbm_c2 zhg*lnb~cYcKOkJiOB}(hg+Av@brv2nWOi{W!Zz_@R4Q)@}4 zUvQ0WGdj)8o#g_o=Rnq&3qsZUAh3>*xluMh5FSk~r z!U}d`XldNF+>2%RKp;l&?f(S`BoCywHyh4?F%6fPuhn_U8;jcxQ z^@sT>w*)DjLYK6!)UnF^*GnzD^>I~5>utXr>Ey?5eO@cddmC}wwc^6V1%J1yELprG zetCe^Vra~FQ&9FK2^vKgS{280eze!rF_{g{)zarw_B#qDxyCJf(qd{BV=7EI$dopS_VZChMvaY|&rwmFqtU8M-* z_=!Ezvt%;rG23s*oa{eJMSOk2XG10R^n0WqI;xgrBRY1&MvL1x;$%v9@YVB5xmBTw zY;raBkb~QHElPfqjPtffm!yoAKU2N7uw#WRDUrKLZ7ek9?98*cNamE&V)dC<>g~Pw zB2$<}lp|ZoYP6%-v%JPM=RNr^@uB`ai_M1@6-uu{Q^!ozOq zfpV~(3kmQ#k?=|G6durBCOC^%Q4iJircIqqCR>}2L(V$8`=-*d+o~Q9{u(`fTSs;I zyGwac4;I|WjC`EKfVfJ(L_4Ur;FH%be5lzC!Jy4dM&0~}I&%=XCuU1ulw4#tbVT|2 z7AiMkx2**e!P+Zs3rO7F#n_b#9z5<64}s3Sw2XVfK+y2SDzlyV8(->F=UILD7aJ;^ zSmijA`H`iVr{L1eTo61Nq|X)<4uZM_)KaW6&}eWh-AFRlt|R z5b}E>J97y0a$CQLo}t0-QDDv3?AskWqtO}gv!a`b+Ok8Zheh2L0~b3H zZJ~xOVTg3>K#a@tqo1z_6yf~8b(sFaE#tu7N#LD~g~Pm4GQ33G-M^NMI>JkR*$MaS ztvelH8E)lQguOB~%f`;ax0A8}OCp0~_ zXs43J{)diW4jCeYW4BwWDDuDl4}W(18i+0!Pa|R~yB%DpAk7WZlUu#_U&crjz{e^o zoh#ryq<@T!9_cbKl8aeMn)MZorv_a(KOF-MGiAx$_GQ5VuV<2h%GfSS(KU?Ls7G-l7lNWqoKrdlv^*rg%ENQU;_Tu zq9G;!%=uXHwimeN_5d@LfGS7~$>9)yGMn27F<4Qvzmb`FCI+xX=l??~A#_;*7KoDU z5cFUEiSd>;>k)YclliZ9fV$JTJb?4yusC4A_@A)M(NN%BIGWl~;e-FuRKR`z50}x_ zjuyiKZnHnB3b?(I;~!&~eUo<|DC{Z8lw_H27ejBZO~(TsO!|)pjf4NE_AQ9*fMqm= z?dfTI+~Irg$aoX+=;1ecn9y=_$JL0y9|Z4x4kk=RS|;-^U^vq{4KxMtisk)C=YQ3@ z?U{=@rugg+$(ZCM^%^!S$c~fk_Yb`s(cR~Tj7DaU5OIu4tZ7qh zxE4gWD6tQ+*ibrnJQx`97tRTx84~M(W0<|In<>RgCM|H|kp%oqg{Zex+zK-!+Ci;(i0xy4tTK^yITzNRuZ`U6aB5P!;Fk$Tb`m@B4ov3VKFn+ccJ0aT`TS;Xp zjmX+UvSta9L0Lj%7ujP9*^PDPxkq(f@AF>o^Stl-|MQQ(Tyx*|`JQv`&*z-aeWx>|za$JKeSyb$NsJ@9(w zFb^_)^S}N(4@NWNA{1ZOXcC_v^ObZhF|u@dlx!q9hV-%+DC1JW*L7`Pkgm-Z#Xj6< zuAi0b7r#kt(hN4X@CafC&SU{D3iB9|FPb?Vp!C3d&!*NUXRKi>#uoolcyl63CwyV3 z>9ml;5$dK>GO*$l$&#nG*Mr!Otp$2tD~w^=4yUv6szW8d+si!@e1K=4&2u>)ig8(; z@i2(_h5NyXh;t9WKlOuhF!Y7V@MpkotkD-g(YRfRXjhVkjR$^))n9Yw61f^gbPaZS ziAAGOoXi8x72MC`*SyS;k{alIqOQ5JJ4jftCd!EV2ueQY9*@_>gTAuV=!K9z&VEag zxUsO+7bA8n0prXEU0NAq;L)%SuKo&ZjJ(!t_HOPG>%o=_5ZY&0auzS6tEUkp2S-%A z`kLdW0QJv!53az9)?8d=S&(-NJZe*=F~iRt@^Ncnkj;fU)UJa|Dk=VckoMWB;eO+| zau*Le{{OdH;uny=)T5CvLWn`C^pyQr@J=K zyPBQBzMe^pIbfzntu%1eN+O_>8)5vyVp-^IryrmG+Rp}#u0nS71nGlylk7kyWgf%K zfMWf2$ziL>t7@**@qXY9DBsnQ$|4F=-P?jM`~=W-kfQ&XUXD364yM*p>f_ zcAPq@_F4;~{-|qSx%*?Oah?#mLUSSCK6v_qtrTxzSNTfZKC&Xlo;8Z(5oAyDs?IN* zOgr~jf|Il%8H1%>Gh?6_p?TGB`GO+F%CO= zqUi5&i%#tTcd3u@pj;HX>U5#id#wf|X+%Q=9r23PJM1&=1mw?)uAQcv zzfz}_spuO$pjYPH?cwq!7tjSSZA_U8m$!G7RgJy9<`uyBo_=rTQbrx-4lV`j`C^EU zstNzj-|uYAJ3D*5l^x>g&q0|h7{SW!hcg;RlDp5M^WGgs^$0I zp828H*=yB^IPmj&R=UG1S$uTrbJUTX>w+7|d-IE=fHt!qa$YKDhU=O*+glT)%Tysz zYl*KV{Za_qm}0+Dd`T^VI;bKl*8mm|BGp-@U_(S0)69c)k{UIBgqy@~dZ0N&*oaCe zJ~2uRc0AXoe&J+0HM+8QbUeg7GfVi`DSBO!{8Zdq7bWa6V%$=ADM3<{D;A92$emm}NeRmRD?80c>t|7;$8-@)`Dv7wG|8MsIwte&;ps%R(*+Rm>i)fi*|59$ z=U+;z)FrvyMIzexrB$F1JRQds5P~pEF0N%r ziQ{LyiOc{Rw(mK)Vb*6r8%iwc8E>3m1ZIg(jY}G8fJ3u-T;ZHiZ}GUZ#B}qL9gFVS z%4CE(fG{hZgr4rkShAr-brR6Xv(W-5y7wRI42L`9)lA{>xcRLlN@HCS)aLEnOC$9B4I^h)vZHv-n4a}w9&&aq zm>NRadWj4?zOcc)lOC9=giMY zl<`N64v(a9k_%wUSAaI0G18dhfzf2D-awtN0?O=QC^>n;aZpjTX3)kuKq_=^q|vls zzVKNon64Bd2VC$;&VDWI(WF{aS1R6T{b-9vF=zg*$;vlw(-Z52FQ%k} z7?ml%EI9c{`XwEV;S&`|dpymZ^ke*E^zo8Rsiy4`-m8xc(!WdmFkJJi+wq!T3n$SM zQ9WKU-`=1knrmhFWg;X!AbP)F^x(;*N5va;T?K3*u2>5e8yOR#5{@N=l&T> zW?-gz45Nr{@;cjgscR^)A94iH+VHOP8hdU5xe#7m$8REuK+l z?UHfy4P0S64vES~Ohr4dT#)r^5bAH0ym8@C2(*q^?Utqx_Y1E-5Q84oC{V{VzmeEJ zX0M448f!Q0?r?%AfE#+g0Vv~l6M`aycl#$*;i`PK<#rL^qYC~fi!tQ3x zb;T^_EU8}E<8$5a-r9Rn=Q-}4DpuoVz{_C1Vi&!%jGaR{XFVY8S~>tyfLP^gR+3_UK_vQ2@cSS^>Sb?JP6FgE27o{Js_+{iFmocM|5 z36Dd+v)cS8xjOnSqu!y@9T0P>ImlpbsYbb}hW z>yZ_65)sJg$0on27cQ4fZ-)6VN3H|k0%i`PiwMKr0Y7cI{p-mB*jTRtxh3x7M1|u= z-T{7uqWTyAljTEKe+-lyf#@S0kj0Q+L~}$#6i~AZ$1iRi38I6ks8#`SYbihYOxz7> zfA8!hykZ_^tOC{k&*6Y%hEz!4P?R?swlYEj)^1#)>1TV>Z z5L{b0cM_7Y+G|K$x~N7rRwBZZRxQJ#HF=f;z}n9U>hK1=RdR|zKpzW4*g^;{y=BqL zAAs`Wh^%Qx|G42CLdPNDny;A30Nmv0#it}jnCoS2o4uohCSfvGv!Cd13Ca|g0b$LF zw+-2I*>Voc7pZ=&^MYn_ByFLyQqIf--p>V0dGv+mZ0A<;;w_VV=(U+-#5mz(9!WC9 zY|Ht189KF|L$)TEw4+WJblAwBEYSpN!y{So@#=SZ^$bfnirZ&A)777U`9k;l?UkFO;++N^ zO4Ra}qFR0xvg4XgyS!USUuLZmJ}p8*+Q#*puj)+#zD`+u;D*$1-O&O1;@h-apSoW% z8QBEja&d2*E*U5sE)ojm+)ol;L=`8sD=FHtg9ni^nX2!eWs0%8u=;O(S8!>?6j00L z#yu02Z`RjUb=M|YQ{anLV}9}u;Posvrdm`+-1j&J))`G1?i2uO5h1EsqvD>29nh<_ zsM2ZGIA<7Soj6jW`qIJ5WG|UDEnTXiAjOE(oT)m{BGT`Zv!@rh>$B7cR}Q|mzPeZE&Ea`N^Q@jyx{x-`P z%=m<)$R!o)yPBD-5OZWYI382gdf^_SzekQa48a23_wG(d3!Sl(4B|DQxn-Q@GxTO@ z9Q*ETyyHY*R(p1j2+Qp_NH-}Jk$0Iv3?jm45AS>Y)q)&GhydD^{ccZpyPGYPIJS0y zk23Mz+n{LFCPa}*+PNFTVDEPv#ZVd~{3lVzfHVg*y+Yxol&Mpby$US(h=_TOxBo+6 zmXZ@dK=perL~NAN(7%&#*;FdpdMc6_pYF%I>pE2MpfxW6eAtZ-h1cR& zIal&5c*jOCH)KB+oIM2skn&7K{Z`Q@J9i_`z$Kb#g_J= zX%x3I^yE-^|Fs)SrTtxVGN3oi%!+5eX2_Q?{KEpSOdwWn4p#XNgK)xWU_u6a`HgHo zl?_Dyz-(4F4^meVOaWd&w=~K>{Ni%b5_)~C`$3ySqgY(!n9qdGuKqY94ZESJAjXq6 z)o-0xxpA>NdjjKiZgxG4Sea|yQysAK;3jlTOmODRJ1>s|;mEogexo#`278G43BOnE| zSofX6X&wmUpw1@eDW#%Uf!QdNh|IeRNo zQ8875p(^;vs|l!-EmK<~-gs1&-M1+<@X!$EMOksWe&E%Q{kobAH#Cq~2<)0N_A~gY zWA&IoUJwbe$8$bv|-XXE}#Hqf4$mcN@inER{fd&dTF!icydvCCRqQGkHgw1A2 z5j+9h;BC?v>*}-B?WNd(Q(Rj~#W%Df;vs(h5>??A^|8iiUNttHxQ3oj-YbC~I0cf< zdl@YSB-xAng^*e4pG-wBnZ!kESQ_2-{W#IJ#?V*@b$EGFD@C*Y#i2xfbx=S}Y_9g& zDX2Y$ncy9Ws5)J1iUnuZzN1fS1)AnSt4Vt4)>X9k`LidvCvA#p+kAww7j6nj(@E`o zxsG4>abHcvG^>FOtL}$16C5nex~6&iDY80csB2B2J7*#Wh|eS4n;JDV&Mbd26ND%) zAGLj#YcEwS5EU_XWsGH8ZT>I3I<4~q-2M{I^ooOZtaqb>;2Gyovp?u4rfR6Z^5fvZvc| z?D@wE>GB3~g?~fBx6BMr%1sGmz%VCRa5smKmAlQT?bB#D=zaUCW09z5dra12yW`{j reW0@Zg*^WA_dgc+e_McwlE^E*XLKO=@+t;Qj)xfNm}nPkp(6hQ+U|pI literal 0 HcmV?d00001 diff --git a/lib/di.dart b/lib/di.dart index 693df0ed3..358f72a77 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -39,6 +39,7 @@ import 'package:cake_wallet/entities/wallet_manager.dart'; import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart'; import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart'; import 'package:cake_wallet/src/screens/receive/address_list_page.dart'; +import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart'; import 'package:cake_wallet/src/screens/send/transaction_success_info_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart'; @@ -1417,5 +1418,7 @@ Future setup({ getIt.registerFactory(() => SignViewModel(getIt.get().wallet!)); + getIt.registerFactory(() => SeedVerificationPage(getIt.get())); + _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index faba5fd52..315c17178 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -66,6 +66,7 @@ import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; +import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/send/send_page.dart'; import 'package:cake_wallet/src/screens/send/send_template_page.dart'; @@ -799,6 +800,12 @@ Route createRoute(RouteSettings settings) { ), ); + case Routes.walletSeedVerificationPage: + return MaterialPageRoute( + fullscreenDialog: true, + builder: (_) => getIt.get(), + ); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index c8eb63c26..517efca29 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -116,4 +116,5 @@ class Routes { static const urqrAnimatedPage = '/urqr/animated_page'; static const walletGroupsDisplayPage = '/wallet_groups_display_page'; static const walletGroupDescription = '/wallet_group_description'; + static const walletSeedVerificationPage = '/wallet_seed_verification_page'; } diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index 475f45fca..91a47fda5 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -25,5 +25,5 @@ class PreSeedPage extends InfoPage { @override void Function(BuildContext) get onPressed => - (BuildContext context) => Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true); + (BuildContext context) => Navigator.of(context).pushNamed(Routes.seed, arguments: true); } diff --git a/lib/src/screens/seed/seed_verification/seed_verification_page.dart b/lib/src/screens/seed/seed_verification/seed_verification_page.dart new file mode 100644 index 000000000..755cb2aae --- /dev/null +++ b/lib/src/screens/seed/seed_verification/seed_verification_page.dart @@ -0,0 +1,35 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_step_view.dart'; +import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_success_view.dart'; +import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class SeedVerificationPage extends BasePage { + final WalletSeedViewModel walletSeedViewModel; + + SeedVerificationPage(this.walletSeedViewModel); + + @override + String? get title => S.current.verify_seed; + + @override + Widget body(BuildContext context) { + return Observer( + builder: (context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: walletSeedViewModel.isVerificationComplete + ? SeedVerificationSuccessView( + imageColor: titleColor(context), + ) + : SeedVerificationStepView( + walletSeedViewModel: walletSeedViewModel, + questionTextColor: titleColor(context), + ), + ); + }, + ); + } +} diff --git a/lib/src/screens/seed/seed_verification/seed_verification_step_view.dart b/lib/src/screens/seed/seed_verification/seed_verification_step_view.dart new file mode 100644 index 000000000..c7b4b31e6 --- /dev/null +++ b/lib/src/screens/seed/seed_verification/seed_verification_step_view.dart @@ -0,0 +1,135 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class SeedVerificationStepView extends StatelessWidget { + const SeedVerificationStepView({ + required this.walletSeedViewModel, + required this.questionTextColor, + super.key, + }); + + final WalletSeedViewModel walletSeedViewModel; + final Color questionTextColor; + + @override + Widget build(BuildContext context) { + return Observer( + builder: (context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 48), + Align( + alignment: Alignment.center, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '${S.current.seed_position_question_one} ', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: questionTextColor, + ), + ), + TextSpan( + text: '${getOrdinal(walletSeedViewModel.currentWordIndex + 1)} ', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w800, + color: questionTextColor, + ), + ), + TextSpan( + text: S.current.seed_position_question_two, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: questionTextColor, + ), + ), + ], + ), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 24), + Align( + alignment: Alignment.center, + child: Wrap( + spacing: 8, + runSpacing: 8, + alignment: WrapAlignment.center, + children: walletSeedViewModel.currentOptions.map( + (option) { + return GestureDetector( + onTap: () async { + final isCorrectWord = walletSeedViewModel.isChosenWordCorrect(option); + final isSecondWrongEntry = walletSeedViewModel.wrongEntries == 2; + if (!isCorrectWord) { + await showBar( + context, + isSecondWrongEntry + ? S.current.incorrect_seed_option_back + : S.current.incorrect_seed_option, + ); + + if (isSecondWrongEntry) { + Navigator.pop(context); + } + } + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Theme.of(context).cardColor, + ), + child: Text( + option, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w800, + color: Theme.of(context).extension()!.buttonTextColor, + ), + ), + ), + ); + }, + ).toList(), + ), + ), + ], + ), + ); + }, + ); + } + + String getOrdinal(int number) { + // Handle special cases for 11th, 12th, 13th + final lastTwoDigits = number % 100; + if (lastTwoDigits >= 11 && lastTwoDigits <= 13) { + return '${number}th'; + } + + // Check the last digit for st, nd, rd, or default th + final lastDigit = number % 10; + switch (lastDigit) { + case 1: + return '${number}st'; + case 2: + return '${number}nd'; + case 3: + return '${number}rd'; + default: + return '${number}th'; + } + } +} diff --git a/lib/src/screens/seed/seed_verification/seed_verification_success_view.dart b/lib/src/screens/seed/seed_verification/seed_verification_success_view.dart new file mode 100644 index 000000000..7d73e7a9c --- /dev/null +++ b/lib/src/screens/seed/seed_verification/seed_verification_success_view.dart @@ -0,0 +1,74 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:flutter/material.dart'; + +class SeedVerificationSuccessView extends StatelessWidget { + const SeedVerificationSuccessView({required this.imageColor, super.key}); + + final Color imageColor; + + @override + Widget build(BuildContext context) { + final image = Image.asset('assets/images/seed_verified.png', color: imageColor); + + return Center( + child: Column( + children: [ + ConstrainedBox( + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), + child: AspectRatio( + aspectRatio: 1.8, + child: image, + ), + ), + SizedBox(height: 16), + Text( + S.current.seed_verified, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.titleColor, + ), + ), + SizedBox(height: 48), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: '${S.current.seed_verified_subtext} ', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.secondaryTextColor, + ), + ), + TextSpan( + text: S.current.seed_display_path, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w800, + color: Theme.of(context).extension()!.secondaryTextColor, + ), + ), + ], + ), + textAlign: TextAlign.center, + ), + Spacer(), + PrimaryButton( + key: ValueKey('wallet_seed_page_open_wallet_button_key'), + onPressed: () { + Navigator.of(context).popUntil((route) => route.isFirst); + }, + text: S.current.open_wallet, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + SizedBox(height: 16), + ], + ), + ); + } +} diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index b1ab7471b..11dffdeac 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; @@ -15,7 +16,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; -import '../../../themes/extensions/menu_theme.dart'; +import '../../../themes/extensions/send_page_theme.dart'; class WalletSeedPage extends BasePage { WalletSeedPage(this.walletSeedViewModel, {required this.isNewWalletCreated}); @@ -29,62 +30,34 @@ class WalletSeedPage extends BasePage { final bool isNewWalletCreated; final WalletSeedViewModel walletSeedViewModel; - @override - void onClose(BuildContext context) async { - if (isNewWalletCreated) { - final confirmed = await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertDialogKey: ValueKey('wallet_seed_page_seed_alert_dialog_key'), - alertRightActionButtonKey: - ValueKey('wallet_seed_page_seed_alert_confirm_button_key'), - alertLeftActionButtonKey: ValueKey('wallet_seed_page_seed_alert_back_button_key'), - alertTitle: S.of(context).seed_alert_title, - alertContent: S.of(context).seed_alert_content, - leftButtonText: S.of(context).seed_alert_back, - rightButtonText: S.of(context).seed_alert_yes, - actionLeftButton: () => Navigator.of(context).pop(false), - actionRightButton: () => Navigator.of(context).pop(true), - ); - }, - ) ?? - false; - - if (confirmed) { - Navigator.of(context).popUntil((route) => route.isFirst); - } - - return; - } - - Navigator.of(context).pop(); - } - - @override - Widget? leading(BuildContext context) => isNewWalletCreated ? null : super.leading(context); - @override Widget trailing(BuildContext context) { + final copyImage = Image.asset( + 'assets/images/copy_address.png', + color: Theme.of(context) + .extension()! + .buttonTextColor + ); + return isNewWalletCreated ? GestureDetector( - key: ValueKey('wallet_seed_page_next_button_key'), - onTap: () => onClose(context), + key: ValueKey('wallet_seed_page_copy_seeds_button_key'), + onTap: () { + ClipboardUtil.setSensitiveDataToClipboard( + ClipboardData(text: walletSeedViewModel.seed), + ); + showBar(context, S.of(context).copied_to_clipboard); + }, child: Container( - width: 100, - height: 32, + padding: EdgeInsets.all(8), + width: 40, alignment: Alignment.center, margin: EdgeInsets.only(left: 10), decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(16)), - color: Theme.of(context).cardColor), - child: Text( - S.of(context).seed_language_next, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.buttonTextColor), + borderRadius: BorderRadius.all(Radius.circular(8)), + color: Theme.of(context).cardColor, ), + child: copyImage, ), ) : Offstage(); @@ -95,7 +68,7 @@ class WalletSeedPage extends BasePage { return WillPopScope( onWillPop: () async => false, child: Container( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8), + padding: EdgeInsets.symmetric(horizontal: 14, vertical: 8), alignment: Alignment.center, child: ConstrainedBox( constraints: @@ -129,7 +102,7 @@ class WalletSeedPage extends BasePage { size: 64, color: Colors.white.withOpacity(0.75), ), - SizedBox(width: 8), + SizedBox(width: 6), Expanded( child: Text( S.current.cake_seeds_save_disclaimer, @@ -146,24 +119,23 @@ class WalletSeedPage extends BasePage { ], ), ), - SizedBox(height: 32), + SizedBox(height: 20), Text( key: ValueKey('wallet_seed_page_wallet_name_text_key'), walletSeedViewModel.name, style: TextStyle( - fontSize: 20, + fontSize: 18, fontWeight: FontWeight.w600, color: Theme.of(context).extension()!.titleColor, ), ), - SizedBox(height: 24), + SizedBox(height: 20), Expanded( child: GridView.builder( - padding: const EdgeInsets.symmetric(horizontal: 4), itemCount: walletSeedViewModel.seedSplit.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: walletSeedViewModel.columnCount, - childAspectRatio: 3.6, + crossAxisCount: 3, + childAspectRatio: 2.8, mainAxisSpacing: 8.0, crossAxisSpacing: 8.0, ), @@ -172,7 +144,7 @@ class WalletSeedPage extends BasePage { final numberCount = index + 1; return Container( - padding: const EdgeInsets.symmetric(horizontal: 4), + padding: const EdgeInsets.symmetric(horizontal: 8), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), @@ -182,25 +154,27 @@ class WalletSeedPage extends BasePage { crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( - width: 20, child: Text( + //maxLines: 1, numberCount.toString(), - textAlign: TextAlign.right, + textAlign: TextAlign.center, style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w700, + fontSize: 12, + height: 1, + fontWeight: FontWeight.w800, color: Theme.of(context) .extension()! .buttonTextColor .withOpacity(0.5)), ), ), - const SizedBox(width: 8), + const SizedBox(width: 6), Expanded( child: Text( - '${item[0].toUpperCase()}${item.substring(1)}', + '${item[0].toLowerCase()}${item.substring(1)}', style: TextStyle( fontSize: 14, + height: 0.8, fontWeight: FontWeight.w700, color: Theme.of(context) .extension()! @@ -225,7 +199,7 @@ class WalletSeedPage extends BasePage { children: [ Flexible( child: Container( - padding: EdgeInsets.only(right: 8.0), + padding: EdgeInsets.only(right: 8.0, top: 8.0), child: PrimaryButton( key: ValueKey('wallet_seed_page_save_seeds_button_key'), onPressed: () { @@ -244,17 +218,13 @@ class WalletSeedPage extends BasePage { ), Flexible( child: Container( - padding: EdgeInsets.only(left: 8.0), + padding: EdgeInsets.only(left: 8.0, top: 8.0), child: Builder( builder: (context) => PrimaryButton( - key: ValueKey('wallet_seed_page_copy_seeds_button_key'), - onPressed: () { - ClipboardUtil.setSensitiveDataToClipboard( - ClipboardData(text: walletSeedViewModel.seed), - ); - showBar(context, S.of(context).copied_to_clipboard); - }, - text: S.of(context).copy, + key: ValueKey('wallet_seed_page_verify_seed_button_key'), + onPressed: () => + Navigator.pushNamed(context, Routes.walletSeedVerificationPage), + text: S.current.verify_seed, color: Theme.of(context).primaryColor, textColor: Colors.white, ), @@ -263,7 +233,7 @@ class WalletSeedPage extends BasePage { ) ], ), - SizedBox(height: 24), + SizedBox(height: 12), ], ) ], diff --git a/lib/utils/feature_flag.dart b/lib/utils/feature_flag.dart index f71e6b489..efde5208d 100644 --- a/lib/utils/feature_flag.dart +++ b/lib/utils/feature_flag.dart @@ -3,4 +3,5 @@ class FeatureFlag { static const bool isExolixEnabled = true; static const bool isInAppTorEnabled = false; static const bool isBackgroundSyncEnabled = false; + static const int verificationWordsCount = 2; } \ No newline at end of file diff --git a/lib/view_model/wallet_seed_view_model.dart b/lib/view_model/wallet_seed_view_model.dart index be348fd09..5355c856d 100644 --- a/lib/view_model/wallet_seed_view_model.dart +++ b/lib/view_model/wallet_seed_view_model.dart @@ -1,3 +1,6 @@ +import 'dart:math'; + +import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/wallet_base.dart'; @@ -8,7 +11,11 @@ class WalletSeedViewModel = WalletSeedViewModelBase with _$WalletSeedViewModel; abstract class WalletSeedViewModelBase with Store { WalletSeedViewModelBase(WalletBase wallet) : name = wallet.name, - seed = wallet.seed!; + seed = wallet.seed!, + currentOptions = ObservableList(), + verificationIndices = ObservableList() { + setupSeedVerification(); + } @observable String name; @@ -22,4 +29,90 @@ abstract class WalletSeedViewModelBase with Store { List get seedSplit => seed.split(RegExp(r'\s+')); int get columnCount => seedSplit.length <= 16 ? 2 : 3; + double get columnAspectRatio => seedSplit.length <= 16 ? 1.8 : 2.8; + + /// The indices of the seed to be verified. + ObservableList verificationIndices; + + /// The index of the word in verificationIndices being verified. + @observable + int currentStepIndex = 0; + + /// The options to be displayed on the page for the current seed step. + /// + /// The user has to choose from these. + ObservableList currentOptions; + + /// The number of words to be verified, linked to a Feature Flag so we can easily modify it. + int get verificationWordCount => FeatureFlag.verificationWordsCount; + + /// Then number of wrong entries the user has selected; + /// + /// Routes the view to the seed screen if it's up to two. + @observable + int wrongEntries = 0; + + int get currentWordIndex => verificationIndices[currentStepIndex]; + + String get currentCorrectWord => seedSplit[currentWordIndex]; + + @observable + bool isVerificationComplete = false; + + void setupSeedVerification() { + generateRandomIndices(); + generateOptions(); + } + + /// Generate the indices of the seeds to be verified. + /// + /// Structured to be as random as possible. + @action + void generateRandomIndices() { + verificationIndices.clear(); + final random = Random(); + final indices = []; + while (indices.length < verificationWordCount) { + final i = random.nextInt(seedSplit.length); + if (!indices.contains(i)) { + indices.add(i); + } + } + + verificationIndices.addAll(indices); + } + + /// Generates the options for each index being verified. + @action + void generateOptions() { + currentOptions.clear(); + + final correctWord = currentCorrectWord; + final incorrectWords = seedSplit.where((word) => word != correctWord).toList(); + incorrectWords.shuffle(); + + final options = [correctWord, ...incorrectWords.take(5)]; + options.shuffle(); + + currentOptions.addAll(options); + } + + bool isChosenWordCorrect(String chosenWord) { + if (chosenWord == currentCorrectWord) { + wrongEntries = 0; + + if (currentStepIndex + 1 < verificationWordCount) { + currentStepIndex++; + generateOptions(); + } else { + // All verification steps completed + isVerificationComplete = true; + } + + return true; + } else { + wrongEntries++; + return false; + } + } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index b9b643804..3a91d2cb0 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -366,6 +366,8 @@ "in_store": "في المتجر", "incoming": "الواردة", "incorrect_seed": "النص الذي تم إدخاله غير صالح.", + "incorrect_seed_option": "غير صحيح. من فضلك حاول مرة أخرى", + "incorrect_seed_option_back": "غير صحيح. يرجى التأكد من حفظ البذور بشكل صحيح وحاول مرة أخرى.", "inputs": "المدخلات", "insufficient_funds_for_tx": "أموال غير كافية لتنفيذ المعاملة بنجاح.", "insufficient_lamport_for_tx": "ليس لديك ما يكفي من SOL لتغطية المعاملة ورسوم المعاملات الخاصة بها. يرجى إضافة المزيد من SOL إلى محفظتك أو تقليل كمية SOL التي ترسلها.", @@ -475,6 +477,7 @@ "online": "متصل", "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", "open_gift_card": "افتح بطاقة الهدية", + "open_wallet": "فتح محفظة", "optional_description": "وصف اختياري", "optional_email_hint": "البريد الإلكتروني إخطار المدفوع لأمره الاختياري", "optional_name": "اسم المستلم الاختياري", @@ -625,6 +628,7 @@ "seed_alert_title": "انتباه", "seed_alert_yes": "نعم، فعلت ذلك", "seed_choose": "اختر لغة السييد", + "seed_display_path": "القائمة -> الأمان والنسخ الاحتياطي -> إظهار المفتاح/البذور", "seed_hex_form": "بذور المحفظة (شكل عرافة)", "seed_key": "مفتاح البذور", "seed_language": "لغة البذور", @@ -643,9 +647,13 @@ "seed_language_russian": "الروسية", "seed_language_spanish": "الأسبانية", "seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", + "seed_position_question_one": "ما هو", + "seed_position_question_two": "كلمة عبارة البذور؟", "seed_reminder": "يرجى تدوينها في حالة فقد هاتفك أو مسحه", "seed_share": "شارك السييد", "seed_title": "سييد", + "seed_verified": "تم التحقق من البذور", + "seed_verified_subtext": "يمكنك استخدام البذور المحفوظة لاحقًا لاستعادة هذه المحفظة في حالة الفساد أو فقدان جهازك. \n\n يمكنك عرض هذه البذرة مرة أخرى من", "seedtype": "البذور", "seedtype_alert_content": "مشاركة البذور مع محافظ أخرى ممكن فقط مع BIP39 Seedtype.", "seedtype_alert_title": "تنبيه البذور", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", "verification": "تَحَقّق", "verify_message": "تحقق من الرسالة", + "verify_seed": "تحقق من البذور", "verify_with_2fa": "تحقق مع Cake 2FA", "version": "الإصدار ${currentVersion}", "view_all": "مشاهدة الكل", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 650480044..9d86f74e4 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -366,6 +366,8 @@ "in_store": "In Store", "incoming": "Входящи", "incorrect_seed": "Въведеният текст е невалиден.", + "incorrect_seed_option": "Неправилно. Моля, опитайте отново", + "incorrect_seed_option_back": "Неправилно. Моля, уверете се, че семето ви е запазено правилно и опитайте отново.", "inputs": "Входове", "insufficient_funds_for_tx": "Недостатъчни средства за успешно извършване на транзакция.", "insufficient_lamport_for_tx": "Нямате достатъчно SOL, за да покриете транзакцията и таксата му за транзакция. Моля, добавете повече SOL към портфейла си или намалете сумата на SOL, която изпращате.", @@ -475,6 +477,7 @@ "online": "Онлайн", "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", "open_gift_card": "Отвори Gift Card", + "open_wallet": "Отворен портфейл", "optional_description": "Описание по избор", "optional_email_hint": "Незадължителен имейл за уведомяване на получателя", "optional_name": "Незадължително име на получател", @@ -625,6 +628,7 @@ "seed_alert_title": "Внимание", "seed_alert_yes": "Да", "seed_choose": "Изберете език на seed-а", + "seed_display_path": "Меню -> Сигурност и архивиране -> Показване на ключ/семена", "seed_hex_form": "Семена от портфейл (шестнадесетична форма)", "seed_key": "Ключ за семена", "seed_language": "Език на семената", @@ -643,9 +647,13 @@ "seed_language_russian": "Руски", "seed_language_spanish": "Испански", "seed_phrase_length": "Дължина на началната фраза", + "seed_position_question_one": "Какво е", + "seed_position_question_two": "Дума на вашата фраза за семена?", "seed_reminder": "Моля, запишете го в случай на загуба на устройството.", "seed_share": "Споделяне на seed", "seed_title": "Seed", + "seed_verified": "Семена проверено", + "seed_verified_subtext": "Можете да използвате запазените си семена по -късно, за да възстановите този портфейл в случай на корупция или загуба на устройството си. \n\n Можете да видите това семе отново от", "seedtype": "Семенна тип", "seedtype_alert_content": "Споделянето на семена с други портфейли е възможно само с BIP39 Seedtype.", "seedtype_alert_title": "Сигнал за семена", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", "verification": "Потвърждаване", "verify_message": "Проверете съобщението", + "verify_seed": "Проверете семената", "verify_with_2fa": "Проверете с Cake 2FA", "version": "Версия ${currentVersion}", "view_all": "Виж всички", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 9f5897046..25a4845d9 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -366,6 +366,8 @@ "in_store": "V obchodě", "incoming": "Příchozí", "incorrect_seed": "Zadaný text není správný.", + "incorrect_seed_option": "Nesprávný. Zkuste to prosím znovu", + "incorrect_seed_option_back": "Nesprávný. Ujistěte se, že vaše semeno je správně uloženo a zkuste to znovu.", "inputs": "Vstupy", "insufficient_funds_for_tx": "Nedostatečné prostředky na úspěšné provedení transakce.", "insufficient_lamport_for_tx": "Nemáte dostatek SOL na pokrytí transakce a jejího transakčního poplatku. Laskavě přidejte do své peněženky více solu nebo snižte množství Sol, kterou odesíláte.", @@ -475,6 +477,7 @@ "online": "Online", "onramper_option_description": "Rychle si koupte krypto s mnoha metodami plateb. K dispozici ve většině zemí. Rozpětí a poplatky se liší.", "open_gift_card": "Otevřít dárkovou kartu", + "open_wallet": "Otevřená peněženka", "optional_description": "Volitelný popis", "optional_email_hint": "Volitelný e-mail s upozorněním na příjemce platby", "optional_name": "Volitelné jméno příjemce", @@ -625,6 +628,7 @@ "seed_alert_title": "Pozor", "seed_alert_yes": "Ano", "seed_choose": "Zvolte si jazyk seedu", + "seed_display_path": "Nabídka -> Zabezpečení a zálohování -> Zobrazit klíč/semena", "seed_hex_form": "Semeno peněženky (hex formulář)", "seed_key": "Klíč semen", "seed_language": "Jazyk semen", @@ -643,9 +647,13 @@ "seed_language_russian": "Ruština", "seed_language_spanish": "Španělština", "seed_phrase_length": "Délka fráze semene", + "seed_position_question_one": "Co je", + "seed_position_question_two": "Slovo vaší fráze semen?", "seed_reminder": "Prosím zapište si toto pro případ ztráty, nebo poškození telefonu", "seed_share": "Sdílet seed", "seed_title": "Seed", + "seed_verified": "Ověřeno semeno", + "seed_verified_subtext": "V případě korupce nebo ztráty zařízení můžete později použít své uložené semeno později k obnovení této peněženky.", "seedtype": "SeedType", "seedtype_alert_content": "Sdílení semen s jinými peněženkami je možné pouze u BIP39 SeedType.", "seedtype_alert_title": "Upozornění seedtype", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", "verification": "Ověření", "verify_message": "Ověřit zprávu", + "verify_seed": "Ověřte osivo", "verify_with_2fa": "Ověřte pomocí Cake 2FA", "version": "Verze ${currentVersion}", "view_all": "Zobrazit vše", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 227e84d21..cf44ab05d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -366,6 +366,8 @@ "in_store": "Im Geschäft", "incoming": "Eingehend", "incorrect_seed": "Der eingegebene Text ist ungültig.", + "incorrect_seed_option": "Falsch. Bitte versuchen Sie es erneut", + "incorrect_seed_option_back": "Falsch. Bitte stellen Sie sicher, dass Ihr Samen korrekt gespeichert wird, und versuchen Sie es erneut.", "inputs": "Eingänge", "insufficient_funds_for_tx": "Unzureichende Mittel zur erfolgreichen Ausführung der Transaktion.", "insufficient_lamport_for_tx": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Bitte fügen Sie Ihrer Wallet mehr Sol hinzu oder reduzieren Sie die SOL-Menge, die Sie senden.", @@ -475,6 +477,7 @@ "online": "online", "onramper_option_description": "Kaufen Sie schnell Krypto mit vielen Zahlungsmethoden. In den meisten Ländern erhältlich. Spreads und Gebühren variieren.", "open_gift_card": "Geschenkkarte öffnen", + "open_wallet": "Offener Brieftasche", "optional_description": "Optionale Beschreibung", "optional_email_hint": "Optionale Benachrichtigungs-E-Mail für den Zahlungsempfänger", "optional_name": "Optionaler Empfängername", @@ -626,6 +629,7 @@ "seed_alert_title": "Achtung", "seed_alert_yes": "Ja, habe ich", "seed_choose": "Seed-Sprache auswählen", + "seed_display_path": "Menü -> Sicherheit und Sicherung -> Schlüssel/Samen anzeigen", "seed_hex_form": "Seed (Hexformat)", "seed_key": "Seed-Schlüssel", "seed_language": "Seed-Sprache", @@ -644,9 +648,13 @@ "seed_language_russian": "Russisch", "seed_language_spanish": "Spanisch", "seed_phrase_length": "Länge der Seed-Phrase", + "seed_position_question_one": "Was ist das", + "seed_position_question_two": "Wort Ihrer Samenphrase?", "seed_reminder": "Bitte notieren Sie diese für den Fall, dass Sie Ihr Telefon verlieren oder es kaputtgeht", "seed_share": "Seed teilen", "seed_title": "Seed", + "seed_verified": "Samen verifiziert", + "seed_verified_subtext": "Sie können Ihren gespeicherten Saat", "seedtype": "Seedtyp", "seedtype_alert_content": "Das Teilen von Seeds mit anderen Wallet ist nur mit bip39 Seedype möglich.", "seedtype_alert_title": "Seedype-Alarm", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", "verification": "Verifizierung", "verify_message": "Nachricht überprüfen", + "verify_seed": "Saatgut überprüfen", "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", "version": "Version ${currentVersion}", "view_all": "Alle anzeigen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3d1255ce2..69ba98f34 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -366,6 +366,8 @@ "in_store": "In Store", "incoming": "Incoming", "incorrect_seed": "The text entered is not valid.", + "incorrect_seed_option": "Incorrect. Please try again", + "incorrect_seed_option_back": "Incorrect. Please make sure your seed is saved correctly and try again.", "inputs": "Inputs", "insufficient_funds_for_tx": "Insufficient funds to successfully execute transaction.", "insufficient_lamport_for_tx": "You do not have enough SOL to cover the transaction and its transaction fee. Kindly add more SOL to your wallet or reduce the SOL amount you\\'re sending.", @@ -475,6 +477,7 @@ "online": "Online", "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", "open_gift_card": "Open Gift Card", + "open_wallet": "Open Wallet", "optional_description": "Optional description", "optional_email_hint": "Optional payee notification email", "optional_name": "Optional recipient name", @@ -625,6 +628,7 @@ "seed_alert_title": "Attention", "seed_alert_yes": "Yes, I have", "seed_choose": "Choose seed language", + "seed_display_path": "Menu -> Security and Backup -> Show key/seeds", "seed_hex_form": "Wallet seed (hex form)", "seed_key": "Seed key", "seed_language": "Seed language", @@ -643,9 +647,13 @@ "seed_language_russian": "Russian", "seed_language_spanish": "Spanish", "seed_phrase_length": "Seed phrase length", + "seed_position_question_one": "What is the", + "seed_position_question_two": "word of your seed phrase?", "seed_reminder": "Please write these down in case you lose or wipe your phone", "seed_share": "Share seed", "seed_title": "Seed", + "seed_verified": "Seed Verified", + "seed_verified_subtext": "You can use your saved seed later on to restore this wallet in the event of corruption or losing your device.\n\nYou can view this seed again from the", "seedtype": "Seedtype", "seedtype_alert_content": "Sharing seeds with other wallets is only possible with BIP39 SeedType.", "seedtype_alert_title": "SeedType Alert", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", "verification": "Verification", "verify_message": "Verify Message", + "verify_seed": "Verify Seed", "verify_with_2fa": "Verify with Cake 2FA", "version": "Version ${currentVersion}", "view_all": "View all", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 797cecdd0..3ab98c5f5 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -366,6 +366,8 @@ "in_store": "En la tienda", "incoming": "Entrante", "incorrect_seed": "El texto ingresado no es válido.", + "incorrect_seed_option": "Incorrecto. Por favor intente de nuevo", + "incorrect_seed_option_back": "Incorrecto. Asegúrese de que su semilla se guarde correctamente e intente nuevamente.", "inputs": "Entradas", "insufficient_funds_for_tx": "Fondos insuficientes para ejecutar con éxito la transacción.", "insufficient_lamport_for_tx": "No tienes suficiente SOL para cubrir la transacción y su tarifa de transacción. Por favor, agrega más SOL a su billetera o reduce la cantidad de sol que está enviando.", @@ -475,6 +477,7 @@ "online": "En línea", "onramper_option_description": "Compra rápidamente cripto con muchos métodos de pago. Disponible en la mayoría de los países. Los diferenciales y las tarifas varían.", "open_gift_card": "Abrir tarjeta de regalo", + "open_wallet": "Billetera abierta", "optional_description": "Descripción opcional", "optional_email_hint": "Correo electrónico de notificación del beneficiario opcional", "optional_name": "Nombre del destinatario opcional", @@ -626,6 +629,7 @@ "seed_alert_title": "Atención", "seed_alert_yes": "Sí tengo", "seed_choose": "Elige el idioma semilla", + "seed_display_path": "Menú -> Seguridad y copia de seguridad -> Mostrar llave/semillas", "seed_hex_form": "Semilla de billetera (forma hexadecimal)", "seed_key": "Llave de semilla", "seed_language": "Lenguaje de semillas", @@ -644,9 +648,13 @@ "seed_language_russian": "Ruso", "seed_language_spanish": "Español", "seed_phrase_length": "Longitud de la frase inicial", + "seed_position_question_one": "¿Qué es el", + "seed_position_question_two": "¿Palabra de tu frase de semillas?", "seed_reminder": "Anótalos en caso de que pierdas o borres tu aplicación", "seed_share": "Compartir semillas", "seed_title": "Semilla", + "seed_verified": "Semilla verificada", + "seed_verified_subtext": "Puede usar su semilla guardada más adelante para restaurar esta billetera en caso de corrupción o perder su dispositivo. \n\n Puede ver esta semilla nuevamente desde el", "seedtype": "Tipos de semillas", "seedtype_alert_content": "Compartir semillas con otras billeteras solo es posible con semillas bip39 - un tipo específico de semilla.", "seedtype_alert_title": "Alerta de tipo de semillas", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", "verification": "Verificación", "verify_message": "Mensaje de verificación", + "verify_seed": "Verificar semilla", "verify_with_2fa": "Verificar con Cake 2FA", "version": "Versión ${currentVersion}", "view_all": "Ver todo", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 6a775a4f4..50fb6c3db 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -366,6 +366,8 @@ "in_store": "En magasin", "incoming": "Entrantes", "incorrect_seed": "Le texte entré est invalide.", + "incorrect_seed_option": "Incorrect. Veuillez réessayer", + "incorrect_seed_option_back": "Incorrect. Veuillez vous assurer que votre graine est enregistrée correctement et réessayer.", "inputs": "Contributions", "insufficient_funds_for_tx": "Fonds insuffisants pour exécuter avec succès la transaction.", "insufficient_lamport_for_tx": "Vous n'avez pas assez de sol pour couvrir la transaction et ses frais de transaction. Veuillez ajouter plus de Sol à votre portefeuille ou réduire la quantité de Sol que vous envoyez.", @@ -475,6 +477,7 @@ "online": "En ligne", "onramper_option_description": "Achetez rapidement des cryptomonnaies avec de nombreuses méthodes de paiement. Disponible dans la plupart des pays. Les spreads et les frais peuvent varier.", "open_gift_card": "Ouvrir la carte-cadeau", + "open_wallet": "Portefeuille ouvert", "optional_description": "Descriptif facultatif", "optional_email_hint": "E-mail de notification du bénéficiaire facultatif", "optional_name": "Nom du destinataire facultatif", @@ -625,6 +628,7 @@ "seed_alert_title": "Attention", "seed_alert_yes": "Oui, je suis sûr", "seed_choose": "Choisissez la langue de la phrase secrète (seed)", + "seed_display_path": "Menu -> Sécurité et sauvegarde -> Afficher la clé / les graines", "seed_hex_form": "Graine du portefeuille (forme hexagonale)", "seed_key": "Clé secrète (seed key)", "seed_language": "Langage de la phrase secrète", @@ -643,9 +647,13 @@ "seed_language_russian": "Russe", "seed_language_spanish": "Espagnol", "seed_phrase_length": "Longueur de la phrase de départ", + "seed_position_question_one": "Qu'est-ce que le", + "seed_position_question_two": "mot de votre phrase de semence?", "seed_reminder": "Merci d'écrire votre phrase secrète (seed) au cas où vous perdriez ou effaceriez votre téléphone", "seed_share": "Partager la phrase secrète (seed)", "seed_title": "Phrase secrète (seed)", + "seed_verified": "Graine vérifiée", + "seed_verified_subtext": "Vous pouvez utiliser votre graine enregistrée plus tard pour restaurer ce portefeuille en cas de corruption ou de perdre votre appareil. \n\n Vous pouvez revoir cette graine à partir du", "seedtype": "Type de graine", "seedtype_alert_content": "Le partage de graines avec d'autres portefeuilles n'est possible qu'avec le type de graine BIP39.", "seedtype_alert_title": "Alerte Type de Graine", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", "verification": "Vérification", "verify_message": "Vérifier le message", + "verify_seed": "Vérifiez les semences", "verify_with_2fa": "Vérifier avec Cake 2FA", "version": "Version ${currentVersion}", "view_all": "Voir tout", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 364c8a796..a532a54b7 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -366,6 +366,8 @@ "in_store": "A cikin Store", "incoming": "Mai shigowa", "incorrect_seed": "rubutun da aka shigar ba shi da inganci.", + "incorrect_seed_option": "Ba daidai ba. Da fatan za a sake gwadawa", + "incorrect_seed_option_back": "Ba daidai ba. Da fatan za a tabbatar da zuriyar ku an ajiye daidai kuma a sake gwadawa.", "inputs": "Abubuwan da ke ciki", "insufficient_funds_for_tx": "Rashin isasshen kuɗi don aiwatar da ma'amala.", "insufficient_lamport_for_tx": "Ba ku da isasshen sool don rufe ma'amala da kuɗin ma'amala. Da unara ƙara ƙarin sool a cikin walat ɗinku ko rage adadin Sol ɗin da kuke aikawa.", @@ -475,6 +477,7 @@ "online": "Kan layi", "onramper_option_description": "Da sauri sayi Crypto tare da hanyoyin biyan kuɗi da yawa. Akwai a yawancin ƙasashe. Yaduwa da kudade sun bambanta.", "open_gift_card": "Bude Katin Kyauta", + "open_wallet": "Bude Wadda", "openalias_alert_content": "Zaka aika kuɗi zuwa \n${recipient_name}", "openalias_alert_title": "An gano adireshin", "optional_description": "Bayanin zai iya ba da maki", @@ -627,6 +630,7 @@ "seed_alert_title": "Hankali", "seed_alert_yes": "E, Na yi", "seed_choose": "Zaɓi harshen seed", + "seed_display_path": "Ming menu -> Tsaro da Ajiyayyen -> Kaben Now / Duri", "seed_hex_form": "Gany Sero (form form)", "seed_key": "Maɓallin iri", "seed_language": "Harshen Magani", @@ -645,9 +649,13 @@ "seed_language_russian": "Rashanci", "seed_language_spanish": "Spanish", "seed_phrase_length": "Tsawon jimlar iri", + "seed_position_question_one": "Menene", + "seed_position_question_two": "Maganar Je'in Seedhniyarka?", "seed_reminder": "Don Allah rubuta wadannan in case ka manta ko ka sake kwallon wayarka", "seed_share": "Raba iri", "seed_title": "iri", + "seed_verified": "Iri", + "seed_verified_subtext": "Kuna iya amfani da zuriyar da kuka tsira daga baya don mayar da wannan walat ɗin a lokacin da ya faru na cin hanci da rashawa ko rasa na'urarka. \n\n Za ku iya duba wannan iri ɗin kuma daga", "seedtype": "Seedtype", "seedtype_alert_content": "Raba tsaba tare da sauran wallets yana yiwuwa ne kawai tare da Bip39 seedtype.", "seedtype_alert_title": "Seedtype farke", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", "verification": "tabbatar", "verify_message": "Tabbatar saƙon", + "verify_seed": "Tabbatar zuriya", "verify_with_2fa": "Tabbatar da Cake 2FA", "version": "Sigar ${currentVersion}", "view_all": "Duba duka", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 03fc08134..b20291df7 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -366,6 +366,8 @@ "in_store": "स्टोर में", "incoming": "आने वाली", "incorrect_seed": "दर्ज किया गया पाठ मान्य नहीं है।", + "incorrect_seed_option": "गलत। कृपया पुन: प्रयास करें", + "incorrect_seed_option_back": "गलत। कृपया सुनिश्चित करें कि आपका बीज सही तरीके से बच गया है और फिर से प्रयास करें।", "inputs": "इनपुट", "insufficient_funds_for_tx": "लेनदेन को सफलतापूर्वक निष्पादित करने के लिए अपर्याप्त धन।", "insufficient_lamport_for_tx": "आपके पास लेनदेन और इसके लेनदेन शुल्क को कवर करने के लिए पर्याप्त सोल नहीं है। कृपया अपने बटुए में अधिक सोल जोड़ें या आपके द्वारा भेजे जा रहे सोल राशि को कम करें।", @@ -475,6 +477,7 @@ "online": "ऑनलाइन", "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", "open_gift_card": "गिफ्ट कार्ड खोलें", + "open_wallet": "खुला बटुआ", "optional_description": "वैकल्पिक विवरण", "optional_email_hint": "वैकल्पिक प्राप्तकर्ता सूचना ईमेल", "optional_name": "वैकल्पिक प्राप्तकर्ता नाम", @@ -627,6 +630,7 @@ "seed_alert_title": "ध्यान", "seed_alert_yes": "हाँ मेरे पास है", "seed_choose": "बीज भाषा चुनें", + "seed_display_path": "मेनू -> सुरक्षा और बैकअप -> कुंजी/बीज दिखाएं", "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)", "seed_key": "बीज कुंजी", "seed_language": "बीज", @@ -645,9 +649,13 @@ "seed_language_russian": "रूसी", "seed_language_spanish": "स्पेनिश", "seed_phrase_length": "बीज वाक्यांश की लंबाई", + "seed_position_question_one": "क्या है", + "seed_position_question_two": "आपके बीज वाक्यांश का शब्द?", "seed_reminder": "यदि आप अपना फोन खो देते हैं या मिटा देते हैं तो कृपया इन्हें लिख लें", "seed_share": "बीज साझा करें", "seed_title": "बीज", + "seed_verified": "बीज सत्यापित", + "seed_verified_subtext": "आप भ्रष्टाचार की स्थिति में इस बटुए को पुनर्स्थापित करने या अपने डिवाइस को खोने के लिए बाद में अपने सहेजे गए बीज का उपयोग कर सकते हैं। \n\n आप इस बीज को फिर से देख सकते हैं", "seedtype": "बीज", "seedtype_alert_content": "अन्य पर्स के साथ बीज साझा करना केवल BIP39 सीडटाइप के साथ संभव है।", "seedtype_alert_title": "बीजगणित अलर्ट", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", "verification": "सत्यापन", "verify_message": "संदेश सत्यापित करें", + "verify_seed": "बीज सत्यापित करें", "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", "version": "संस्करण ${currentVersion}", "view_all": "सभी देखें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 58fef20f9..9b228d843 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -366,6 +366,8 @@ "in_store": "U trgovini", "incoming": "Dolazno", "incorrect_seed": "Uneseni tekst nije valjan.", + "incorrect_seed_option": "Netočno. Pokušajte ponovo", + "incorrect_seed_option_back": "Netočno. Provjerite je li vaše sjeme ispravno spasilo i pokušajte ponovo.", "inputs": "Unosi", "insufficient_funds_for_tx": "Nedovoljna sredstva za uspješno izvršavanje transakcije.", "insufficient_lamport_for_tx": "Nemate dovoljno SOL -a da pokriva transakciju i njegovu transakcijsku naknadu. Ljubazno dodajte više sol u svoj novčanik ili smanjite količinu SOL -a koju šaljete.", @@ -475,6 +477,7 @@ "online": "Na mreži", "onramper_option_description": "Brzo kupite kriptovalute s mnogim načinima plaćanja. Dostupno u većini zemalja. Širenja i naknade variraju.", "open_gift_card": "Otvori darovnu karticu", + "open_wallet": "Otvoreni novčanik", "optional_description": "Opcijski opis", "optional_email_hint": "Neobavezna e-pošta za obavijest primatelja", "optional_name": "Izborno ime primatelja", @@ -625,6 +628,7 @@ "seed_alert_title": "Upozorenje", "seed_alert_yes": "Jesam", "seed_choose": "Odaberi jezik pristupnog izraza", + "seed_display_path": "Izbornik -> Sigurnost i sigurnosna kopija -> Prikaži ključ/sjemenke", "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)", "seed_key": "Sjemenski ključ", "seed_language": "Sjemeni jezik", @@ -643,9 +647,13 @@ "seed_language_russian": "Ruski", "seed_language_spanish": "Španjolski", "seed_phrase_length": "Duljina početne fraze", + "seed_position_question_one": "Što je", + "seed_position_question_two": "Riječ vaše sjemenske fraze?", "seed_reminder": "Molimo zapišite ih u slučaju da izgubite mobitel ili izbrišete podatke", "seed_share": "Podijeli pristupni izraz", "seed_title": "Prisupni izraz", + "seed_verified": "Potvrđeno sjeme", + "seed_verified_subtext": "Svoje spremljeno sjeme možete kasnije koristiti za vraćanje ovog novčanika u slučaju korupcije ili gubitka uređaja. \n\n To sjeme možete ponovo pogledati iz", "seedtype": "Sjemenska vrsta", "seedtype_alert_content": "Dijeljenje sjemena s drugim novčanicima moguće je samo s BIP39 sjemenom.", "seedtype_alert_title": "Upozorenje o sjemenu", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", "verification": "Potvrda", "verify_message": "Provjerite poruku", + "verify_seed": "Provjerite sjeme", "verify_with_2fa": "Provjerite s Cake 2FA", "version": "Verzija ${currentVersion}", "view_all": "Prikaži sve", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 95da83928..668c99a14 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -366,6 +366,8 @@ "in_store": "Տեղում", "incoming": "Մուտքային", "incorrect_seed": "Տեքստը սխալ է", + "incorrect_seed_option": "Սխալ Խնդրում ենք կրկին փորձել", + "incorrect_seed_option_back": "Սխալ Խնդրում ենք համոզվեք, որ ձեր սերմը ճիշտ պահվում է եւ կրկին փորձեք:", "inputs": "Մուտքեր", "insufficient_funds_for_tx": "Անբավարար միջոցներ `գործարքը հաջողությամբ կատարելու համար:", "insufficient_lamport_for_tx": "Դուք չունեք բավարար SOL՝ գործարքն և գործարքի վարձը ծածկելու համար։ Խնդրում ենք ավելացնել ավելի շատ SOL ձեր դրամապանակում կամ նվազեցնել ուղարկվող SOL-ի քանակը։", @@ -475,6 +477,7 @@ "online": "Առցանց", "onramper_option_description": "Արագ գնեք կրիպտոցուլեր շատ վճարման մեթոդներով։ Հասանելի է մեծ մասամբ երկրներում։ Տարածված և վճարները փոփոխվում են", "open_gift_card": "Բացեք նվեր քարտ", + "open_wallet": "Բաց դրամապանակ", "optional_description": "Ոչ պարտադիր նկարագրություն", "optional_email_hint": "Ոչ պարտադիր վճարողի ծանուցման էլեկտրոնային փոստ", "optional_name": "Ոչ պարտադիր ստացողի անուն", @@ -625,6 +628,7 @@ "seed_alert_title": "Ուշադրություն", "seed_alert_yes": "Այո, ես արդեն գրի եմ առել այն", "seed_choose": "Ընտրել սերմի լեզուն", + "seed_display_path": "MENU -> Անվտանգություն եւ պահուստավորում -> Show ույց տալ ստեղնը / սերմերը", "seed_hex_form": "Դրամապանակի սերմ (hex ֆորմատ)", "seed_key": "Սերմի բանալի", "seed_language": "Սերմի լեզու", @@ -643,9 +647,13 @@ "seed_language_russian": "Ռուսերեն", "seed_language_spanish": "Իսպաներեն", "seed_phrase_length": "Սերմի արտահայտության երկարություն", + "seed_position_question_one": "Ինչ է", + "seed_position_question_two": "Ձեր սերմի արտահայտության խոսքը:", "seed_reminder": "Խնդրում ենք գրի առնել այս տեղեկությունը, եթե դուք կորցնեք կամ ջնջեք ձեր հեռախոսը", "seed_share": "Կիսվել սերմով", "seed_title": "Սերմ", + "seed_verified": "SEED- ը հաստատեց", + "seed_verified_subtext": "Դուք կարող եք ավելի ուշ օգտագործել ձեր պահպանված սերմը `վերականգնելու այս դրամապանակը կոռուպցիայի դեպքում կամ ձեր սարքը կորցնելու դեպքում: \n\n կարող եք կրկին դիտել այս սերմը", "seedtype": "Սերմի տեսակ", "seedtype_alert_content": "Այլ դրամապանակներով սերմերի փոխանակումը հնարավոր է միայն BIP39 SEEDTYPE- ով:", "seedtype_alert_title": "SEEDTYPE ALERT", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Այս փոփոխականի զույգը չի աջակցվում ընտրված բորսաների հետ", "verification": "Ստուգում", "verify_message": "Ստուգել հաղորդագրությունը", + "verify_seed": "Ստուգեք սերմը", "verify_with_2fa": "Ստուգեք Cake 2FA-ով", "version": "Տարբերակ ${currentVersion}", "view_all": "Դիտել բոլորը", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c275a70df..3102ea2e0 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -366,6 +366,8 @@ "in_store": "Di Toko", "incoming": "Masuk", "incorrect_seed": "Teks yang dimasukkan tidak valid.", + "incorrect_seed_option": "Salah. Tolong coba lagi", + "incorrect_seed_option_back": "Salah. Pastikan benih Anda disimpan dengan benar dan coba lagi.", "inputs": "Input", "insufficient_funds_for_tx": "Dana yang tidak mencukupi untuk berhasil menjalankan transaksi.", "insufficient_lamport_for_tx": "Anda tidak memiliki cukup SOL untuk menutupi transaksi dan biaya transaksinya. Mohon tambahkan lebih banyak sol ke dompet Anda atau kurangi jumlah sol yang Anda kirim.", @@ -475,6 +477,7 @@ "online": "Online", "onramper_option_description": "Beli crypto dengan cepat dengan banyak metode pembayaran. Tersedia di sebagian besar negara. Spread dan biaya bervariasi.", "open_gift_card": "Buka Kartu Hadiah", + "open_wallet": "Dompet Buka", "openalias_alert_content": "Anda akan mengirim dana ke\n${recipient_name}", "openalias_alert_title": "Alamat Terdeteksi", "optional_description": "Deskripsi opsional", @@ -628,6 +631,7 @@ "seed_alert_title": "Perhatian", "seed_alert_yes": "Ya, sudah", "seed_choose": "Pilih bahasa bibit", + "seed_display_path": "Menu -> Keamanan dan Cadangan -> Tampilkan kunci/biji", "seed_hex_form": "Biji dompet (bentuk hex)", "seed_key": "Kunci benih", "seed_language": "Bahasa benih", @@ -646,9 +650,13 @@ "seed_language_russian": "Rusia", "seed_language_spanish": "Spanyol", "seed_phrase_length": "Panjang frase benih", + "seed_position_question_one": "Apakah yang", + "seed_position_question_two": "Kata frasa benih Anda?", "seed_reminder": "Silakan tulis ini di tempat yang aman jika kamu kehilangan atau menghapus ponselmu", "seed_share": "Bagikan bibit", "seed_title": "Bibit", + "seed_verified": "Benih diverifikasi", + "seed_verified_subtext": "Anda dapat menggunakan benih yang disimpan nanti untuk mengembalikan dompet ini jika terjadi korupsi atau kehilangan perangkat Anda. \n\n Anda dapat melihat benih ini lagi dari", "seedtype": "Seedtype", "seedtype_alert_content": "Berbagi biji dengan dompet lain hanya dimungkinkan dengan BIP39 seedtype.", "seedtype_alert_title": "Peringatan seedtype", @@ -905,6 +913,7 @@ "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", "verification": "Verifikasi", "verify_message": "Verifikasi pesan", + "verify_seed": "Verifikasi benih", "verify_with_2fa": "Verifikasi dengan Cake 2FA", "version": "Versi ${currentVersion}", "view_all": "Lihat Semua", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 2d3561144..cbeaa191d 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -367,6 +367,8 @@ "in_store": "In negozio", "incoming": "In arrivo", "incorrect_seed": "Il testo inserito non è valido.", + "incorrect_seed_option": "Errato. Per favore riprova", + "incorrect_seed_option_back": "Errato. Assicurati che il tuo seme venga salvato correttamente e riprova.", "inputs": "Input", "insufficient_funds_for_tx": "Fondi insufficienti per eseguire correttamente la transazione.", "insufficient_lamport_for_tx": "Non hai abbastanza SOL per coprire la transazione e la sua quota di transazione. Si prega di aggiungere più SOL al tuo portafoglio o ridurre l'importo SOL che stai inviando.", @@ -476,6 +478,7 @@ "online": "in linea", "onramper_option_description": "Acquista rapidamente la criptovaluta con molti metodi di pagamento. Disponibile nella maggior parte dei paesi. Gli spread e le commissioni variano.", "open_gift_card": "Apri carta regalo", + "open_wallet": "Portafoglio aperto", "optional_description": "Descrizione facoltativa", "optional_email_hint": "Email di notifica del beneficiario facoltativa", "optional_name": "Nome del destinatario facoltativo", @@ -627,6 +630,7 @@ "seed_alert_title": "Attenzione", "seed_alert_yes": "Sì, l'ho fatto", "seed_choose": "Scegli la lingua del seme", + "seed_display_path": "Menu -> Sicurezza e backup -> Mostra chiave/Semi", "seed_hex_form": "Seme di portafoglio (forma esadecimale)", "seed_key": "Chiave di semi", "seed_language": "Linguaggio di semi", @@ -645,9 +649,13 @@ "seed_language_russian": "Russo", "seed_language_spanish": "Spagnolo", "seed_phrase_length": "Lunghezza della frase seed", + "seed_position_question_one": "Qual è il", + "seed_position_question_two": "Parola della tua frase di semi?", "seed_reminder": "Gentilmente trascrivi le parole. Ti tornerà utile in caso perdessi o ripristinassi il tuo telefono", "seed_share": "Condividi seme", "seed_title": "Seme", + "seed_verified": "Semi verificato", + "seed_verified_subtext": "Puoi usare il tuo seme salvato in seguito per ripristinare questo portafoglio in caso di corruzione o perdere il dispositivo. \n\n Puoi visualizzare di nuovo questo seme dal", "seedtype": "Seedtype", "seedtype_alert_content": "La condivisione di semi con altri portafogli è possibile solo con Bip39 SeedType.", "seedtype_alert_title": "Avviso seedType", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", "verification": "Verifica", "verify_message": "Verificare il messaggio", + "verify_seed": "Verifica il seme", "verify_with_2fa": "Verifica con Cake 2FA", "version": "Versione ${currentVersion}", "view_all": "Visualizza tutto", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 6c0a8f8f3..95ae7b672 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -367,6 +367,8 @@ "in_store": "インストア", "incoming": "着信", "incorrect_seed": "入力されたテキストは無効です。", + "incorrect_seed_option": "正しくない。もう一度やり直してください", + "incorrect_seed_option_back": "正しくない。種子が正しく保存されていることを確認し、再試行してください。", "inputs": "入力", "insufficient_funds_for_tx": "トランザクションを正常に実行するための資金が不十分です。", "insufficient_lamport_for_tx": "トランザクションとその取引手数料をカバーするのに十分なSOLがありません。財布にソルを追加するか、送信するソル量を減らしてください。", @@ -476,6 +478,7 @@ "online": "オンライン", "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", "open_gift_card": "オープンギフトカード", + "open_wallet": "開いたウォレット", "optional_description": "オプションの説明", "optional_email_hint": "オプションの受取人通知メール", "optional_name": "オプションの受信者名", @@ -626,6 +629,7 @@ "seed_alert_title": "注意", "seed_alert_yes": "はい、あります", "seed_choose": "シード言語を選択してください", + "seed_display_path": "メニュー - >セキュリティとバックアップ - >キー/シードを表示します", "seed_hex_form": "ウォレットシード(ヘックスフォーム)", "seed_key": "シードキー", "seed_language": "シード言語", @@ -644,9 +648,13 @@ "seed_language_russian": "ロシア", "seed_language_spanish": "スペイン語", "seed_phrase_length": "シードフレーズの長さ", + "seed_position_question_one": "何ですか", + "seed_position_question_two": "あなたの種のフレーズの言葉?", "seed_reminder": "スマートフォンを紛失したりワイプした場合に備えて、これらを書き留めてください", "seed_share": "シードを共有する", "seed_title": "シード", + "seed_verified": "種子確認済み", + "seed_verified_subtext": "後で保存された種子を使用して、腐敗やデバイスの紛失の場合にこの財布を復元することができます。\n\nこのシードを再度見ることができます", "seedtype": "SeedType", "seedtype_alert_content": "他の財布と種子を共有することは、BIP39 SeedTypeでのみ可能です。", "seedtype_alert_title": "SeedTypeアラート", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", "verification": "検証", "verify_message": "メッセージを確認します", + "verify_seed": "シードを確認します", "verify_with_2fa": "Cake 2FA で検証する", "version": "バージョン ${currentVersion}", "view_all": "すべて表示", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2f1684b5a..4e9a7cff7 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -366,6 +366,8 @@ "in_store": "매장 내", "incoming": "들어오는", "incorrect_seed": "입력하신 텍스트가 유효하지 않습니다.", + "incorrect_seed_option": "잘못된. 다시 시도하십시오", + "incorrect_seed_option_back": "잘못된. 씨앗이 올바르게 저장되어 있는지 확인하고 다시 시도하십시오.", "inputs": "입력", "insufficient_funds_for_tx": "거래를 성공적으로 실행하기위한 자금이 충분하지 않습니다.", "insufficient_lamport_for_tx": "거래 및 거래 수수료를 충당하기에 충분한 SOL이 없습니다. 지갑에 더 많은 솔을 추가하거나 보내는 솔을 줄입니다.", @@ -475,6 +477,7 @@ "online": "온라인", "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", "open_gift_card": "기프트 카드 열기", + "open_wallet": "오픈 지갑", "optional_description": "선택적 설명", "optional_email_hint": "선택적 수취인 알림 이메일", "optional_name": "선택적 수신자 이름", @@ -626,6 +629,7 @@ "seed_alert_title": "주의", "seed_alert_yes": "네, 있어요", "seed_choose": "시드 언어를 선택하십시오", + "seed_display_path": "메뉴 -> 보안 및 백업 -> 키/씨앗 표시", "seed_hex_form": "지갑 씨앗 (16 진 양식)", "seed_key": "시드 키", "seed_language": "종자 언어", @@ -644,9 +648,13 @@ "seed_language_russian": "러시아인", "seed_language_spanish": "스페인의", "seed_phrase_length": "시드 문구 길이", + "seed_position_question_one": "무엇입니까", + "seed_position_question_two": "당신의 씨앗 문구의 말?", "seed_reminder": "휴대 전화를 분실하거나 닦을 경우를 대비해 적어 두세요.", "seed_share": "시드 공유", "seed_title": "씨", + "seed_verified": "종자 확인", + "seed_verified_subtext": "나중에 저장된 씨앗을 사용하여 부패 또는 장치를 잃을 때이 지갑을 복원 할 수 있습니다.\n\n이 씨앗을 다시 볼 수 있습니다.", "seedtype": "시드 타입", "seedtype_alert_content": "다른 지갑과 씨앗을 공유하는 것은 BIP39 SeedType에서만 가능합니다.", "seedtype_alert_title": "종자 경보", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", "verification": "검증", "verify_message": "메시지를 확인하십시오", + "verify_seed": "씨앗을 확인하십시오", "verify_with_2fa": "케이크 2FA로 확인", "version": "버전 ${currentVersion}", "view_all": "모두 보기", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index ed5e91fce..c73db85dd 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -366,6 +366,8 @@ "in_store": "စတိုးတွင်", "incoming": "ဝင်လာ", "incorrect_seed": "ထည့်သွင်းထားသော စာသားသည် မမှန်ကန်ပါ။", + "incorrect_seed_option": "မမှန်ကန်ပါ ကျေးဇူးပြုပြီးထပ်ကြိုးစားပါ", + "incorrect_seed_option_back": "မမှန်ကန်ပါ သင်၏မျိုးစေ့ကိုမှန်ကန်စွာသိမ်းဆည်းပြီးထပ်မံကြိုးစားပါ။", "inputs": "သွင်းငေှ", "insufficient_funds_for_tx": "ငွေပေးငွေယူအောင်မြင်စွာလုပ်ဆောင်ရန်ရန်ပုံငွေမလုံလောက်ပါ။", "insufficient_lamport_for_tx": "သငျသညျငွေပေးငွေယူနှင့်၎င်း၏ငွေပေးငွေယူကြေးကိုဖုံးလွှမ်းရန် sol ရှိသည်မဟုတ်ကြဘူး။ ကြင်နာစွာသင်၏ပိုက်ဆံအိတ်သို့ပိုမို sol ကိုထပ်ထည့်ပါသို့မဟုတ်သင်ပို့လွှတ်ခြင်း sol ပမာဏကိုလျှော့ချပါ။", @@ -475,6 +477,7 @@ "online": "အွန်လိုင်း", "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", "open_gift_card": "Gift Card ကိုဖွင့်ပါ။", + "open_wallet": "ပွင့်လင်းပိုက်ဆံအိတ်", "optional_description": "ရွေးချယ်နိုင်သော ဖော်ပြချက်", "optional_email_hint": "ရွေးချယ်နိုင်သော ငွေလက်ခံသူ အကြောင်းကြားချက် အီးမေးလ်", "optional_name": "ရွေးချယ်နိုင်သော လက်ခံသူအမည်", @@ -625,6 +628,7 @@ "seed_alert_title": "အာရုံ", "seed_alert_yes": "ဟုတ်ကဲ့၊", "seed_choose": "မျိုးစေ့ဘာသာစကားကို ရွေးချယ်ပါ။", + "seed_display_path": "Menu -> Security နှင့် Backup -> သော့ / အစေ့များကိုပြပါ", "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)", "seed_key": "မျိုးစေ့သော့", "seed_language": "မျိုးစေ့ဘာသာ", @@ -643,9 +647,13 @@ "seed_language_russian": "ရုရှ", "seed_language_spanish": "ငပိ", "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", + "seed_position_question_one": "ဘာလဲ", + "seed_position_question_two": "သင်၏အမျိုးအနွယ်စကားစု၏စကားဟူမူကား,", "seed_reminder": "ကျေးဇူးပြု၍ သင့်ဖုန်းကို ပျောက်ဆုံးသွားပါက သို့မဟုတ် ဖျက်မိပါက ၎င်းတို့ကို ချရေးပါ။", "seed_share": "မျိုးစေ့မျှဝေပါ။", "seed_title": "မျိုးစေ့", + "seed_verified": "မျိုးစေ့အတည်ပြု", + "seed_verified_subtext": "နောက်မှသင်သိမ်းဆည်းထားသောမျိုးစေ့ကိုနောက်ပိုင်းတွင်ဤပိုက်ဆံအိတ်ကိုအဂတိလိုက်စားမှုသို့မဟုတ်သင်၏စက်ပစ္စည်းကိုဆုံးရှုံးစေသည့်အခါဤပိုက်ဆံအိတ်ကိုပြန်ယူရန်နောက်မှသင်အသုံးပြုနိုင်သည်။ \n\n ဤမျိုးစေ့ကိုနောက်တဖန်ကြည့်ရှုနိုင်သည်", "seedtype": "မျိုးပွားခြင်း", "seedtype_alert_content": "အခြားပိုက်ဆံအိတ်များနှင့်မျိုးစေ့များကိုမျှဝေခြင်းသည် BIP39 sebyspe ဖြင့်သာဖြစ်သည်။", "seedtype_alert_title": "ပျိုးပင်သတိပေးချက်", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", "verification": "စိစစ်ခြင်း။", "verify_message": "မက်ဆေ့ခ်ျကိုအတည်ပြုရန်", + "verify_seed": "မျိုးစေ့ကိုစစ်ဆေးပါ", "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", "version": "ဗားရှင်း ${currentVersion}", "view_all": "အားလုံးကိုကြည့်ရှုပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index bc3106b28..367b8f625 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -366,6 +366,8 @@ "in_store": "In winkel", "incoming": "inkomend", "incorrect_seed": "De ingevoerde tekst is niet geldig.", + "incorrect_seed_option": "Onjuist. Probeer het opnieuw", + "incorrect_seed_option_back": "Onjuist. Zorg ervoor dat uw zaad correct is opgeslagen en probeer het opnieuw.", "inputs": "Invoer", "insufficient_funds_for_tx": "Onvoldoende fondsen om de transactie met succes uit te voeren.", "insufficient_lamport_for_tx": "U hebt niet genoeg SOL om de transactie en de transactiekosten te dekken. Voeg vriendelijk meer SOL toe aan uw portemonnee of verminder de SOL -hoeveelheid die u verzendt.", @@ -475,6 +477,7 @@ "online": "online", "onramper_option_description": "Koop snel crypto met veel betaalmethoden. Beschikbaar in de meeste landen. Spreads en vergoedingen variëren.", "open_gift_card": "Geschenkkaart openen", + "open_wallet": "Open portemonnee", "optional_description": "Optionele beschrijving", "optional_email_hint": "Optionele kennisgeving per e-mail aan de begunstigde", "optional_name": "Optionele naam ontvanger", @@ -625,6 +628,7 @@ "seed_alert_title": "Aandacht", "seed_alert_yes": "Ja ik heb", "seed_choose": "Kies een starttaal", + "seed_display_path": "Menu -> Beveiliging en back -up -> Key/Seeds tonen", "seed_hex_form": "Portemonnee zaad (hexvorm)", "seed_key": "Zaadsleutel", "seed_language": "Zaadtaal", @@ -643,9 +647,13 @@ "seed_language_russian": "Russisch", "seed_language_spanish": "Spaans", "seed_phrase_length": "Lengte van de zaadzin", + "seed_position_question_one": "Wat is de", + "seed_position_question_two": "woord van je zaadzin?", "seed_reminder": "Schrijf deze op voor het geval u uw telefoon kwijtraakt of veegt", "seed_share": "Deel zaad", "seed_title": "Zaad", + "seed_verified": "Zaad geverifieerd", + "seed_verified_subtext": "U kunt uw opgeslagen zaad later gebruiken om deze portemonnee te herstellen in het geval van corruptie of het verliezen van uw apparaat. \n\n U kunt dit zaad opnieuw bekijken van de", "seedtype": "Zaadtype", "seedtype_alert_content": "Het delen van zaden met andere portefeuilles is alleen mogelijk met BIP39 SeedType.", "seedtype_alert_title": "Zaadtype alert", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", "verification": "Verificatie", "verify_message": "Verifieer bericht", + "verify_seed": "Controleer zaad", "verify_with_2fa": "Controleer met Cake 2FA", "version": "Versie ${currentVersion}", "view_all": "Alles bekijken", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 947b1bc6e..ad797bb24 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -366,6 +366,8 @@ "in_store": "W Sklepie", "incoming": "Przychodzące", "incorrect_seed": "Wprowadzony seed jest nieprawidłowy.", + "incorrect_seed_option": "Błędny. Spróbuj ponownie", + "incorrect_seed_option_back": "Błędny. Upewnij się, że twoje ziarno jest prawidłowo zapisane i spróbuj ponownie.", "inputs": "Wejścia", "insufficient_funds_for_tx": "Niewystarczające fundusze na skuteczne wykonanie transakcji.", "insufficient_lamport_for_tx": "Nie masz wystarczającej ilości SOL, aby pokryć transakcję i opłatę za transakcję. Uprzejmie dodaj więcej sol do portfela lub zmniejsz wysyłaną kwotę SOL.", @@ -475,6 +477,7 @@ "online": "online", "onramper_option_description": "Szybko kup kryptowaluty z wieloma metodami płatności. Dostępne w większości krajów. Spready i opłaty różnią się.", "open_gift_card": "Otwórz kartę podarunkową", + "open_wallet": "Otwarty portfel", "optional_description": "Opcjonalny opis", "optional_email_hint": "Opcjonalny e-mail z powiadomieniem odbiorcy płatności", "optional_name": "Opcjonalna nazwa odbiorcy", @@ -625,6 +628,7 @@ "seed_alert_title": "Uwaga", "seed_alert_yes": "Tak", "seed_choose": "Wybierz język", + "seed_display_path": "Menu -> Bezpieczeństwo i kopia zapasowa -> Pokaż klucz/nasiona", "seed_hex_form": "Nasiona portfela (forma sześciokątna)", "seed_key": "Klucz nasion", "seed_language": "Język nasion", @@ -643,9 +647,13 @@ "seed_language_russian": "Rosyjski", "seed_language_spanish": "Hiszpański", "seed_phrase_length": "Długość frazy początkowej", + "seed_position_question_one": "Co to jest", + "seed_position_question_two": "Słowo twojego wyrażenia nasion?", "seed_reminder": "Musisz zapisać tą fraze, bo bez niej możesz nie odzyskać portfela!", "seed_share": "Udostępnij seed", "seed_title": "Seed", + "seed_verified": "Ziarno zweryfikowane", + "seed_verified_subtext": "Możesz później użyć zapisanego ziarna, aby przywrócić ten portfel w przypadku uszkodzenia lub utraty urządzenia. \n\n Możesz ponownie obejrzeć to ziarno z", "seedtype": "Sedtype", "seedtype_alert_content": "Dzielenie się nasionami z innymi portfelami jest możliwe tylko z BIP39 sededType.", "seedtype_alert_title": "Ustanowienie typu sedype", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", "verification": "Weryfikacja", "verify_message": "Sprawdź wiadomość", + "verify_seed": "Zweryfikować ziarno", "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", "version": "Wersja ${currentVersion}", "view_all": "Wyświetl wszystko", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 87ecf3f23..d9df7e2ee 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -366,6 +366,8 @@ "in_store": "Na loja", "incoming": "Recebidas", "incorrect_seed": "O texto digitado não é válido.", + "incorrect_seed_option": "Incorreto. Por favor, tente novamente", + "incorrect_seed_option_back": "Incorreto. Certifique -se de que sua semente seja salva corretamente e tente novamente.", "inputs": "Entradas", "insufficient_funds_for_tx": "Fundos insuficientes para executar com sucesso a transação.", "insufficient_lamport_for_tx": "Você não tem Sol suficiente para cobrir a transação e sua taxa de transação. Por favor, adicione mais sol à sua carteira ou reduza a quantidade de sol que você envia.", @@ -477,6 +479,7 @@ "onramper_option_description": "Compre rapidamente criptografia com muitos métodos de pagamento. Disponível na maioria dos países. Os spreads e taxas variam.", "opcionalmente_order_card": "Opcionalmente, peça um cartão físico.", "open_gift_card": "Abrir vale-presente", + "open_wallet": "Carteira aberta", "optional_description": "Descrição opcional", "optional_email_hint": "E-mail opcional de notificação do beneficiário", "optional_name": "Nome do destinatário opcional", @@ -627,6 +630,7 @@ "seed_alert_title": "Atenção", "seed_alert_yes": "Sim, eu tenho", "seed_choose": "Escolha o idioma da semente", + "seed_display_path": "Menu -> Segurança e Backup -> Mostrar chave/sementes", "seed_hex_form": "Semente de carteira (forma hexadecimal)", "seed_key": "Chave de semente", "seed_language": "Linguagem de semente", @@ -645,9 +649,13 @@ "seed_language_russian": "Russa", "seed_language_spanish": "Espanhola", "seed_phrase_length": "Comprimento da frase-semente", + "seed_position_question_one": "Qual é o", + "seed_position_question_two": "Palavra da sua frase de semente?", "seed_reminder": "Anote-os para o caso de perder ou limpar seu telefone", "seed_share": "Compartilhar semente", "seed_title": "Semente", + "seed_verified": "Semente verificada", + "seed_verified_subtext": "Você pode usar sua semente salva mais tarde para restaurar esta carteira em caso de corrupção ou perda do seu dispositivo. \n\n Você pode ver essa semente novamente do", "seedtype": "SeedType", "seedtype_alert_content": "Compartilhar sementes com outras carteiras só é possível com o BIP39 SeedType.", "seedtype_alert_title": "Alerta de SeedType", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", "verification": "Verificação", "verify_message": "Verifique a mensagem", + "verify_seed": "Verifique a semente", "verify_with_2fa": "Verificar com Cake 2FA", "version": "Versão ${currentVersion}", "view_all": "Ver todos", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 8993f6b29..d9468f148 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -366,6 +366,8 @@ "in_store": "В магазине", "incoming": "Входящие", "incorrect_seed": "Введённый текст некорректный.", + "incorrect_seed_option": "Неверный. Пожалуйста, попробуйте еще раз", + "incorrect_seed_option_back": "Неверный. Пожалуйста, убедитесь, что ваше семя сохранено правильно, и попробуйте еще раз.", "inputs": "Входы", "insufficient_funds_for_tx": "Недостаточно средств для успешного выполнения транзакции.", "insufficient_lamport_for_tx": "У вас недостаточно Sol, чтобы покрыть транзакцию и плату за транзакцию. Пожалуйста, добавьте больше Sol в свой кошелек или уменьшите сумму Sol, которую вы отправляете.", @@ -475,6 +477,7 @@ "online": "Онлайн", "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", "open_gift_card": "Открыть подарочную карту", + "open_wallet": "Открытый кошелек", "optional_description": "Дополнительное описание", "optional_email_hint": "Необязательное электронное письмо с уведомлением получателя платежа", "optional_name": "Необязательное имя получателя", @@ -626,6 +629,7 @@ "seed_alert_title": "Внимание", "seed_alert_yes": "Да", "seed_choose": "Выберите язык мнемонической фразы", + "seed_display_path": "Меню -> Безопасность и резервное копирование -> Показать ключ/семена", "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)", "seed_key": "Ключ семян", "seed_language": "Язык семян", @@ -644,9 +648,13 @@ "seed_language_russian": "Русский", "seed_language_spanish": "Испанский", "seed_phrase_length": "Длина исходной фразы", + "seed_position_question_one": "Что такое", + "seed_position_question_two": "Слово вашей семенной фразы?", "seed_reminder": "Пожалуйста, запишите мнемоническую фразу на случай потери или очистки телефона", "seed_share": "Поделиться мнемонической фразой", "seed_title": "Мнемоническая фраза", + "seed_verified": "Семя проверено", + "seed_verified_subtext": "Позже вы можете использовать сохраненное семя, чтобы восстановить этот кошелек в случае коррупции или потери вашего устройства. \n\n Вы можете снова просмотреть это семя из", "seedtype": "SEEDTYPE", "seedtype_alert_content": "Обмен семенами с другими кошельками возможно только с BIP39 SeedType.", "seedtype_alert_title": "SEEDTYPE ALERT", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", "verification": "Проверка", "verify_message": "Проверьте сообщение", + "verify_seed": "Проверьте семя", "verify_with_2fa": "Подтвердить с помощью Cake 2FA", "version": "Версия ${currentVersion}", "view_all": "Просмотреть все", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 7db703fc2..649d59d59 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -366,6 +366,8 @@ "in_store": "ในร้าน", "incoming": "ขาเข้า", "incorrect_seed": "ข้อความที่ป้อนไม่ถูกต้อง", + "incorrect_seed_option": "ไม่ถูกต้อง. โปรดลองอีกครั้ง", + "incorrect_seed_option_back": "ไม่ถูกต้อง. โปรดตรวจสอบให้แน่ใจว่าเมล็ดพันธุ์ของคุณได้รับการบันทึกอย่างถูกต้องและลองอีกครั้ง", "inputs": "อินพุต", "insufficient_funds_for_tx": "เงินทุนไม่เพียงพอที่จะดำเนินการทำธุรกรรมได้สำเร็จ", "insufficient_lamport_for_tx": "คุณไม่มีโซลเพียงพอที่จะครอบคลุมการทำธุรกรรมและค่าธรรมเนียมการทำธุรกรรม กรุณาเพิ่มโซลให้มากขึ้นลงในกระเป๋าเงินของคุณหรือลดจำนวนโซลที่คุณส่งมา", @@ -475,6 +477,7 @@ "online": "ออนไลน์", "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", "open_gift_card": "เปิดบัตรของขวัญ", + "open_wallet": "กระเป๋าสตางค์เปิด", "optional_description": "คำอธิบายเพิ่มเติม", "optional_email_hint": "อีเมลแจ้งผู้รับเงินเพิ่มเติม", "optional_name": "ชื่อผู้รับเพิ่มเติม", @@ -625,6 +628,7 @@ "seed_alert_title": "ความสนใจ", "seed_alert_yes": "ใช่ ฉันได้เขียน", "seed_choose": "เลือกภาษาของ seed", + "seed_display_path": "เมนู -> ความปลอดภัยและการสำรองข้อมูล -> แสดงคีย์/เมล็ดพันธุ์", "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)", "seed_key": "คีย์เมล็ดพันธุ์", "seed_language": "ภาษาเมล็ด", @@ -643,9 +647,13 @@ "seed_language_russian": "รัสเซีย", "seed_language_spanish": "สเปน", "seed_phrase_length": "ความยาววลีของเมล็ด", + "seed_position_question_one": "ไฟล์", + "seed_position_question_two": "คำพูดของวลีเมล็ด?", "seed_reminder": "โปรดเขียนข้อมูลนี้ลงสมุดเพื่อความปลอดภัยหากคุณสูญเสียหรือล้างโทรศัพท์ของคุณ", "seed_share": "แบ่งปัน seed", "seed_title": "Seed", + "seed_verified": "ตรวจสอบเมล็ดพันธุ์", + "seed_verified_subtext": "คุณสามารถใช้เมล็ดพันธุ์ที่บันทึกไว้ในภายหลังเพื่อคืนค่ากระเป๋าเงินนี้ในกรณีที่เกิดการทุจริตหรือสูญเสียอุปกรณ์ของคุณ \n\n คุณสามารถดูเมล็ดพันธุ์นี้ได้อีกครั้งจากไฟล์", "seedtype": "เมล็ดพันธุ์", "seedtype_alert_content": "การแบ่งปันเมล็ดกับกระเป๋าเงินอื่น ๆ เป็นไปได้เฉพาะกับ bip39 seedtype", "seedtype_alert_title": "การแจ้งเตือน seedtype", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", "verification": "การตรวจสอบ", "verify_message": "ยืนยันข้อความ", + "verify_seed": "ตรวจสอบเมล็ดพันธุ์", "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", "version": "เวอร์ชัน ${currentVersion}", "view_all": "ดูทั้งหมด", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6945d088b..33b4d23d6 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -366,6 +366,8 @@ "in_store": "Nasa Stock", "incoming": "Papasok", "incorrect_seed": "Ang text na ipinasok ay hindi wasto.", + "incorrect_seed_option": "Maling. Mangyaring subukang muli", + "incorrect_seed_option_back": "Maling. Mangyaring tiyakin na ang iyong binhi ay nai -save nang tama at subukang muli.", "inputs": "Mga input", "insufficient_funds_for_tx": "Hindi sapat na pondo upang matagumpay na magsagawa ng transaksyon.", "insufficient_lamport_for_tx": "Wala kang sapat na SOL upang masakop ang transaksyon at ang bayad sa transaksyon nito. Mabuting magdagdag ng higit pa sa iyong pitaka o bawasan ang sol na halaga na iyong ipinapadala.", @@ -475,6 +477,7 @@ "online": "Online", "onramper_option_description": "Mabilis na bumili ng crypto na may maraming paraan ng pagbabayad. Available sa karamihan ng mga bansa. Iba-iba ang mga spread at fee.", "open_gift_card": "Buksan ang Gift Card", + "open_wallet": "Buksan ang pitaka", "optional_description": "Opsyonal na paglalarawan", "optional_email_hint": "Opsyonal na payee notification email", "optional_name": "Opsyonal na pangalan ng tatanggap", @@ -625,6 +628,7 @@ "seed_alert_title": "Attention", "seed_alert_yes": "Oo meron ako", "seed_choose": "Pumili ng seed language", + "seed_display_path": "Menu -> Seguridad at Pag -backup -> Ipakita ang mga susi/buto", "seed_hex_form": "Wallet seed (hex form)", "seed_key": "Seed key", "seed_language": "Wika ng seed", @@ -643,9 +647,13 @@ "seed_language_russian": "Russian", "seed_language_spanish": "Spanish", "seed_phrase_length": "Haba ng parirala ng seed", + "seed_position_question_one": "Ano ang", + "seed_position_question_two": "Salita ng iyong pariralang binhi?", "seed_reminder": "Mangyaring isulat ang mga ito kung sakaling mawala o mabura sa inyong telepono", "seed_share": "Ibahagi ang seed", "seed_title": "Seed", + "seed_verified": "Napatunayan ang binhi", + "seed_verified_subtext": "Maaari mong gamitin ang iyong nai -save na binhi sa ibang pagkakataon upang maibalik ang pitaka na ito kung sakaling may katiwalian o mawala ang iyong aparato.\n\nMaaari mong tingnan muli ang binhi na ito mula sa", "seedtype": "Seed type", "seedtype_alert_content": "Ang pagbabahagi ng mga buto sa iba pang mga pitaka ay posible lamang sa bip39 seedtype.", "seedtype_alert_title": "Alerto ng Seedtype", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling exchange", "verification": "Pag-verify", "verify_message": "I -verify ang mensahe", + "verify_seed": "I -verify ang binhi", "verify_with_2fa": "Mag-verify sa Cake 2FA", "version": "Bersyon ${currentVersion}", "view_all": "Tingnan lahat", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 51b0dd18d..7b27ded8a 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -366,6 +366,8 @@ "in_store": "Mağazada", "incoming": "Gelen", "incorrect_seed": "Girilen metin geçerli değil.", + "incorrect_seed_option": "Yanlış. Lütfen tekrar deneyin", + "incorrect_seed_option_back": "Yanlış. Lütfen tohumunuzun doğru bir şekilde kaydedildiğinden emin olun ve tekrar deneyin.", "inputs": "Girişler", "insufficient_funds_for_tx": "İşlemi başarıyla yürütmek için yeterli fon.", "insufficient_lamport_for_tx": "İşlemi ve işlem ücretini karşılamak için yeterli SOL'unuz yok. Lütfen cüzdanınıza daha fazla SOL ekleyin veya gönderdiğiniz sol miktarını azaltın.", @@ -475,6 +477,7 @@ "online": "Çevrimiçi", "onramper_option_description": "Birçok ödeme yöntemi ile hızlı bir şekilde kripto satın alın. Çoğu ülkede mevcuttur. Forma ve ücretler değişir.", "open_gift_card": "Hediye Kartını Aç", + "open_wallet": "Açık cüzdan", "optional_description": "İsteğe bağlı açıklama", "optional_email_hint": "İsteğe bağlı alacaklı bildirim e-postası", "optional_name": "İsteğe bağlı alıcı adı", @@ -625,6 +628,7 @@ "seed_alert_title": "Dikkat", "seed_alert_yes": "Evet yazdım", "seed_choose": "Tohum dilini seçin", + "seed_display_path": "Menü -> Güvenlik ve Yedekleme -> Anahtar/Tohumları Göster", "seed_hex_form": "Cüzdan tohumu (onaltılık form)", "seed_key": "Tohum", "seed_language": "Tohum dili", @@ -643,9 +647,13 @@ "seed_language_russian": "Rusça", "seed_language_spanish": "İspanyolca", "seed_phrase_length": "Çekirdek cümle uzunluğu", + "seed_position_question_one": "Nedir", + "seed_position_question_two": "Tohum ifadenizin kelimesi?", "seed_reminder": "Telefonunu kaybetmen veya silinmesi ihtimaline karşı lütfen bunları not et", "seed_share": "Tohumu paylaş", "seed_title": "Tohum", + "seed_verified": "Tohum doğrulandı", + "seed_verified_subtext": "Kaydedilen tohumunuzu daha sonra, yolsuzluk veya cihazınızı kaybetme durumunda bu cüzdanı geri yüklemek için kullanabilirsiniz. \n\n Bu tohumu tekrar görüntüleyebilirsiniz.", "seedtype": "Tohum", "seedtype_alert_content": "Tohumları diğer cüzdanlarla paylaşmak sadece BIP39 tohumu ile mümkündür.", "seedtype_alert_title": "SeedType uyarısı", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", "verification": "Doğrulama", "verify_message": "Mesajı Doğrula", + "verify_seed": "Tohumu doğrulamak", "verify_with_2fa": "Cake 2FA ile Doğrulayın", "version": "Sürüm ${currentVersion}", "view_all": "Hepsini göster", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f591a8e06..cdf169a5a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -366,6 +366,8 @@ "in_store": "У магазині", "incoming": "Вхідні", "incorrect_seed": "Введений текст невірний.", + "incorrect_seed_option": "Неправильно. Будь ласка, спробуйте ще раз", + "incorrect_seed_option_back": "Неправильно. Будь ласка, переконайтеся, що ваше насіння зберігається правильно і повторіть спробу.", "inputs": "Вхoди", "insufficient_funds_for_tx": "Недостатні кошти для успішного виконання транзакції.", "insufficient_lamport_for_tx": "У вас недостатньо SOL, щоб покрити транзакцію та її плату за трансакцію. Будь ласка, додайте до свого гаманця більше SOL або зменшіть суму, яку ви надсилаєте.", @@ -475,6 +477,7 @@ "online": "Онлайн", "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", "open_gift_card": "Відкрити подарункову картку", + "open_wallet": "Відкритий гаманець", "optional_description": "Додатковий опис", "optional_email_hint": "Додаткова електронна адреса для сповіщення одержувача", "optional_name": "Додаткове ім'я одержувача", @@ -626,6 +629,7 @@ "seed_alert_title": "Увага", "seed_alert_yes": "Так", "seed_choose": "Виберіть мову мнемонічної фрази", + "seed_display_path": "Меню -> Безпека та резервна копія -> Показати ключ/насіння", "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)", "seed_key": "Насіннєвий ключ", "seed_language": "Насіннєва мова", @@ -644,9 +648,13 @@ "seed_language_russian": "Російська", "seed_language_spanish": "Іспанська", "seed_phrase_length": "Довжина початкової фрази", + "seed_position_question_one": "Що таке", + "seed_position_question_two": "Слово вашої насіннєвої фрази?", "seed_reminder": "Будь ласка, запишіть мнемонічну фразу на випадок втрати або очищення телефону", "seed_share": "Поділитися мнемонічною фразою", "seed_title": "Мнемонічна фраза", + "seed_verified": "Насіння перевірено", + "seed_verified_subtext": "Пізніше ви можете скористатися збереженим насінням, щоб відновити цей гаманець у разі пошкодження або втрату пристрою. \n\n Ви можете переглянути це насіння ще раз з", "seedtype": "Насіннєвий тип", "seedtype_alert_content": "Спільний доступ до інших гаманців можливе лише за допомогою BIP39 Seedtype.", "seedtype_alert_title": "Попередження насінника", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", "verification": "Перевірка", "verify_message": "Перевірте повідомлення", + "verify_seed": "Перевірте насіння", "verify_with_2fa": "Перевірте за допомогою Cake 2FA", "version": "Версія ${currentVersion}", "view_all": "Переглянути все", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 372f875ea..5213cbaeb 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -366,6 +366,8 @@ "in_store": "اسٹور میں", "incoming": "آنے والا", "incorrect_seed": "درج کردہ متن درست نہیں ہے۔", + "incorrect_seed_option": "غلط براہ کرم دوبارہ کوشش کریں", + "incorrect_seed_option_back": "غلط براہ کرم یقینی بنائیں کہ آپ کا بیج صحیح طریقے سے محفوظ ہے اور دوبارہ کوشش کریں۔", "inputs": "آدانوں", "insufficient_funds_for_tx": "لین دین کو کامیابی کے ساتھ انجام دینے کے لئے ناکافی فنڈز۔", "insufficient_lamport_for_tx": "آپ کے پاس ٹرانزیکشن اور اس کے لین دین کی فیس کا احاطہ کرنے کے لئے کافی SOL نہیں ہے۔ برائے مہربانی اپنے بٹوے میں مزید سول شامل کریں یا آپ کو بھیجنے والی سول رقم کو کم کریں۔", @@ -475,6 +477,7 @@ "online": "آن لائن", "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", "open_gift_card": "گفٹ کارڈ کھولیں۔", + "open_wallet": "کھلا پرس", "openalias_alert_content": "آپ کو فنڈز بھیجیں گے\\n${recipient_name}", "openalias_alert_title": "پتہ کا پتہ چلا", "optional_description": "اختیاری تفصیل", @@ -627,6 +630,7 @@ "seed_alert_title": "توجہ", "seed_alert_yes": "ہاں میرے پاس ہے", "seed_choose": "بیج کی زبان کا انتخاب کریں۔", + "seed_display_path": "مینو -> سیکیورٹی اور بیک اپ -> کلیدی/بیج دکھائیں", "seed_hex_form": "پرس بیج (ہیکس فارم)", "seed_key": "بیج کی کلید", "seed_language": "بیج کی زبان", @@ -645,9 +649,13 @@ "seed_language_russian": "روسی", "seed_language_spanish": "ہسپانوی", "seed_phrase_length": "ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", + "seed_position_question_one": "کیا ہے؟", + "seed_position_question_two": "آپ کے بیج کے فقرے کا کلام؟", "seed_reminder": "اگر آپ اپنا فون کھو دیتے ہیں یا صاف کرتے ہیں تو براہ کرم یہ لکھ دیں۔", "seed_share": "بیج بانٹیں۔", "seed_title": "بیج", + "seed_verified": "بیج کی تصدیق", + "seed_verified_subtext": "آپ بدعنوانی یا اپنے آلے کو کھونے کی صورت میں اس پرس کو بحال کرنے کے لئے بعد میں اپنے محفوظ کردہ بیج کا استعمال کرسکتے ہیں۔ \n\n آپ اس بیج کو دوبارہ سے دیکھ سکتے ہیں", "seedtype": "سیڈ ٹائپ", "seedtype_alert_content": "دوسرے بٹوے کے ساتھ بیجوں کا اشتراک صرف BIP39 بیج ٹائپ کے ساتھ ہی ممکن ہے۔", "seedtype_alert_title": "سیڈ ٹائپ الرٹ", @@ -904,6 +912,7 @@ "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", "verification": "تصدیق", "verify_message": "پیغام کی تصدیق کریں", + "verify_seed": "بیج کی تصدیق کریں", "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", "version": "ورژن ${currentVersion}", "view_all": "سب دیکھیں", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 74cc9c3af..963c3002a 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -365,6 +365,8 @@ "in_store": "Tại cửa hàng", "incoming": "Đang nhận", "incorrect_seed": "Văn bản nhập không hợp lệ.", + "incorrect_seed_option": "Không đúng. Hãy thử lại", + "incorrect_seed_option_back": "Không đúng. Vui lòng đảm bảo hạt giống của bạn được lưu chính xác và thử lại.", "inputs": "Đầu vào", "insufficient_funds_for_tx": "Không đủ tiền để thực hiện thành công giao dịch.", "insufficient_lamport_for_tx": "Bạn không có đủ SOL để thanh toán giao dịch và phí giao dịch. Vui lòng thêm SOL vào ví của bạn hoặc giảm số lượng SOL bạn đang gửi.", @@ -474,6 +476,7 @@ "online": "Trực tuyến", "onramper_option_description": "Mua tiền điện tử nhanh chóng với nhiều phương thức thanh toán. Có sẵn ở hầu hết các quốc gia. Chênh lệch và phí thay đổi.", "open_gift_card": "Mở thẻ quà tặng", + "open_wallet": "Mở ví", "optional_description": "Mô tả tùy chọn", "optional_email_hint": "Email thông báo cho người nhận (tùy chọn)", "optional_name": "Tên người nhận (tùy chọn)", @@ -624,6 +627,7 @@ "seed_alert_title": "Chú ý", "seed_alert_yes": "Có, tôi đã ghi lại", "seed_choose": "Chọn ngôn ngữ hạt giống", + "seed_display_path": "Menu -> Bảo mật và Sao lưu -> Hiển thị khóa/Hạt giống", "seed_hex_form": "Hạt giống ví (dạng hex)", "seed_key": "Khóa hạt giống", "seed_language": "Ngôn ngữ hạt giống", @@ -642,9 +646,13 @@ "seed_language_russian": "Tiếng Nga", "seed_language_spanish": "Tiếng Tây Ban Nha", "seed_phrase_length": "Độ dài cụm từ hạt giống", + "seed_position_question_one": "Cái gì là gì", + "seed_position_question_two": "Lời của cụm từ hạt giống của bạn?", "seed_reminder": "Vui lòng ghi lại những điều này phòng khi bạn mất hoặc xóa điện thoại của mình", "seed_share": "Chia sẻ hạt giống", "seed_title": "Hạt giống", + "seed_verified": "Hạt giống được xác minh", + "seed_verified_subtext": "Bạn có thể sử dụng hạt giống đã lưu của mình sau này để khôi phục ví này trong trường hợp tham nhũng hoặc mất thiết bị của mình. \n\n Bạn có thể xem lại hạt giống này từ", "seedtype": "Loại hạt giống", "seedtype_alert_content": "Chia sẻ hạt giống với ví khác chỉ có thể với BIP39 SeedType.", "seedtype_alert_title": "Cảnh báo hạt giống", @@ -901,6 +909,7 @@ "variable_pair_not_supported": "Cặp biến này không được hỗ trợ với các sàn giao dịch đã chọn", "verification": "Xác minh", "verify_message": "Xác minh tin nhắn", + "verify_seed": "Xác minh hạt giống", "verify_with_2fa": "Xác minh với Cake 2FA", "version": "Phiên bản ${currentVersion}", "view_all": "Xem tất cả", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 4131d4211..dd9c16347 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -367,6 +367,8 @@ "in_store": "A níyí", "incoming": "Wọ́n tó ń bọ̀", "incorrect_seed": "Ọ̀rọ̀ tí a tẹ̀ kì í ṣe èyí.", + "incorrect_seed_option": "Ti ko tọ. Jọwọ gbiyanju lẹẹkansi", + "incorrect_seed_option_back": "Ti ko tọ. Jọwọ rii daju pe irugbin rẹ wa ni fipamọ ni deede ki o tun gbiyanju lẹẹkan si.", "inputs": "Igbewọle", "insufficient_funds_for_tx": "Awọn owo ti ko to lati ṣe idunadura ni ifijišẹ.", "insufficient_lamport_for_tx": "O ko ni sosi to lati bo idunadura ati idiyele iṣowo rẹ. Fi agbara kun Sol diẹ sii si apamọwọ rẹ tabi dinku sodo naa ti o \\ 'tun n firanṣẹ.", @@ -476,6 +478,7 @@ "online": "Lórí ayélujára", "onramper_option_description": "Ni kiakia Ra Crypto pẹlu ọpọlọpọ awọn ọna isanwo. Wa ni ọpọlọpọ awọn orilẹ-ede. Itankale ati awọn idiyele yatọ.", "open_gift_card": "Ṣí káàdí ìrajà t'á lò nínú irú kan ìtajà", + "open_wallet": "Ṣii apamọwọ", "optional_description": "Ṣeto ẹru iye", "optional_email_hint": "Ṣeto imọ-ẹrọ iye fun owo ti o gbọdọjọ", "optional_name": "Ṣeto orukọ ti o ni", @@ -626,6 +629,7 @@ "seed_alert_title": "Ẹ wo", "seed_alert_yes": "Mo ti kọ ọ́", "seed_choose": "Yan èdè hóró", + "seed_display_path": "Aṣayan -> Aabo ati afẹyinti -> Fiwe bọtini / Awọn irugbin", "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)", "seed_key": "Bọtini Ose", "seed_language": "Ewu ọmọ", @@ -644,9 +648,13 @@ "seed_language_russian": "Èdè Rọ́síà", "seed_language_spanish": "Èdè Sípéènì", "seed_phrase_length": "Gigun gbolohun irugbin", + "seed_position_question_one": "Kini awọn", + "seed_position_question_two": "Ọrọ ti gbolohun irubò rẹ?", "seed_reminder": "Ẹ jọ̀wọ́, kọ wọnyí sílẹ̀ k'ẹ́ tó pàdánù ẹ̀rọ ìbánisọ̀rọ̀ yín", "seed_share": "Pín hóró", "seed_title": "Hóró", + "seed_verified": "Irugbin ijẹrisi", + "seed_verified_subtext": "O le lo irugbin ti o fipamọ nigbamii lati mu apamọwọ yii pada sinu iṣẹlẹ ti ibajẹ tabi padanu ẹrọ rẹ. \n\n O le wo irugbin yii lẹẹkansi lati", "seedtype": "Irugbin-seetypu", "seedtype_alert_content": "Pinpin awọn irugbin pẹlu awọn gedo miiran ṣee ṣe pẹlu Bip39 irugbin.", "seedtype_alert_title": "Ṣajọpọ Seeytype", @@ -903,6 +911,7 @@ "variable_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", "verification": "Ìjẹ́rìísí", "verify_message": "Daju ifiranṣẹ", + "verify_seed": "Dajudaju irugbin", "verify_with_2fa": "Ṣeẹda pẹlu Cake 2FA", "version": "Àtúnse ${currentVersion}", "view_all": "Wo gbogbo nǹkan kan", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 797aee624..2d70c2325 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -366,6 +366,8 @@ "in_store": "店内", "incoming": "收到", "incorrect_seed": "输入的文字无效。", + "incorrect_seed_option": "不正确。请重试", + "incorrect_seed_option_back": "不正确。请确保您的种子可以正确保存,然后重试。", "inputs": "输入", "insufficient_funds_for_tx": "资金不足无法成功执行交易。", "insufficient_lamport_for_tx": "您没有足够的溶胶来支付交易及其交易费用。请在您的钱包中添加更多溶胶或减少您发送的溶胶量。", @@ -475,6 +477,7 @@ "online": "在线", "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", "open_gift_card": "打开礼品卡", + "open_wallet": "打开钱包", "optional_description": "可选说明", "optional_email_hint": "可选的收款人通知电子邮件", "optional_name": "可选收件人姓名", @@ -625,6 +628,7 @@ "seed_alert_title": "注意", "seed_alert_yes": "确定", "seed_choose": "选择种子语言", + "seed_display_path": "菜单 - >安全性和备份 - >显示键/种子", "seed_hex_form": "钱包种子(十六进制形式)", "seed_key": "种子钥匙", "seed_language": "种子语言", @@ -643,9 +647,13 @@ "seed_language_russian": "俄文", "seed_language_spanish": "西班牙文", "seed_phrase_length": "种子短语长度", + "seed_position_question_one": "什么是", + "seed_position_question_two": "你的种子短语的话?", "seed_reminder": "请记下这些内容,以防丟失或数据损坏", "seed_share": "分享种子", "seed_title": "种子", + "seed_verified": "种子经过验证", + "seed_verified_subtext": "您可以在以后使用保存的种子在发生损坏或丢失设备的情况下还原该钱包。\n\n您可以从", "seedtype": "籽粒", "seedtype_alert_content": "只有BIP39籽粒可以与其他钱包共享种子。", "seedtype_alert_title": "籽粒警报", @@ -902,6 +910,7 @@ "variable_pair_not_supported": "所选交易所不支持此变量对", "verification": "验证", "verify_message": "验证消息", + "verify_seed": "验证种子", "verify_with_2fa": "用 Cake 2FA 验证", "version": "版本 ${currentVersion}", "view_all": "查看全部",